프로세스 생성
- 부모 프로세스가 자식 프로세스 생성
- 프로세스의 트리(계층 구조) 형성
- 프로세스는 자원을 필요로 함
- 자원의 공유
- 부모와 자식이 모든 자원을 공유
- 일부를 공유
- 전혀 공유 X
- 보통은 자원을 공유하지 않고 경쟁
- 수행
- 부모와 자식이 공존하며 수행되는 모델
- 자식이 종료(terminate)될 때까지 부모가 기다리는(wait) 모델
- 보통은 부모 자식이 독립적으로 프로세스를 수행
- 주소 공간(Address space)
- 자식은 부모의 공간을 복사함(binary and OS data)
- 자식은 그 공간에 새로운 프로그램을 올림
- 유닉스의 예
- fork () 시스템 콜이 새로운 프로세스를 생성
- 부모를 그대로 복사(OS data except PID + binary)
- 주소 공간 할당
- fork 다음에 이어지는 exec() 시스템 콜을 통해 새로운 프로그램을 메모리에 올림.
- fork는 부모의 code, data, stack 복사 -> 복사하는 시점의 부모 프로세스의 상태를 가져옴(PC, register 정보도 가져옴)
- 새로운 프로그램을 돌리고 싶으면 exec을 통해 완전히 새로 덮어씌움..
Q.그럼 exec()을 실행하면 부모 프로세스의 정보는 아예 삭제되는 건가?
Q.여기서 말하는 자원은 뭐야? 부모랑 자원을 어떻게 공유해?
프로세스 종료
- 프로세스가 마지막 명령을 수행한 후 운영체제게 이를 알려줌(exit)
- 자식이 부모에게 output data를 보냄(via wait).
- 프로세스의 각종 자원들이 운영체제에게 반납됨
- 부모 프로세스가 자식의 수행을 종료시킴(abort)
- 자식이 할당 자원의 한계치를 넘어섬
- 자식에게 할당된 태스크가 더 이상 필요하지 않음
- 부모가 종료(exit)하는 경우
- 운영체제는 부모 프로세스가 종료하는 경우 자식이 더 이상 수행되도록 두지 않는다.
- 단계적인 종료: 가장 말단의 자식부터 차례로 죽여나감
- 자식이 먼저 죽고 부모가 죽는 것이 룰
- 윈도우에서 어떤 프로그램을 돌리고 그 프로그램 내에 여러 창이 띄워져 있을 경우, 가장 상위 창을 닫아버리면 밑에 창도 다 죽음
- 모든 시스템 내 프로세스는 자신의 부모 프로세스를 가지고 있다.
Q. 그럼 최초에 시작되는 프로세스인 O.S가 공동 조상인가? 하나의 독립된 프로그램이 처음 시작할 때 복제되는 부모는 누구인가?
fork() 시스템 콜
- 프로세스는 부모 프로세스의 fork() 시스템 콜에 의해 생성됨
- fork()를 통해 부모의 컨텍스트(메모리 상 주소 공간, PC, register..등의 정보)를 복제함
- 자식 프로세스도 부모 프로세스가 진행중인 시점 그 이후부터 동작함
- fork의 리턴값: 부모는 자식 프로세스의 pid(> 0), 자식은 0, 이걸 이용하여 각 프로세스 간 다른 작업을 수행할 수 있음
- fork 하면 부모와 자식 프로세스의 메모리 상 주소나 PC랑 register들의 정보와 그 주소는 다 다른건가? 내부적인 값만 복사되는거고 주소값이 복사되는 건 아닌거지? P.C나 register에 대한 정보는 어떻게 구성돼있는거냐 ..?
왜 부모에서 자식을 만들까잉 그냥 새롭게 만들면 안 돼?
exec() 시스템 콜
- 부모를 복제해서 프로세스를 시작하는 FORK만 있으면 동일한 프로세스만 돌아갈텐데 그렇지 않음
- exec()을 통해 새로운 프로세스를 시작할 수 있기 때문
- 완전히 덮어 씌워진다, 부모 프로세스의 코드는 더 이상 존재하지 않는다. 새로운 프로세스의 코드가 처음부터 실행된다.
wait() 시스템 콜
- 왜 사용할까?
- 리눅스 커맨드에서 VI를 이용해 A라는 파일을 편집하는 "vi A"를 입력하면 해당 파일 편집이 종료되기 전까지는 명령어를 입력할 수 없고, 편집이 종료되면 또 다른 명령어를 입력할 수 있는데, 이러한 커맨드 한 줄 한 줄이 쉘이라는 프로세스임, 편집 프로세스가 종료될 때까지 쉘 프로세스가 wait하다가 자식 프로세스인 편집기가 종료되면 다른 작업을 수행할 수 있도록 함
- 보통은 부모와 자식이 서로 CPU를 할당받기 위해 경쟁상태에 있는데 wait을 사용하면 자식 프로세스가 수행 완료할 때까지 기다릴 수 있음
exit() 시스템 콜
- 프로세스의 종료
- 자발적 종료
- 마지막 statement 수행 후 exit() 시스템 콜을 통해
- 프로그램에 명시적으로 적어주지 않아도 main 함수가 리턴되는 위치에 컴파일러가 넣어줌
- 비자발적 종료
- 부모 프로세스가 자식 프로세스를 강제 종료시킴
- 자식 프로세스가 한계치를 넘어서는 자원 요청
- 자식에게 할당된 태스크가 더 이상 필요하지 않음
- 키보드로 kill, break 등을 친 경우
- 부모가 종료하는 경우
- 부모 프로세스가 종료하기 전에 자식들이 먼저 종료됨
프로세스간 협력
- 프로세스들은 일반적으로는 독립적으로, 경쟁하며 동작하는 게 원칙(cpu, 메모리 공간 등을 필요로함)
- 원칙적으로 각 프로세스는 다른 프로세스들의 메모리 주소 등에 대한 정보를 알 수가 없음(O.S만이 모든 정보를 가지고 있음)
- O.S에게 메시지를 전달하여 프로세스간 협력하는 방법과 메모리를 아예 공유하는 방법이 있음
메시지 전달
-
Direct Communication: 메시지를 전달받을 프로세스를 지정하고 메시지를 전달
-
Indirect Communication: 메일박스(또는 PORT)를 통해 메시지 간접 전달" 운좋게 Q가 메일박스를 빨리 열어봤으면 Q가, 다른 프로세스가 빨리 열면 다른 친구가 꺼내갈 수 있음. 누가 받을지 명시하지 않고 서로 협력하는 누군가(프로세스)가 꺼내갈 수 있게 함
-
어쨌든 두 방법 모두 커널을 이용하여 메시지를 전달하는 방식을 사용
메모리 공유
- 원칙적으로는 각 프로세스는 본인만의 code, data, stack만 접근할 수 있기 때문에 공유할 수가 없음
- 운영체제에게 시스템 콜을 통해 메모리 공간 일부를 공유하겠다고 하면 O.S가 허용해줌
- 프로세스가 서로 신뢰할 수 있는 경우에는 공유해도 문제가 없으나 신뢰불가하다면 공유하는 것에 유의해야 함
Q.스레드는 협력하기 더 쉬울까 어려울까?
- 동일한 프로세스에 있기 때문에 메모리 공간을 공유하고 있고, 협력하기 더 용이하다.
Q.프로세스간 커뮤니케이션은 언제 사용하는거야?