...
user access memory...
에서 어느 부분을 검사하는 거냐
라고 해서
rip를 다 찍어보셨다고...해서
분명 프로세스별 유저 스택이 있을 건데
커널 스택 외의 유저 스택은 전부 유효하다고 하는 게
아무리 매핑이 되어있다고 해도 OS 적으로는 말도안되는 처리인데
(여러개의 유저프로그램을 돌린다고 생각하면.)
왜 이렇게 하는지...에 관해
아마 실제적으로는 그런 구분이 있는게 당연하지만
아주 단순하게 이 PintOS는 유저프로그램을 하나만 돌리는 상황을 상정하고있어서
가장 중요한.. 커널 스택과 유저 스택만 구분하는 거같다...
그리고 main에서 load 단계의
rip는 아직 load 단계라면 단순한 포인터고
그 포인터가 addr을 가지고 있는 건데
load 전까지는 사용자가 침범할 겨를이 없고
사용자 프로그램 내에서 시스템 콜을 호출하는 그 시점
포인터가 이상하여 protection을 침범하는 걸 방지해야하는거니까
시스템콜 핸들러로 넘어온 시점의 rip의 addr을
검사하는게 좋을거같다는 얘기를 함.
...
이후에 어차피 addr을 체크할수는 없어서
깃북에 있는 systemcall 부분 정독하고
강의의 systemcall 부분도 다 들은 다음
티타임 다녀오고?
아무튼 그거 다 들었고?
저녁먹고?
채용설명회 듣고?
티타임과 채용설명회 정리하고.
화이트보드에 여태 내용 총정리함.
(사실 반복적인 내용도 많고 해서 할까말까하다가
그냥 하긴 했음 왜냐하면 아무리 함수끼리 따로 논다고해도
이 함수는 뭐였지<하고 헤매기보다는
하나의 청사진이 갖고 싶긴 해서.)




