OS

pintos project#2

bogus919 2013. 10. 3. 04:54

1. making & using the file system


- creating

pintos-mkdisk filesys.dsk --filesys-size=2

: 현재 폴더에다가 filesys.dsk 라는 이름으로 simulated diks를 만든다


- formating

pintos -f -q

: 현재 폴더에 있는 filesys.dsk 를 포맷한다

 userprog 폴더에서 실행해야 제대로 작동한다 씨발 좆같은


- copying 'user program file' into the pintos file system

pintos -p ../../examples/ehco -a echo -- -q

: exmaples폴더의 echo를 filesys.dsk에 복사한다. -a 옵션을 줘서 'echo' 라고 이름을 지정할 수 있다


- running

pintos -q run 'echo x'

:filesys.dsk에 복사한 echo를 실행한다



2. gdb

pintos --gdb -- run alarm-multiple 

을 먼저 실행 한후, 다른 터미널 창을 띄워서


pintos-gdb kernel.o

를 실행한다. kernel.o 를 디버깅할거니까, kernel.o 가 존재하는 threads/build 에서 실행해야 한다


target remote localhost:15031

gdb를 실행한후 위 커맨드를 실행한다. 두개의 터미널로 띄웠으니 remote localhost를 target으로 지정해줘서 access 해야한다


진짜 토나올거같다 진짜 속이 안좋다 담배피다가 토할뻔 지금은 새벽다섯시


3. user program

user program을 사용하기 위해서, user는 system call 을 사용한다

user가 system call을 하면, system call interface에서 interrupt를 발생시킨다

이 system call interface의 수행을 하는것이 init.c 에 있는 syscall_init() 인것 같다.

그리고 syscall_init() 이 호출되면 자동으로 syscall_handler()가 호출되는데

syscall_handler가 호출되는 과정이 system call table 에 access 한 것 같다

그럼 이제 해야할 일은 system call table에서 system call에 대한 번호를 할당 한 후에,

할당된 번호에 해당하는 handler를 작성하는 것 같다


남은 건 내일해야겟다 이 시발롬아



4. syscall.c 에 보면 

static void syscall_handler (struct intr_frame *); void syscall_init (void) { intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); } static void syscall_handler (struct intr_frame *f UNUSED) { thread_exit (); }


이래 되어있다

syscall_init에서는 여러 parameter를 패싱하면서 intr_register_int 를 호출하는데


void intr_register_int (uint8_t vec_no, int dpl, enum intr_level level, intr_handler_func *handler, const char *name)

원형은 저렇게 생겼다
순서대로 vector table에서의 interrupt number인 것 같고,
descriptor privilege level(dpl) 은 3으로 해주면 user에서 interrupt를 호출할 수 있고
0일때는 호출 할 수 없다
handler는 syscall.c 에 선언되어있고, 이 핸들러를 작성하는거에 따라서 system call이 수행 하나보다
"syscall"을 넘겨준거 보니  name은 interrupt의 종류인것 같다. 

오늘은 여기까지 시발 



5. syscall_init도 호출되고, intr_register_int도 잘 호출됐는데(실제로 syscall도 kernel로 넘어갔는데)

핸들러인 syscall_handler가 호출안된 이유는

process.c에서 process가 excute된후 wait되지않았기 때문이다

process가 excute되면 thread가 생성된 후(new) wait상태로 있어야 하는데

지금 process_wait() 에서는 기다리는 조건이 없고 무조건 리턴해버렸기 때문이다

일단은 여기를 무한루프를 돌리면서 확인해보면 될것 같다



6. process_execute() 안에서

thread를 생성해주고 - thread_create() 

프로세스를 실행한다 - start_process() 


start_process()에서는 내가 실행시킨 user program을 로드시켜주는데  - load()

load()안에 parse_filename()과 construct_ESP(esp)가 필요하다

각각 커맨드를 파싱해주고 파싱한 내용으로 스택을 구성한다


simulated disk에 'echo'라는 실행파일이 있었지만 나는 'echo x' 를 실행시켰고

이는 load가 아직 파싱을 하지 못했기때문에 filesys에서 일치하는 실행파일을 못찾았기 때문이다

exit보다 먼저 할일은 argument_parsing 이다


서서히 윤곽이 잡히는것 같기도 하고 아닌것같기도 하고 시방



7. 스택 or 페이지 접근?

우아앙아아앙 우여곡절 끝에 argument parsing하고 stack에 쳐넣은것 같다

parsing은 strtok_s로 그냥 똑같이 하면되고

stack은 그냥 스택포인터를 이용해서 접근하니까 된것 같다

스택포인터를 하나 내린후에, 그곳에 값 저장하고, 또 내리고 저장하고 반복


잘 찾아보니

thread structure의 member중에 stack pointer와 page directory 가 있다

thread랑 process랑 같은걸로 생각하라 했으니 아마 thread structure가 PCB와 같은 역할을 하는것 같다

system call handler에서 current_thread()를 이용해 저 stack pointer로 스택에 접근해서

passing해줬던 argument들을 받아와서 system call에게 인자로 넘겨주면 되지않을까?


페이지 디렉토리는 뭔지 아직 잘모르겠다

thread의 esp로 하니까 안되네

intr_frame에도 여러 멤버있는데 거기도 esp가 있긴하다 이걸로해봐야겠다



8. thread

thread.c 파일을 잘 읽어봐야겠다

thread에 대한 함수들의 설명이 잘나와있다



9.

Q2. exit 뿐만 아니라 모든 시스템콜들이 lib/user/syscall.c 안에 이미 있죠?

