[CS] 프로세스 생성

do yeon kim·2022년 10월 16일
0

CS-운영체제

목록 보기
6/20

http://www.kocw.net/home/cview.do?cid=3646706b4347ef09

프로세스 생성

전반적인 흐름

프로세스생성
부모프로세스가 자식 프로세스를 만든다.

하나의 프로세스가 다른 프로세스를 생성한다. 복제생성을 한다.
부모가 자식을 만드는데 부모프로세스는 하나가 자식을 복제해서 만든다.
자식을 여러개 만들 수 있다. 프로세스의 계층도가 트리가 될 수 있다.
자식이 다시 자식을 나을 수 있다. 밑으로 갈수록 삼각형 형태의 프로세스 족보도가 만들어 진다.

프로세스가 실행을 위해서는 자원이 있어야 하고, 자원은 운영체제로 부터 받는다. 부모프로세스와 자원을 공유하는 경우도 있고, 공유하지 않는 경우도 있다.
원칙적으로는 공유하지 않는다.

자식이 만들어지면 개별적인 프로세스이기 때문에 cpu를 먼저 얻으려고, 메모리를 더 많이 얻으려고 경쟁한다.

프로세스가 실행될 때 부모,자식이 공존해서 실행되는 경우가 있고, 자식이 끝날 때까지 기다리는 경우도 있다.


부모프로세스의 주소공간이 있다. 자식 프로세스는 그대로 주소공간을 복사한다.
운영체제에 있는 pcb등 자원도 일단 복사한다. 복제 생성만 하게 되면, 모두 같은 일을 하는 것이다. 그래서 일단 복제 하고 새로운 프로그램을 덮어 씌울수 있다. 그렇게함으로써, 서로 다른 프로그램이 존재할 수 있다.
fork()와 exec()가 그 역할을 한다.

fork()
복제 생성을 하는 것이 fork() 라는 시스템콜의 역할이다.

exec()
복제 후 다른 프로그램으로 덮어씌우는 것이 exec() 시스템 콜이라고 한다.

프로세스의 생성은 부모 프로세스를 복제하고, 새로운 프로그램을 덮어씌우는 것이다. 두개가 독립적이므로 복제만 할 수도 있고, 복제 후 덮어 씌울수도 있다.

자식프로세스를 만들지 않고, exec를 하면 새로운 프로세스로 바뀔 수도 있다.
이 경우는 지금까지 해온 프로세스의 수행을 모두 없애고 새로운 것으로 바꾸는 것이다.

프로세스를 사용자프로세스가 다른 프로세스를 생성하는 것이 아니라 운영체제를 통해서만 프로세스를 만드는 것이다. 시스템콜이기 때문에 운영체제에 요청을 하는 것이다.


exit()
프로세스가 마지막 수행을 하고서, 프로세스를 종료할 때는 exit()이라는 시스템 콜을 요청하면 종료하게 된다.

프로세스가 종료될 때는 자식이 부모한테 데이터를 보내게 된다.
프로세스에서는 원칙적으로 부모프로세스가 먼저 종료되지 않고 자식이 먼저 종료된다. 프로세스가 종료될 때는 데이터가 wait()시스템 콜을 통해서 전달하게 된다,

자발적으로 종료될 때는 exit()시스템콜을 하면되고, 비자발적으로 종료될 때는 abort()하게 된다.

abort()
강제적 프로세스 종료할 때를 의미한다. 어떨때 강제 종료되면은 자원의 한계치가 넘어설때, 자식에게 더이상 할당할 테스크가 없을 때, 부모가 종료될 때(자식이 부모보다 먼저 종료되어야 한다). 부모가 먼저 종료되어야 한다면, 자식을 모두 종료시키고서 부모가 종료하게 된다.
단계적인 종료가 일어난다.




process creation

프로세스는 부모프로세스로 부터 복제해서 만들어 지기 된다. 복제되는것은 부모의 모든 데이터로 프로세스문맥(cpu가 프로세스의 어디까지 실행했는가를 표현하는 프로그램카운터를 포함해서)을 포함해서, 주소공간(code,data,stack), 모든 메모리가 복제된다.
만들어지는 순간 부터 독립적인 프로세스로 한정된 자원을 먼저 차지하기 위해서 경쟁을 하게 된다.



copy-on-write

copy-on-write(cow)
프로세스의 생성은 부모프로세스를 자식클래스가 그대로 복제하는 것이라고 했다. 그러다보니, 똑같은 데이터가 2개가 있는 것이고, 메모리 낭비가 발생한다.
메모리 낭비를 줄이기 위해서, 프로그램카운터만 복사를 하고, 메모리는 공유할수 있는 것을 공유하면서 프로세스를 생성하는 것을 copy-on-write라고 한다.
복제 후, 공유된 데이터는 같이 사용하다가 내용이 달라지기 시작하는 시점부터 공유하던 메모리를 카피해서 사용한다. write가 발생하면, 두 프로세스의 공유하는 데이터에 차이가 발생하기 때문에 그 시점에 code,data,stack을 카피해서 자식프로세스의 영역을 만드는 것이다.



fork() 시스템콜

프로세스를 만든다는 것은 사용자프로세스가 직접하는게 아니라 운영체제에 요청을 하는 것이다. fork()시스템 콜을 통해서 자식을 만든다.

