RAM에 로드된 프로세스에 의해 파일이 열립니까?

RAM에 로드된 프로세스에 의해 파일이 열립니까?

명령예를 들어 sed, 프로그램은 파일 내부의 코드화된 논리이며 이러한 파일은 하드 디스크 어딘가에 있습니다. 그러나 명령이 실행되는 동안에는 해당 파일의 복사본이하드 디스크에 넣어집니다, 그들이 살아나서 일을 할 수 있고 부름을 받는 곳프로세스.

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

좋아, 그래서 내가 궁금한 것은 명령의 이중 수명(하나는 하드 디스크에 있고 다른 하나는 RAM에 있음)이 다른 종류의 파일에도 적용되는지입니다. 예를 들어 논리가 프로그래밍되지 않았지만 단순히 컨테이너에 불과한 파일입니다. 데이터.

내 가정은 프로세스에 의해 열린 파일도 RAM에 로드된다는 것입니다. 그것이 사실인지는 모르겠지만 단지 직감일 뿐입니다.

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

답변1

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

그것 과 awk동일합니다. 그것은 읽습니다기록기본적으로 한 줄입니다. 입력 데이터의 일부를 변수에 저장하면 당연히 1 이 추가됩니다 .

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

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

쉘은 루프 $(cat file)의 첫 번째 반복을 실행하기 전에 명령 대체를 완전히 확장해야 하기 때문에for~ 할 것이다전체를 file메모리(루프를 실행하는 쉘이 사용하는 메모리 for)로 읽습니다. 이것은 약간 어리석고 우아하지도 않습니다. 대신에 해야 할 일은

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

이것은 file한 줄씩 처리됩니다 (그러나 읽으십시오"IFS= 읽기 -r 라인" 이해).

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

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

다음과 같은 파일 형식을 사용하더라도~ 아니다JSON이나 XML과 같은 라인 지향에는 RAM에 모두 저장하지 않고도 대용량 파일을 처리할 수 있게 해주는 스트림 파서가 있습니다.

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

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


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

답변2

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

이것은 (일반적으로) 잘못된 것입니다. 프로그램이 실행될 때(execve(2)...) (해당 프로그램을 실행하는) 프로세스가 해당 프로그램을 변경하고 있습니다.가상 주소 공간커널이 재구성 중입니다.MMU그 목적을 위해. 다음 사항에 대해서도 읽어보세요.가상 메모리. 응용 프로그램은 다음을 사용하여 가상 주소 공간을 변경할 수 있습니다.mmap(2)& munmap&m보호(2), 에서도 사용됩니다.동적 링커(보다ld-리눅스(8)). 또한보십시오미치광이(2)&posix_fadvise(2)&mlock(2).

미래페이지 오류실행 파일에서 (지연) 페이지를 로드하기 위해 커널에 의해 처리됩니다. 다음 사항에 대해서도 읽어보세요.대패.

커널은 큰 크기를 유지합니다.페이지 캐시. 다음 사항에 대해서도 읽어보세요.기록 중 복사. 또한보십시오미리 읽기(2).

좋아, 그래서 내가 궁금한 것은 명령의 이중 수명(하나는 하드 디스크에 있고 다른 하나는 RAM에 있음)이 다른 종류의 파일에도 적용되는지입니다. 예를 들어 논리가 프로그래밍되지 않았지만 단순히 컨테이너에 불과한 파일입니다. 데이터.

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

와 같은 책을 읽는 것을 추천합니다운영 체제: 세 가지 쉬운 부분(무료로 다운로드 가능, 장당 하나의 PDF 파일) 이 모든 것을 설명합니다.

또한보십시오리눅스가 내 RAM을 먹었습니다xosview, 또는 또는 같은 명령을 실행합니다 (참조 top:htopcat /proc/self/mapscat /proc/$$/maps프로세스(5)).

추신. 저는 Linux에 집중하고 있지만 다른 OS에도 가상 메모리와 페이지 캐시가 있습니다.

답변3

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

관련 정보