프로세스가 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=read-r-line" 이해).

그러나 대부분의 유틸리티는 라인 지향적이므로 쉘에서 파일을 한 줄씩 처리할 필요가 거의 없습니다(참조:쉘 루프를 사용하여 텍스트를 처리하는 것이 왜 나쁜 습관으로 간주됩니까?).

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

파일 형식임에도 불구하고아니요JSON이나 XML과 같은 라인 기반에는 대용량 파일을 모두 RAM에 저장하지 않고도 처리할 수 있는 스트리밍 파서가 있습니다.

실행 파일의 경우 공유 라이브러리를 요청 시 로드하거나 프로세스 간에 공유할 수 있으므로 상황은 약간 더 복잡합니다(참조:공유 라이브러리 로딩 및 RAM 사용량, 예를 들어).

캐싱은 여기서 언급하지 않은 것입니다. 이는 자주 액세스되는 데이터 블록을 보관하기 위해 RAM을 사용하는 것입니다. 실행 파일과 같은 작은 파일은 사용자가 여러 번 참조할 수 있기를 바라면서 운영 체제에 의해 캐시될 수 있습니다. 파일을 처음 읽을 때를 제외하고 후속 액세스는 디스크가 아닌 RAM에 수행됩니다. 캐싱(예: 입력 및 출력 버퍼링)은 일반적으로 사용자에게 거의 투명하며 콘텐츠를 캐시하는 데 사용되는 메모리 양은 예를 들어 애플리케이션에서 할당한 RAM 양에 따라 동적으로 변경될 수 있습니다.


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

답변2

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

이는 잘못된 것입니다(일반적으로 말하면). 프로그램이 실행될 때 (를 통해실행(2)...) 프로세스(프로그램 실행)가 변경 중입니다.가상 주소 공간커널이 재구성 중입니다메모리 관리 유닛이 목적을 위해. 다음 내용도 읽어보세요.가상 메모리. 애플리케이션은 다음을 사용하여 가상 주소 공간을 변경할 수 있습니다.매핑(2)munmap&&보호(2), 또한 사용됨동적 링커(바라보다ld-리눅스(8)). 당신은 또한 볼 수 있습니다미친 웨스(2)&posix_fadvise(2)&시계 잠금(2).

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

커널은 큰 크기를 유지합니다.페이지 캐시. 다음 내용도 읽어보세요.쓰기 중 복사. 당신은 또한 볼 수 있습니다미리 읽기(2).

좋습니다. 제가 궁금한 점은 명령의 이중 수명(하나는 하드 드라이브에 있고 다른 하나는 RAM에 있음)이 로직이 프로그래밍되어 있지 않지만 단지 컨테이너인 파일과 같은 다른 유형의 파일에도 작동하는지 여부입니다. 데이터.

~을 위한시스템 호출좋다독서(2)&쓰기(2)또한 페이지 캐싱을 사용합니다. 읽을 데이터가 그 안에 있으면 디스크 IO가 수행되지 않습니다. 디스크 IO가 필요한 경우 읽은 데이터는 페이지 캐시에 저장될 가능성이 높습니다. 따라서 실제로 동일한 명령을 두 번 실행하면 두 번째에는 디스크에 대한 물리적 I/O가 수행되지 않을 수 있습니다(SSD가 아닌 오래된 회전 하드 드라이브가 있는 경우). 또는 하드 드라이브 LED를 자세히 살펴보십시오.)

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

당신은 또한 볼 수 있습니다리눅스가 RAM을 잡아먹는다xosview, 또는 같은 명령을 실행합니다 (참조 top:htopcat /proc/self/mapscat /proc/$$/maps공정(5)).

추신. 저는 주로 Linux에 집중하고 있지만 다른 운영 체제에는 가상 메모리와 페이지 캐시가 있습니다.

답변3

아니요. 요즘에는 기가바이트의 RAM을 갖는 것이 좋지만 RAM이 매우 제한된 리소스였던 때가 있었고(저는 2MB RAM이 있는 VAX 11/750에서 프로그래밍을 배웠습니다) RAM에 있는 유일한 것은 활성 실행 파일과 활성 파일 수뿐이었습니다. 버퍼 캐시의 데이터 페이지 및 파일 데이터에 대한 프로세스입니다.
버퍼 캐시가 플러시되고 데이터 페이지가 교체됩니다. 그리고 자주. 읽기 전용 실행 가능 페이지를 덮어쓰고 페이지 테이블을 표시하므로 프로그램이 이러한 페이지를 다시 터치하면 파일 시스템에서 페이지 인됩니다. 데이터는 스왑 영역에서 전송됩니다. 위에서 언급한 것처럼 STDIO 라이브러리는 데이터를 청크로 추출하고 필요에 따라 프로그램(fgetc, fgets, fread 등)에 의해 가져옵니다. mmap을 사용하면 공유 라이브러리 객체나 일반 파일을 사용하는 등 파일을 프로세스의 주소 공간에 매핑할 수 있습니다. 예, RAM에 있든 없든(mlock) 어느 정도 제어할 수 있지만 그게 전부입니다(mlock의 오류 코드 섹션 참조).

관련 정보