issues
search
prgrms-web-devcourse
/
BE-Team-preArmand-Book-study
2
stars
2
forks
source link
실습과 그림으로 배우는 리눅스 구조 5장(~162)
#58
Open
epicblues
opened
1 year ago
epicblues
commented
1 year ago
고수준 레벨에서의 메모리 할당
mmap()
시스템 콜
커널로부터 요청한 크기만큼 메모리를 할당 받고, 해당 주소를 사용
페이지 단위 메모리 확보
malloc()
바이트 단위 메모리 확보
OS가 제공하는 사용자 모드에서 실행되는 함수(glibc)
시스템 콜 아님
mmap()
으로 미리 운영 체제로부터 받은 메모리를 보관
malloc() 호출 시 해당 메모리를 할당한다(커널 X)
부족할 경우 mmap() 다시 호출
운영체제 입장에서의 프로세스 메모리 사용량 ≠ 프로세스 입장에서 메모리 사용량
프로세스 입장에서는
mmap()
으로 미리 호출된 메모리 공간을 알 수 없음
파일 맵
물리 메모리로 올라올 파일과 가상 메모리를 매핑
mmap()
으로 수행
파일 읽기/쓰기 시스템 콜 없이, 프로세스의 메모리 제어 코드 만으로 파일을 읽고 쓸 수 있음
memcpy()
메모리 write 코드로 변경된 내역이 실제 파일에 적용될 때까지는 시간이 걸림
디멘드 페이징
프로세스가 가상 메모리를 할당받았다고 바로 페이징 테이블에 물리 메모리가 매핑되는 것은 아님
프로세스가 할당된 메모리에
처음
접근할 때 페이지 폴트가 발생하고, 커널의 페이지 폴트 핸들러에서 실제 물리 메모리 주소를 확보하고 페이징 테이블에 매핑
페이지 폴트의 종류(?)
가상 메모리를 할당받지 못한 경우 → 프로세스 종료
가상 메모리는 할당 받았으나, 물리 메모리를 할당받지 못한 경우 → 물리 메모리 할당
mmap()
가상 메모리 확보
물리 메모리 확보 X
HunkiKim
commented
1 year ago
5장
고수준 레벨에서의 메모리 할당
실제 메모리 할당은 malloc()은 mmap()을 호출해 구현되고 있다.
c언어는 사용자 프로그램에서 glibc에 메모리풀을 할당받아 쓴다.
파이썬 같이 직접 메모리를 관리하지 않는 스크립트 언어의 오브젝트 생성도 결국 glibc를 이용한거다.
더 궁금하면 파이썬 스크립트를 strace로 추적해보자
해결법
메모리 단편화 문제
페이지 테이블을 잘 설정하면 물리 메모리의 단편화되어 있는 영역을 프로세스의 가상 공간에선 하나의 큰 영역처럼 보이게 할 수 있다.
즉 가상주소 0~300을 100씩 물리주소를 여러곳에서 할당받아 사용하는 방식이다.
프로세스의 페이지 테이블을 잘 설정하면 된다.
다른 용도의 메모리에 접근 가능한 문제
가상 주소 공간은 프로세스별로 만들어지며, 페이지 테이블도 프로세스별로 만들어진다. (커널 메모리에)
따라서 A,B가 독립적인 가상 주소 공간을 갖는다.
그렇게되면 다른 프로세스는 가상 주소공간만 참조하기 떄문에 다른 물리메모리는 참조할 수 없다.
여러 프로세스를 다루기 곤란한 문제
가상 주소 공간은 프로세스마다 존재하기 때문에 다른 프로그램과 주소 겹칠 걱정은 안해도 된다.
가상 메모리의 응용
파일 맵
디맨드 페이징
Copy on Write 방식의 고속 프로세스 생성
스왑
계층형 페이지 테이블
Huge page
파일 맵
일반적으로 프로세스가 파일에 접근할 떄는 파일을 연 뒤에
read()
, 'write()
,
lseek()` 등의 시스템 콜을 사용한다.
뿐만 아니라 리눅스엔 파일의 영역을 가상 주소 공간에 메모리 매핑하는 기능이 있다.
즉 가상 주소 공간에 프로세스의 메모리와 파일의 복사본을 매핑해 메모리 접근과 같은 방식으로 접근 가능하다. 이후 나중에 적절한 타이밍에 저장 장치 내의 파일이 써진다.
디맨드 페이징
앞에서 프로세스가 생성될 때 혹은 그 뒤에 mmap() 시스템 콜로 프로세스에 메모리를 할당했을 때 아래와 같은 순서로 진행된다고 함
커널이 필요한 영역을 메모리에 확보
커널이 페이지 테이블을 설정해 가상 주소 공간을 물리 주소 공간에 매핑
하지만 위의 방법은 메모리를 낭비하는 단점이 있다.
메모리를 확보하고 종료할때 까지 안쓰는 메모리가 확보되어있기 때문이다.
커다란 프로그램 중 실행에 사용하지 않는 기능을 위한 코드 영역 및 데이터 영역
glibc가 확보한 메모리 맵 중 유저가 malloc() 함수로 확보하지 않은 부분
리눅스는 위의 문제를 해결하기 위해 디멘드 페이징 (요구 페이징)방식을 사용해 메모리를 프로세스에 할당
쉽게 말하면 가상 메모리만 할당해놓고 물리메모리는 사용하기 전까지 할당하지 않는 것이다.
사용할때 할당해 가성비있게 쓰자
mmap()으로 할당하면 물리메모리는 할당되지 않고, 실제 사용할때 할당
한 번 할당되면 이후론 페이지 폴트가 발생하지 않는다. (이미 이전에 물리메모리 할당 됐기 때문)
가상 메모리 부족
예전 32bit시절엔 4기가 까지 표현할 수 없어 발생했지만 64bit인 요즘은 128TB까지 표현되기때문에 부족할일이 거의 없다.
고수준 레벨에서의 메모리 할당
mmap()
시스템 콜malloc()
mmap()
으로 미리 운영 체제로부터 받은 메모리를 보관mmap()
으로 미리 호출된 메모리 공간을 알 수 없음파일 맵
mmap()
으로 수행memcpy()
디멘드 페이징
처음
접근할 때 페이지 폴트가 발생하고, 커널의 페이지 폴트 핸들러에서 실제 물리 메모리 주소를 확보하고 페이징 테이블에 매핑mmap()