본문 바로가기

cs/운영체제

운영체제 9강 Process Management 2

https://core.ewha.ac.kr/publicview/C0101020140325134428879622?vmode=f 

 

반효경 [운영체제] 9. Process Management 2

설명이 없습니다.

core.ewha.ac.kr

 

 

프로세스 생성 실행 종료와 관련된 4가지 시스템콜을 살펴볼것임 

 

프로세스 메니지먼트 마저 보는것임

 

프로세스는 복제생성함

 

복제 -> 프로세스의 context를 모두 복제함

부모의 code,data,stack 모두 복사함, cpu context 도 복제함 부모꺼 그대로 PCB 들도 베낌

 

공유하는것은 리눅스 같은 효율적인 운영체제에서는 그냥 죄다 카피하는게아니라 우선 공유할수있는 code,data,stack 같은 부모의 주소공간은 공유함 program counter 만 copy 해서 같은곳 가르키게 되어있는것임(원래 그냥 일반적으로는 죄다 복사해서 새거만듬)

 

부모와 자식이 달라지는경우 그제서야 이제 부모의 공유하던 메모리의 일부를 copy해서 자식이 갖게됨

-> 이런방식을 copy-on-writre(cow) 라고한다. -> 학부 정도에서는 이정도는 잘안다룬다고 한다.

copy-on-write 는 write 가 발생할때 copy 하겠다라는건데 뭐 lateinit 정도의 느낌으로 생각하면되지않을까 싶다(자원아끼는데)

copy하는것도 모든것을 copy 하겠다는게 아니라 일부분(메모리에 올라간부분)에 변화가 생겼을때 그부분만 copy 한다는것임

 

프로세스의 생성은 프로세스가 직접하는것이 아닌 운영체제에게 자식 프로세스를 만들어달라고 시스템 콜을 이용해서 요청하게됨

 

새로운 프로세스를 만드는 시스템콜이 fork() 시스템 콜이다.

 

일단 복제생성을 하니까 다 똑같아야하는데 프로세스들 다르지 않는가?

-> fork()로 복제를 뜨고 그다음에 exec()라는 시스템 콜을 통해 새로운 내용을 덮어씌운다.

 

일단 복제해놓고 그다음 덮어 씌운다.

 

fork() 시스템 콜 코드이다. -> 운영체제의 코드는 아니고 이제 c언어로 사용자 프로그램이 자식 프로세스 하나 만드는 코드이다.

fork() 가 시스템콜 이다 -> 새로운 프로세스 만드는 요청

 

요런식으로 자식이 똑같은 코드가 fork함수 호출결과로 만들어진다고 생각하면된다.

그리고 자식 프로세스는 fork() 함수 이후의 코드부터 실행된다.(부모 컨텍스트를 그대로 가져오니까)

-> 포크 함수이후 부분을 pc가 가리키고 있을것임

 

이렇게 포크하면 문제점이 생길것이다.

1.복제본(자식) 이 원본행세를 하려고함 

2.복제 생성되었으니 모든 프로그램이 다 똑같아야하는것 아닌가?

 

자식과 부모를 구별하기 위한 방법이 있다.

-> fork() 의 반환값으로 오는 값이 부모프로세스는 양수이다.

그리고 자식 프로세스는 반환값이 0 이다.

코드에서는 pid 라고 받음

 

fork() 의 반환값으로 부모인지 자식인지 구별함

그래서 위 코드보면 부모와 자식을 fork()의 반환값을 통해 분기처리해서 각각의 일을 할수있도록 코드를 짜놓음

 

일단 프로세스 자체는 분리된것이다 현재는 코드는 같지만 그래서 이제 다른 코드를 덮어씌울수 있는 방법을 보자

 

이제 코드를 바꾸는 시스템 콜이다 (이그젝이라 부름)

exec() 시스템콜은 전혀 다른 새로운 프로세스로 바꿔주는 역할이다.

그래서 위코드를 보면 fork() 뜨고 반환값으로 분기하여 자식이라면 execlp() 라는 함수를 호출한다.

execlp() 는 exec() 시스템 콜이다.

이제 execlp 라는 함수를 호출하면 새로운 프로그램의 첫번째 코드부터 실행하게된다.

