프로세스가 파일을 RAM에로드 했습니까?


24

예를 들어 sed, 명령 은 프로그램이며 프로그램은 파일 내부의 논리로 체계화되어 있으며 이러한 파일은 하드 디스크 어딘가에 있습니다. 그러나 명령이 실행되면 하드 디스크 에서 파일 사본이 RAM에 저장되어 실제 작업을 수행 할 수 있으며 프로세스 라고 합니다 .

프로세스는 다른 파일을 사용하거나 읽거나 쓸 수 있으며 이러한 파일을 수행하는 경우이를 열린 파일이라고합니다. 실행중인 모든 프로세스별로 열려있는 모든 파일을 나열하는 명령이 있습니다 lsof..

좋아, 내가 궁금해하는 것은 명령의 이중 수명, 하나는 하드 디스크에 있고 다른 하나는 RAM에 프로그래밍 된 논리가 없지만 단순히 컨테이너 인 파일과 같은 다른 종류의 파일에도 적용되는지 여부입니다. 데이터.

프로세스가 연 파일도 RAM에로드된다고 가정합니다. 그것이 사실인지 모르겠습니다. 직관 일뿐입니다.

제발, 누군가 이해할 수 있습니까?


답변:


27

그러나 명령이 실행되면 하드 디스크의 파일 사본이 RAM에 저장됩니다.

이것은 일반적으로 잘못되었습니다. 프로그램이 실행될 때 ( execve (2) ...) 프로세스 (해당 프로그램 실행)는 가상 주소 공간을 변경 하고 있으며 커널은이를 위해 MMU 를 재구성합니다 . 가상 메모리에 대해서도 읽어보십시오 . 응용 프로그램은 동적 링커 에서도 사용되는 mmap (2) & munmap& mprotect (2)를 사용하여 가상 주소 공간을 변경할 수 있습니다 ( ld-linux (8) 참조 ). madvise (2) & posix_fadvise (2) & mlock (2) 도 참조하십시오 .

향후 페이지 결함 은 커널이 처리 파일에서 페이지를 느리게로드하기 위해 처리합니다. 스 래싱에 대해서도 읽어보십시오 .

커널은 큰 페이지 캐시를 유지 합니다 . copy-on-write 도 읽어보십시오 . readahead (2) 도 참조하십시오 .

좋아, 내가 궁금해하는 것은 명령의 이중 수명, 하나는 하드 디스크에 있고 다른 하나는 RAM에 프로그래밍 된 논리가 없지만 단순히 컨테이너 인 파일과 같은 다른 종류의 파일에도 적용되는지 여부입니다. 데이터.

들어 시스템 호출 과 같은 읽기 (2)쓰기 (2) 페이지 캐시도 사용됩니다. 읽을 데이터가 그 안에 있으면 디스크 IO가 수행되지 않습니다. 디스크 IO가 필요한 경우 읽은 데이터가 페이지 캐시에 저장 될 가능성이 높습니다. 따라서 실제로 동일한 명령을 두 번 실행하면 두 번째로 디스크에 물리적 I / O가 수행되지 않을 수 있습니다 (SSD가 아닌 오래된 회전 하드 디스크가있는 경우). 또는 하드 디스크 LED를주의 깊게 관찰하십시오).

이 모든 것을 설명하는 Operating Systems : Three Easy Pieces (무료 다운로드, 장당 하나의 PDF 파일) 와 같은 책을 읽는 것이 좋습니다 .

Linux Ate My RAM을 참조 xosview하고 top, htop또는 cat /proc/self/maps또는 같은 명령을 실행 cat /proc/$$/maps하십시오 ( proc (5) 참조 ).

추신. Linux에 중점을두고 있지만 다른 OS에도 가상 메모리와 페이지 캐시가 있습니다.


35

아니요, 파일을 열어 메모리에 파일을 자동으로 읽지 않습니다. 그것은 끔찍하게 비효율적입니다. sed예를 들어 다른 많은 유닉스 도구와 마찬가지로 입력을 한 줄씩 읽습니다. 메모리에 현재 행보다 많은 것을 유지해야하는 경우는 거의 없습니다.