fork()시스템콜만 있다면 모든 프로세스가 똑같은 프로세스만 있을 것이다.
하지만 실제로는 다양한 프로세스가 있다. 이는 fork()로 복제된 자식 프로세스를 exec()시스템콜을 통해 새로운 프로그램을 메모리에 올리는 것이다.

그러므로 프로세스의 생성은 2단계를 걸치게 된다.
1. fork()를 통한 복제
2. exec()을 통한 덮어씌우기

위의 코드는 실제 운영체제의 fork() 코드는 아니다.

왼쪽이 부모프로세스, 오른쪽이 자식프로세스이다. 자식부로세스는 메인부터 다시 시작하는 것이 아니라, fork()이후 부터 실행된다.
부모프로세스의 프로그램카운터도 복제하기 때문에 자식의 프로그램카운터는 fork()까지 실행되어진 상태이다. 그래서 그 다음부터 실행한다.

자식프로세스를 만들면 부모프로세스와 같기 때문에 누가 부모프로세스인지 알수 없다. 그렇기 때문에 부모프로세스와 자식프로세스를 구분하기 위해서 pid가 있다. pid를 통해서 자식과 부모를 구분해준다. fork()의 리턴벨류가 다르다.
리턴벨류로 부모프로세스는 양수의 pid를 얻는다. 자식프로세스는 pid 0이다.
fork() 의 리턴벨류가 다르기 때문에 다른 일을 할 수 있게 할 수 있다.



exec() 시스템콜

프로그램을 완전히 새로운 프로세스로 태어나게하는 역할을 한다.
exec()를 만나게되면, 새로운 프로그램으로 덮어씌우는 것이다.
exec()을 만나게 되면 새로운 프로그램의 처음부터 시작하게 된다.

부모프로세스가 자식을 만들고 나서 자식은 완전히 다른 프로그램으로 덮어씌어지는 것이다.

exec() 이후에는 새로운 프로세스로 변경되는 것이기 때문에 그 이후의 코드는 실행이 불가능 하다.



wait() 시스템콜

wait()
wait()시스템콜은 프로세스를 잠들게 하는 것이다. block상태로 보내는 것이다. block상태는 오래 걸리는 이벤트를 기다리고, 이벤트가 만족되면 cpu를 얻을 수 있는 상태를 말한다. wait()시스템콜을 하면 조건이 만족하기를 기다리면서 block상태가 되는가. 자식프로세스를 만들고 wait()시스템콜을 한다.
자식프로세스가 종료되기를 기다리면서 block상태가 된다. 자식프로세스가 종료되면 부모클래스가 다시 ready가 된다.

부모프로세스는 잠들게 되서 cpu를 얻지 못한다. 자식프로세스가 코드를 다 실행하고 종료가 되면 그때서야 wait를 빠져나가서 다음 코드를 실행할 수 있다.

wait()는 자식프로세스가 끝날 때까지 기다리는 것이다.



exit() 시스템콜

exit()
프로세스를 종료시킬때 부르는 시스템콜이다.
명시적으로 프로그램내에서 적을 수도 있고, 컴파일러가 프로그램이 끝날 때 부르게 만들어 둔다. 자발적으로 종료될 때 마지막 문장을 실행뒤 호출하게 된다.

비자발적인 종료
부모프로세스가 자식을 종료시키는게 대표적인 예이다.
한계치를 넘어서는 자원을 요청하거나 자식프로세스에게 더이상 시킬 일이 없거나
키보드로 kill break등을 친 경우에 해당한다.
부모가 종료하는 경우 자식들이 먼저 종료된다. 그리고 부모가 종료되게 된다.



  • fork()
    부모프로세스를 복제하는
  • exec()
    완전히 새로운 프로세스로 덮어씌우는
  • wait()
    자식이 종료될 때까지 기다리는
  • exit()
    프로세스를 종료시키는


프로세스간의 협력

원칙적으로 프로세스는 독립적이고, 경쟁을 하면서 실행하게 된다. 원칙적으로 하나의 프로세스가 다른 프로세스의 수행에 영향을 미치지 못한다.
경우에 따라서는 협력을 해야만 효율적으로 돌아가는 경우도 있다.

프로세스간 협력 메커니즘(IPC) 2가지 방법
meassage passing
shared memory



Message Passing

프로세스A가 프로세스B에 메시지를 전달하고, 그 영향을 받아서 프로세스B가 실행된다.
다른 프로세스에 직접 전달하는 방법은 없고 운영체제의 커널을 통해서 메시지를 전달한다.

통신하려는 프로세스 이름을 명시하냐 않하냐에 따라서 Direct와 Indirect로 구분된다.

둘다 커널을 통해서 전달하지만 다른 점은 메시지를 받을 프로세스를 명시하느냐 않하는냐의 차이이다. 명시하지 않은 경우에는 아무나 가지고 갈 수 도 있다.



Shared Memory

원칙적으로 독립적인 주소공간을 가지는데, shared memory는 일부 주소공간을 공유하는 것을 말한다.
커널한테 shared memory를 쓴다고 요청하고, 그 후에 공유하는 것이다.
shared memory를 하기 위해서는 신뢰하는 관계여야 한다.

Thread들 끼리는 같은 주소 공간을 공유하므로 협력이 가능하다.

0개의 댓글