execlp 안에 있는것들 어떤 프로그램 실행하며 argument 전해주는 리눅스 코드이다.(프로그램 이름 두번 따옴표안에 넣어주고 argument  필요한것 담아주는것) -> 그냥 새로운 프로그램으로 덮어 씌우는것만 알면되니까 그정도만 알고 넘어가자

 

 

이제 date라는 프로그램도 누가 짜놓은 프로그램일 것이다.

 

옆에 있는게 date 프로그램이다.(대충 이렇게 생겨먹었을거란 생각으로 보면된다.)

 

exec() 하고 나면 되돌릴수 없다.

 

exec() 꼭 자식을 만들어서 해야하는것은 아니다.

 

이런식으로 그냥 exec 냅다 불러버리면 덮어 씌워진다 .

exec 이후 코드는 영원히 호출이 안된다 -> 바뀌니까

 

wait() 시스템 콜은 이 프로세스를 blocked 상태로 잠들게 하는것임

 

기존에는 blocked 상태가 되는 조건은 i/o 작업을 하거나 이런거였는데

 

wait() 시스템 콜은 주로 자식 프로세스를 만들고 호출하게 되는데 자식프로세스가 종료되길 기다리며 blocked 된다

-> 자식프로세스가 종료되면 ready 상태로 다시 될아가고 cpu 를 받을수있게 되는것이다.

 

위에 코드 짜놓은것을 보면 fork() 하고 난뒤 자식이라면 뭔가를 하고 

부모프로세스라면 wait 으로 그냥 잠들어버리게 만들었다. -> 자식 프로세스가 끝날때까지 기다리도록 막아버리는 시스템 콜이다.

 

wait 시스템콜을 하는 대표적인 예는 

리눅스 프롬프트에 프로그램 실행하게 되고 그거 종료되고 다시 프롬프트 깜빡거리는거랑 같은거임 

그 리눅스에 기본적으로 쉘(뭐입력하는거) 그것도 프로그램인데 그런게 저런식으로 짜져있는 프로세스 인것임.

(이거 말이 좀 더러움 대충 설명해서)

 

exit 시스템 콜은 프로그램을 종료할때 호출하는 시스템 콜이다.

 

exit 시스템콜 코드에 명시적으로 표기해서 끄기도 하고 그냥 코드 다끝나는지점에 컴파일러가 알아서 갖다 붙임

 

자발적 종료: 코드 내에 명시적으로 exit 시스템 콜을 호출하거나 정상적으로 코드의 끝부분까지 갔을때 알아서 종료될때 일어나는 것

 

비자발적 종료: 코드가 그냥 잘 실행되고있는데 외부요인으로 죽이는것 -> 부모 프로세스가  자식 프로세스를 죽이는것(너무 많은 자원요구 등등)

사용자가 키보드로 alt f4 같은거 누른경우 -> kill 이라는 커맨드를 사용할수도 있음

어쩃든 부모 프로세스 혹은 사람이 종료시키는 경우임

부모가 죽는 경우도 자식먼저 다죽이고 죽으므로 비자발적으로 종료되기도함

 

 

프로세스 원칙적으로 대단히 독립적이다.-> 자식 낳아놓으면 다 알아서 하는것임 경쟁적 관계가됨

 

프로세스 간의 협력: 서로 정보를 주고 받으면서 실행하는것 (프로세스간 데이터를 주고 받는것)

 

 

프로세스간의 데이터를 주고 받는 방법은 두가지가 있다.

 

 

message passing : 프로세스 a가 프로세스 b 에게 메시지를 전달하는 것이다.

-> 프로세스는 원래 독립적이다 자기 메모리 공간만 볼수있고 프로세스가 다른 프로세스에게 직접 메시지를 전달할수있는 방법은 없다.

메시지를 전달하는 방법으로 커널을 통해서 메시지를 주고받는다 -> 커널이 메신저 역할을 해주는것이다.

 

프로세스 사이에는 공유 변수 이런것도 없고 자기것만 볼수있으므로

그래서 메시지를 보내는데 그 메시지도 직접 보내는것이 아니라 커널을 통해서 보낸다.

 

메시지를 전달하는 방법에도 두가지가 있다.(명시적 암시적 인텐트 같은 느낌인거 같다.)

1. Direct communication

-> 통신하려는 프로세스 이름을 명시

2. Indirect communication

프로세스 이름을 명시하지 않고 그냥 커널에있는 메일 박스에다가 메시지를 집어넣는다. 그러면 누가 꺼내볼지는 명시를 안한다.