정리만 두시간걸렸다 나도울고싶다
그래도 이제 알았다
내가 모르는게 많다는것을........
어제 알고리즘 또 안풀었음
1시 반 ~ 3시 반 OS 강의
오, 내일은 토요일.
흠 fd table 만들때
thread안에 정적 배열로 만들면
그걸 밖에서 참조할때는 포인터로 참조해서
값을 넣으면 된다는걸 질문 답하면서 알게됨(사실 몰랐음)
알고리즘이나 풀고 내려가자
(못풀었음)
OS 강의.
OS 강의 정리.
알고리즘 풀기.
총정리하면서 궁금했던 거 찾아보기.
? pid와 tid의 차이는?
? pid 구조는 뭘로 정의되어있지?
: process 식별자와 thread 식별자. 둘다 int 형.
별개로 off_t는 map region 식별자, int형.
fd는 그냥 int 형으로 받음.
? pid로 process exit status를 검색한다는건 무슨 의미?
? process exit status가 대체 뭐지?
: exit status는 그냥 성공, 실패시 0, 0외의 값등을 반환하는 것을 말함.
아마 pid로 탐색을 한다면 성공 실패 여부인 값을 받아올 수는 있어야한다는 얘기인 것 같음.
? child_tid로 process_wait 단계에서 child process descriptor를 찾는다는게 뭐지?(tid가 쓰레드 fd같은 거면 pid로 찾아야하는거아님?)
: process_wait가 child_tid라는 인자를 받음.
이론적으로는 thread는 프로세스 안에 있어서, 하나의 PID를 공유하고 있기때문에 찾을 수 있다지만 관련 함수가 어디 있다거나 그런건 잘 모르겠군. pid 자체를 배정받는 순간을 찾아봐야할지도.
? 프로세스가 죽었어도 상태 검색이 가능하다는건 무슨 원리?
: 상태 검색이라는 것 자체가, 내부 스레드가 여전히 메모리에 남아있어 탐색이 가능하여 죽었는지 아닌지 알수있다는 말.
반대로 종료하자마자 free 시킬수 없다는 얘기이기도 함. (아예 지우면 검색을 못할테니.) 아마 종료되는 process 등을 따로 list 에 관리하거나 해서 init process 종료 시점에 싹 청소하고 끈다든가 해야할 것 같음.
궁금했던 거 마저 찾아보기.
? fdt와 pml4는 뭐가 다른 거지? pml4가 정확히 뭐지?
: page map level4로,
상위 레벨 페이지 테이블이고, 단순히 말하자면 페이지 테이블인데.
이건 process가 시작되자마자 자기의 code에 따라 할당받는 페이지에 관한 테이블이고.
fdt는 이제 그 process가 다른 파일에 access하기 시작한다면 참조하거나 열었거나 읽고 쓰기가 가능한 파일에 대한 목록을 적은 테이블이다.
pml4에는 가상 주소가 적혀있는 거니까
그걸로 물리 메모리로 변환하거나
그 가상주소가 접근 가능한 건지, 접근이 불가능한건지 판단할 수 있고
거기에 접근했을때 이제 페이지 폴트가 나면 페이지 폴트 핸들러로 넘어갈것.
? 자식 프로세스가 fdt를 상속받는다면 어떻게 하는거지? 단순히 참조하나? 아예 복사해서 붙여오나?
흠 복사해서 붙여오는 것도 하나의 방법이기는 한데, PintOS도 그렇고 대부분의 운영체제도 그렇고 그냥 부모 프로세스의 fdt를 자식 프로세스 생성 시점에서 참조할 수 있도록 넘겨주는 듯함.
? fd table 만들 시 next_fd라는 걸 추가하라는데 왜 필요하지?
: 다음에 새로운 fd를 할당할 때 바로바로 할당할 수 있음. 가용 공간을 찾기도 쉽고, 연속적으로 배정하기도 쉬움.
? file 구조체는 무엇으로 이루어져있지?
? read나 write할때 position 같은걸 알 필요가 없는 이유가 뭐지? position을 굳이 움직이고 어디인지 가져오는 함수는 있으면서?
/* An open file. */
struct file {
struct inode *inode; /* File's inode. */
off_t pos; /* Current position. */
bool deny_write; /* Has file_deny_write() been called? */
};
inode (index node)
/* In-memory inode. */
struct inode {
struct list_elem elem; /* Element in inode list. */
disk_sector_t sector; /* Sector number of disk location. */
int open_cnt; /* Number of openers. */
bool removed; /* True if deleted, false otherwise. */
int deny_write_cnt; /* 0: writes ok, >0: deny writes. */
struct inode_disk data; /* Inode content. */
};
파일마다의 메타데이터, 물리적 위치를 포함한 inode.
파일명이 바뀌더라도 파일에 따라 고유한 inode는 바뀌지 않음.
struct list_elem elem: 이 구조체는 연결 리스트에서 각 inode를 연결하는 데 사용됩니다. PintOS에서는 리스트의 요소를 나타내는 노드를 가리키는 포인터로 구성된 연결 리스트를 사용하여 inode들을 관리합니다.
disk_sector_t sector: 이는 디스크에서 해당 inode의 위치를 식별하는 데 사용되는 디스크 섹터 번호입니다. 디스크에서 파일의 실제 데이터와 메타데이터가 저장되는 위치를 가리킵니다.
int open_cnt: 파일을 현재 열고 있는 프로세스의 수를 나타냅니다. 여러 프로세스가 동시에 파일을 열 때 이 값을 증가시키고, 파일을 닫을 때 감소시킵니다.
bool removed: 이 값이 true이면 해당 inode가 삭제되었음을 나타냅니다. 파일이 삭제되었더라도 해당 inode를 사용 중인 프로세스가 있을 수 있으므로, 삭제된 파일을 식별하기 위해 사용됩니다.
int deny_write_cnt: 이 값이 0보다 크면 파일에 대한 쓰기 작업이 거부된 상태임을 나타냅니다. 파일이 현재 쓰기 작업을 수행 중인 경우, 이 값을 증가시켜 다른 프로세스가 동시에 쓰기 작업을 시도하지 못하도록 합니다.
struct inode_disk data: 이는 실제 inode의 내용을 나타내는 구조체입니다. 파일의 메타데이터 정보를 포함하며, 해당 파일의 크기, 소유자, 권한 등의 정보를 저장합니다.
struct inode와 struct inode_disk의 구조는 유사하지만, struct inode_disk는 디스크에 저장되는 형식에 맞게 조정된 구조입니다. struct inode는 메모리 상의 inode를 나타내며, 파일 시스템의 메모리 관리 및 작업을 위해 사용됩니다. 반면 struct inode_disk는 디스크에 저장되는 inode의 실제 데이터를 나타내며, 파일 시스템이 디스크에서 inode를 읽고 쓸 때 사용됩니다.
그러니까 inode는 일종의 관리용 메타데이터에 가까운거고
inode_disk는 이제 데이터를 직접 편집할때 쓰는 거군.
file에서 position을 따로 지정 받지 않고 읽거나 쓰는 이유도 알았어. 구조체 내에 이미 정의되어 있기 때문이네.
읽고 있는 숫자를 세는 것도 인상깊고. 함수를 쓸 때 고려할만한 변수가 뭔지 잘 알게되었음.
? 열려있는 파일을 remove해도 어떻게 close가 되진 않게 하는거지?
아마 삭제 여부 remove를 true로 해놓고 Open_cnt가 0이 되면 그제서야 file 자체를 삭제하면 되는거겠지...
? page_fault를 modify하는 것과 check_address 단계에서 처리하는건 뭐가 다른 거지?
page_fault는 메모리 액세스 중에 발생하는 하드웨어 인터럽트로, 실제로 메모리에 접근하려는 시점에 발생합니다. 반면에 check_address는 주어진 가상 주소의 유효성을 미리 검사하여 잘못된 주소로 인한 비정상적인 동작을 방지하는 것에 초점을 둡니다.
Race Condition(경합 조건):
프로세스가 가상 주소를 검사한 후 실제로 해당 주소에 접근하기 전에 다른 프로세스가 해당 페이지를 제거하여 메모리에 로드되지 않은 상태에서 접근하려고 시도할 수 있습니다. 이 경우 check_address는 유효한 주소로 인식하지만, 실제로는 페이지가 없는 상태에서 접근하려고 하면 page_fault가 발생합니다.
Page Replacement(페이지 교체):
가상 메모리 관리에서 페이지 교체가 발생하는 경우에도 page_fault가 발생할 수 있습니다. 프로세스가 가상 주소에 접근하는 도중에 페이지가 물리 메모리에 없는 경우 페이지 교체가 발생하여 해당 페이지를 디스크에서 메모리로 로드합니다. 이 때 check_address는 주소의 유효성을 확인하지만, 페이지가 메모리에 로드되기 전에 접근하려는 시도가 발생하면 page_fault가 발생합니다.
간단히 말하자면 미리 방지해도
직접 액세스 순간에는
1 로드가 아직 안되었는데 접근함
2 다른 프로세스가 없앴음
등의 예외가 있으니 한번 더 처리를 해야하는 거같음.
? 강의에서는 exec이 fork+exec이랬음. 그리고 fork는 다루지 않음. 그러나 깃북은 두개를 따로 다룸. 그러면 깃북의 exec은 fork 같은 일은 안 하는 건가?
?? 그렇다면 exec시 고려하는, load 자체를 기다리는 semaphore 과정은 fork에 가깝고 exec이 아니라 fork의 load 과정에서 하면 되는건가?
: exec은 새로운 실행 파일을 실행하면서, 새로운 프로세스를 시작하여 기존 프로세스에서 대체하기 때문에 process_exec을 하기때문에 process_exec에 관한 처리는 해야함.
exec 시스템 호출을 사용하여 새로운 프로세스를 실행하면, 이전의 프로세스는 종료되고 새로운 프로세스가 시작됩니다.
따라서 exec 시스템 호출을 수행할 때, 실행되는 새로운 프로세스의 인수를 사용자 프로그램 스택에 적재하여 전달할 수 있습니다.
(아마 intr_frame에 있을 user stack 포인터를 이용하면 될거같다.)
물론 fork도 복제 여부 확인 전까지 리턴하지 않고 실패, 성공 여부를 반환하기때문에 기다리는 것 역시 해야할 것같음.
? exec시 create가 완료되는 지점, load가 완료되는 지점을 체크하라고 했는데 create가 완료되는 지점은 어떻게 체크하지?
: 근데 사실 load가 완료되는 순간 create도 완료되는걸 체크하는거나 마찬가지 아닌가.
? fork시 유효하지 않은 pid를 리턴하는 경우는 실패인 경우인가? 실패라면 왜 굳이 실패했다고 안하고 그런걸 리턴하는거지?
: 흠 실패했을 때는 -1을 반환한다는데.
유효하지않은 pid 자체가 반환되는 순간은 있다고 함.
(아마 깃북에서는 자식 pid만을 반환해야한다는 얘기같음.)
?pml4_for_each()의 Pte_for_each_func()를 virtual memeory 파트를 확인해서 추가 구현하라는데 무엇을 추가 구현하라는 것인지 확인하기.
: 넹
? fd는 exec 호출 중에도 열린 상태라는데, 당연히 열었다면 이미 open 중일텐데... 새로 exec한게 그대로 상속받는다는건지, 아니면 별개로 exec한 애가 있든 말든 열려있다는 건지. 또 exec을 했다가 종료한다면 원래의 상태로 돌아오는 건지.
: 이전 프로세스는 완전히 종료된다고 하니 그대로 복사해서 가져오는것일거같음.
? Denying write to executable 깃북과 확인해서 대조하기.
: 넹
흠... 코드를 뒤져보면서 알아보든
지피티를 털든 코드를 좀 만지든 해야겠군.
오늘은 시스템 콜 함수들 뼈대 골자 정도는 쓰고
주로 쓰는 함수들을 일단 넣어놔야징...
fd와 pml4 차이를 아는걸 주로...