유저 프로그램 (echo 같은 것) 에서 exit()를 호출하면 일단 lib/user/syscall.c 안의 exit가 호출됩니다. 그러면 exit 함수 안에서 syscall1(SYS_EXIT, status) 라는 매크로를 사용하는데, (syscall1 매크로는 같은 파일 위쪽에 보면 있습니다) syscall1 매크로가 0x30 인터럽트를 발생시키면 인터럽트 벡터 테이블을 참조하여 시스템콜 핸들러를 호출하게 되는데, 이 시스템콜 핸들러에서, 해당하는 시스템콜, 그러니깐 우리가 구현해야하는 exit 함수를 호출하게 되는 것입니다. 

정리하면 lib/user/syscall.c 안의 exit는 유저 프로그램에서 exit를 호출했을 때, 우리가 구현해야하는 exit()를 호출해주기 위한 인터페이스(?) 같은 것이라 보면 됩니다.



10. 해야되는거

- process_wait 에서 어떻게 exit의 리턴값을 받음???? 어떻게 종료시킴????

- tid 가지고 thread의 status 가져오기

  (child list 만들어야되나)

- excetion 대체 어떻게 돌아가는거야


11. 에이 시발

돌아가는꼬라지를 보니

process.c 의 process_execute()에서


tid = thread_create (file_name, PRI_DEFAULT, start_process, fn_copy);


이 부분 호출하기전까지는 file_name 이 파싱되지않은 raw command 이다

start process 가 호출인자라서, start process 안에서 load부르고 parsing하고

그러고나서 parsing된 file_name이 들어갈줄 알았는데 그게 아닌것 같다

parising된 file_name을 인자로 전달할 수 있도록 해야겠다



그리고

run_task에서 

process_wait (process_execute (task));

이 부분을 잘보면
process_execute가 종료되면서 tid를 리턴한다
그럼 그 tid가 process_wait에게 넘어가는데
process_wait 은 넘겨받은 tid를 가지고 일단 그 process의 thread의 structure에 접근한다
이건 아마 이 현재 wait안에서 실행중인 process는 main이고, main의
child list안에 execute가 끝난 process가 있을테니 리스트 탐색을 통해 접근하면 될것 같다
그리고 나서 그 child의 status를 리턴해준다


근데 test파일중에 exit(57) 이건 무슨뜻이지?
알아냈다
exit의 argument는 그냥 status일 뿐이니까 종료할떄 exit(57) 이렇게 해주면된다
근데 실제로 정의된 status는 4개뿐이니까 그냥 그거로 하면됨



12. sys_call.c 안에, user_exit()에서 구현할 내용


1. child를 죽일떄는 부모 안에서, 부모의 child list를 통해서 접근해야함

 실행된 child process가 비정상인 bad pointer가 들어 올 수도 있기도 하고


 지금 실행되는 child process가 자기 안에서 자기 자신을 죽이면 안되고

 부모의 process로 들어가서 child를 죽여야함


2. 부모가 있는지 확인 해야함


3. child넘어올때 parent block 해야됨


4. 지금 돌아가고있는 애를 block 걸면 무한 루프 돌수도


5. 이제 child를 exit할때는 부모를 unblock하고 


6. kernel에 있는 syscall에서 syscall number와 status를 push해주므로

esp, esp+4 로 접근해주면 된다

int status = (int*)esp 이렇게인가?



13. process_wait 안에서 구현할거


예를 들어, thread가 생성될때 wait_status라는 member를 추가하고

thread가 종료될때 그 값을 변경하도록 한다

그리고 while문을 돌리다가 그 값이 변경됨을 확인하면 그때 break하도록 한다


마지막으로 값을 리턴하게 되는데

이 리턴값이 음수 인지 아닌지만 구별하면된다

-1이 리턴되면 커널이 알아서 error인지 인식하고 알아서 오류띄우든가 할거고

아니면 그냥 정상처리된걸로 생각한다



14. user program의 큰? 그림

 OS kernel <-> kernel-function  <내가 연결> your_function <-sys_handler-> user_prog : some function call;


어떤 user program이 호출되었고

그 프로그램안에서 printf등등 system call을 필요로 한다하면

system call handler를 호출하게 된다

내가 할일을 바로 이 handler안에서 kernel function 호출해주는것

 


15. process wait operation

1. process wait에서 parent는 child가 죽을때까지 기다린다

2. parent가 child를 기다리때, parent는 자신의 실행을 중단시킨다. 언제까지? child가 자신의 execution을 끝내고     exit status를 리턴할 때까지

3. parent는 자신의 execution을 중단시키는데 child의 pcb중 wait semaphore를 재워서 중단시킨다

(왜 자기가 아니라 child의 wait semaphore를 중단시키지???)

4. child는 자신의 execution이 끝나면 parent를 깨우고, 자신의 zombie semaphore를 block시킨다

5. parent는 child의 exit status를 받아오고  child를 unblock시키고, child는 자기자신을 완전히 죽인다. 그리고     parent의 child list에서 제거시킨다



16. process termination

1. 프로세스에 의해 실행중인 executable을 닫는다. 그러면 executable 에 대해 write가 re-enable됨

2. 모든 open file들을 닫는다

3. 현재 process에게 잡혀진 모든 lock을 release한다

4. process의 살아있는 childe들의 zombie semaphore를 up 시킨다

5. base page directory를 activate시키고 process의 page directory를 죽여버린다

6. waiting parent에게 신호를 보낸다

7. process의 zombie semaphore를 down시킨다



17. synchronization

1. wait operation

- wait semaphore를 down 시킴

- zombie semaphore를 up 시킴


2. exit operation

- wait semaphore를 up 시킴

- zombie semaphore를 down 시킴