awk그 동일합니다. 한 번에 레코드 를 읽습니다 . 기본적으로 한 줄입니다. 입력 데이터의 일부를 변수에 저장하면 물론 추가됩니다 1 .

어떤 사람들은 다음과 같은 일을하는 습관이 있습니다

for line in $(cat file); do ...; done

쉘 확장해야하므로 $(cat file)의 심지어 첫번째 반복 실행하기 전에 완전히 명령어 치환 for루프 이는 전체를 판독 file(실행중인 쉘에 의해 사용되는 메모리로 메모리에 for루프). 이것은 약간 어리 석고 우아하지 않습니다. 대신,해야 할 일

while IFS= read -r line; do ...; done <file

이렇게하면 file한 줄씩 처리 됩니다 ( "IFS = read -r line"이해 참조).

어쨌든 대부분의 유틸리티는 줄 지향적이므로 쉘에서 한 줄씩 파일을 처리하는 것은 거의 필요하지 않습니다 ( 쉘 루프를 사용하여 텍스트를 나쁜 습관으로 간주하는 이유는 무엇입니까? 참조 ).

나는 생물 정보학에서 일하고 있으며 대량의 게놈 데이터를 처리 할 때 절대적으로 필요한 데이터를 메모리에 보관하지 않으면 많은 것을 할 수 없습니다. 예를 들어, VCF 파일에 DNA 변형이 포함 된 1 테라 바이트 데이터 세트에서 개인을 식별하는 데 사용할 수있는 데이터 비트를 제거해야하는 경우 (데이터 유형을 공개 할 수 없기 때문에) 한 줄씩 간단한 awk프로그램으로 처리 (VCF 형식은 라인 지향적이므로 가능합니다). 나는 하지 않는 메모리로 파일을 읽을 그것을 거기를 처리하고 다시 밖으로 다시 쓰기! 파일이 압축 된 경우, 나는 그것을 통해 공급 것 zcat또는 gzip -d -c이후하는, gzip데이터 스트림 처리를 수행, 또한 메모리에 전체 파일을 읽을 것이다.

JSON 또는 XML과 같이 라인 지향 이 아닌 파일 형식의 경우에도 파일을 모두 RAM에 저장하지 않고도 대용량 파일을 처리 할 수있는 스트림 파서가 있습니다.

실행 파일을 사용하면 공유 라이브러리가 요청시로드되거나 프로세스간에 공유 될 수 있으므로 약간 더 복잡합니다 ( 예 : 공유 라이브러리로드 및 RAM 사용량 참조 ).

캐싱은 여기서 언급하지 않은 것입니다. RAM을 사용하여 자주 액세스하는 데이터를 보관하는 작업입니다. 더 작은 파일 (예 : 실행 파일)은 사용자가 많은 참조를 할 수 있도록 OS에서 캐시 할 수 있습니다. 파일을 처음 읽은 것 외에도 디스크가 아닌 RAM에 대한 후속 액세스가 이루어집니다. 입력 및 출력의 버퍼링과 같은 캐싱은 일반적으로 사용자에게 크게 투명하며 사물을 캐시하는 데 사용되는 메모리의 양은 응용 프로그램 등에 의해 할당 된 RAM의 양에 따라 동적으로 변경 될 수 있습니다.


1 기술적으로 대부분의 프로그램은 명시 적 버퍼링을 사용하거나 표준 I / O 라이브러리가 수행하는 버퍼링을 통해 암시 적으로 한 번에 입력 데이터 청크를 읽은 다음 해당 청크를 한 줄씩 사용자 코드에 표시합니다. 한 번에 한 문자보다 여러 개의 디스크 블록 크기를 읽는 것이 훨씬 더 효율적입니다. 이 청크 크기는 소수 킬로바이트보다 크지 않습니다.


공유 라이브러리를 RAM에로드 할 수 있으며 데이터가 포함 된 일반 파일을 RAM에로드 할 수도 있습니까?
상어