아무나 꺼낼수있는 프로세스가 꺼내는것이다.

 

결론적으로는 커널을 통해서 전달하는것은 같다

 

 

shared memory: 원칙적으로 프로세스는 독자적인 주소공간을 사용하지만

일부 주소 공간을 두 프로세스가 공유하는것이다.  -> 커널이랑은 상관없다.

메모리 영역을 그냥 공유해서 사용한다.

 

shared memory도 그냥 바로 사용할수 있는것이 아니라 커널한테 shared memory를 쓰겠다고 시스템콜을 해서 메모리를 mapping 해놓고 그 이후에 사용자 프로세스 끼리 공유하게 되는것이다.

 

한번 커널이 시스템콜로 메모리를 공유하게 해주면 그이후에 커널은 관여하지 않는다.

 

그리고 shared memory 는 함부로 쓰면 이상한 결과를 불러올수있으니 서로 신뢰관계가 있는 프로세스 끼리 행한다.

 


 5장 cpu 스케쥴링에 대해서 예습 형식으로 하고 넘어감

 

프로그램이 실행되면 어떤 프로그램이든 간에 이런식의 pass 를 실행하면서 진행된다.

load store add store 이런것들이 cpu 에서 instruction 을 실행하는 기계어 들이다 -> cpu 를 running 하고 있다는 것이다.

I/O 작업 중에는 기다리고 있을것이다.

어쩃든 기다렸다 cpu 받았다가 이런행위를 반복하게 될것이다 어느 프로그램이던지 간에

 

cpu 만 받아서 쭉 하는것도 있겠지만 

이렇게 i/O 가 많은 프로그램들은 사람들과 상호작용하는 프로그램들이 이렇다.

과학 계산 프로그램 이런것들은 그냥 cpu 만 잡고 쭉 쓸것이다.

 

각 프로그램들의 cpu -burst(cpu 사용시간) 타임을 찍어본것이다.

 

보면 중간에 i/o 작업이 끼어드는 프로그램이 압도적으로 많았다.

이런 프로그램을 I/O bound job 이라 부르고

 

cpu 만 주로 쓰는 프로그램을 cpu bound job 라고 부른다.

 

이제 사용자와 상호작용하는 프로그램을 위해선 응답성을 위해서 어느정도 cpu 사용권을 줘야하는데 cpu 오래 잡고있는 프로그램들이 있기 때문에 스케쥴링은 효율성을 위해서 공평하기 보다는 이런 상호작용하는 프로그램에 조금 우선순위를 주는 방식으로 설계되어있다.

 

I/O bound job: i/o 가 중간에 많이 끼어들어 cpu 를 잡고있는 시간은 길지않지만 자주자주 가져다 쓰는것 주로 사용자와 상호작용

 

cpu bound job : cpu 길게 쓰는 계산작업하는 프로그램

 

cpu scheduler: 누구한테 cpu 를 줄지를 결정하는 놈 -> 운영체제 의 코드이다 (하드웨어 아님)

 

dispatcher : cpu를 넘겨주는 역할을 하는 놈 -> 운영체제 의 코드이다 (하드웨어 아님)
-> 컨텍스트 스위치 해주는 놈이다. 컨텍스트 저장하고 새로운 컨텍스트 올리고

 

cpu 스케쥴링이 필요한경우

-> I/O 작업하는경우

-> time out 된경우

-> I/O 가 끝난경우(바로 cpu를 주지는 않음 사실) -> 그냥 I/O 가 끝난경우 ready상태로만 변함 하지만 바로 넘어가는 경우도있음 priority 가 제일 높은 경우 추후에 priority 를 공부할것임

-> 걍 끝난경우

 

이제 용어가 중요함

cpu를 그냥 내가 쓸수없어서 내려놓는경우 nonpreemptive

강제로 뺴앗긴경우 preemptive 

이제 자주 등장 할것임

 

'cs > 운영체제' 카테고리의 다른 글

11강 CPU Scheduling 2/ Process Synchronization 1  (0) 2023.01.09
10강 CPU scheduling 1  (0) 2023.01.03
운영체제 8강 Process Management 1  (0) 2022.12.14
운영체제 7강 Process 3  (0) 2022.12.14
운영체제 6강 Process 2  (1) 2022.12.14