1
@sharkant 물론입니다. 그것은 모든 파일이 저장 될 때까지 변수 (또는 배열 또는 해시 또는 문제가있는 언어의 모든 데이터 구조)에 데이터를 추가하는 것입니다. 으로는 awk, { a[i++] = $0 }배열에 입력 파일의 모든 행을 추가합니다 a. C 함수를 찾아보고 싶을 수도 mmap()있지만 여기서는 주제가 약간 벗어납니다.
Kusalananda

6
sed, awk, 일반적으로 (512 일반 텍스트 파일은 라인 인덱스를 포함하지 않기 때문에 다른 라인 지향 프로그램은 메모리에 한 번에 한 줄을 읽어하지 않으며, 파일 시스템 API와 낮은 수준의 스토리지 하드웨어는 하나 이상의 "분야"를 읽고 또는 한 번에 1024 바이트). 첫 번째 줄이 처리되기 전에 OS에서 8KB 미만의 메모리를 읽은 경우 놀랍습니다.
Russell Borogove

5
같은 유틸리티 sed는 한 번에 한 줄씩 메모리로 읽지 만 운영 체제는 여유 램을 사용하여 파일을 캐시하므로 파일에 빠르게 액세스 할 수 있습니다. sed더 작은 파일에서 실행중인 경우 OS가 전체 파일을 메모리에 캐시하고 작업은 완전히 RAM으로 수행됩니다. 참조 : en.wikipedia.org/wiki/Page_cache
Sean Dawson

5
@sharkant 파일을 메모리에서 완전히 액세스 할 수 있습니다 (다른 대답을 참조하십시오. mmap은 키워드 시스템 호출입니다). 예를 들어, 데이터베이스 시스템은 일반적으로 전체 데이터베이스 또는 메모리에 매핑 된 적어도 일부 인덱스를 쉽고 빠르게 액세스하기를 원할 것입니다. 이것이 반드시 모든 것이 실제로 메모리에 있다는 것을 의미하지는 않습니다. OS는 파일이 메모리에있는 것으로 가장합니다. 응용 프로그램에 "여기,이 범위의 메모리는 파일입니다."라고 말하고 프로세스가 스왑 아웃 될 때와 같이 읽기가 완료되면 데이터는 실제로 읽 힙니다.
Jonas Schäfer

5

아니요. 요즘에는 RAM이 많은 것이 환상적이지만 RAM이 매우 제한된 리소스 (2MB의 RAM이있는 VAX 11/750에서 프로그래밍을 배웠 음)가 있었고 RAM의 유일한 것은 실행 가능한 실행 파일과 데이터 페이지였습니다 활성 프로세스 및 버퍼 캐시에 있던 파일 데이터
버퍼 캐시가 플러시되고 데이터 페이지가 스왑되었습니다. 그리고 종종 자주. 프로그램이 해당 페이지를 다시 터치하면 파일 시스템에서 페이징 된 읽기 전용 실행 가능 페이지를 덮어 쓰고 페이지 테이블을 표시했습니다. 스왑에서 데이터가 페이징되었습니다. 위에서 언급했듯이 STDIO 라이브러리는 블록 단위로 데이터를 가져 와서 fgetc, fgets, fread 등 필요한 프로그램에 의해 확보되었습니다. mmap을 사용하면 파일을 프로세스의 주소 공간에 매핑 할 수 있습니다. 공유 라이브러리 객체 또는 일반 파일. 예, RAM에 있는지 (mlock) 아니면 어느 정도 제어 할 수 있지만 지금까지만 진행됩니다 (mlock의 오류 코드 섹션 참조).


1
VAX 시절과 마찬가지로 "RAM이 파일에 비해 너무 작습니다"라는 문구가 적용됩니다.
Federico Poloni

1
@Federico_Poloni 오늘은 사실이 아닙니다. 마지막 고용주는 1Tb RAM과 0.5Tb 하드 디스크를 갖춘 워크 스테이션 급 PC를 사용했습니다. (문제 등급 : 계산 중 작은 입력, 중간 출력, 큰 랜덤 액세스 배열)
nigel222
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.