# 4-1 Process Management 1
프로세스 생성
부모 프로세스
- 부모가 자식을 만드는데, 보통 복제 생성
- 부모 1이 자식 여럿을 만들 수 있음 – 트리 형태
- 원칙적으로 자식과 자원을 공유하지는 않음
- 생성된 자식은 부모와 별개의 프로세스 = 경쟁 관계
- 공유하지 않는 모델이 일반적
- 부모가 기다리는 = wait = blocked 되는 모델도 있음
자식 프로세스
- 자식은 부모의 주소 공간을 그대로 복제
- 운영체제에 있는 데이터인 PCB, 자원 등도 똑같이 복사
- 이론적으로 이렇게 복제 생성하면 컴퓨터 내의 모든 프로세스는 다 같은 일만 해야 함
- 그렇기에 일단 복제 후 그 복제된 곳에 새로운 프로그램을 덮어씌울 수 있음
- 이렇게 서로 다른 프로그램이 한 컴퓨터에 존재 가능
- 복제 생성 = fork 시스템콜
- 복제 후 다른 프로그램으로 덮어 씌우기 = exec 이라는 시스템콜
- fork 와 exec 은 독립적이기에, 복제 후 덮어씌우지 않을 수도 있음
- exec 하면 완전 새로운 프로그램으로 바뀔 수 있음
- 사용자 프로세스가 직접 다른 프로세스를 생성하는 게 아니라, 운영체제 통해 생성
- 시스템콜이니까, 자식을 낳아달라 부탁하면 운영체제가 대신 낳아주는 역할
프로세스 종료
exit
- 메서드 마지막을 중괄호로 닫으면 프로그래머가 명시적으로 exit 시스템콜 하지 않아도 컴파일러가 중괄호 닫는 지점에 exit 이라는 시스템콜을 자동으로 넣어줌
- exit 으로 프로그램 종료되면 자식이 부모에게 어떤 데이터를 보냄
- 프로세스의 세계에서는 부모가 자식을 낳으면, 자식이 먼저 종료돼야 하기에, 프로세스가 종료되면 부모에게 데이터가 전달됨 = 그게 wait 시스템콜로 전달하는 것
- 자발적으로 프로세스가 종료되면 exit 시스템콜 해주면 됨
abort
- 비자발적으로 프로세스 종료되는 경우 = abort
- 자원의 할당치를 넘어선 요구를 하면 부모가 강제로 죽임
- 자식을 왜 낳았느냐? 일을 시키려고 : 자식에게 더 시킬 일이 없으면 부모가 자식을 죽임
- 부모 프로세스가 종료되는 경우 : 그 부모가 낳은 자식들 모두 죽인 후 부모가 죽음
# 4-2 Process Management 2
프로세스 생성
프로세스
- 복제 생성
- 여기서의 복제 = 프로세스의 문맥을 모두 복사
- 부모 프로세스의 주소 공간인 메모리의 코드와 스택을 그대로 복사해 자식 프로세스 생성
- 부모 프로세스의 CPU 문맥에서 현재 인스트럭션을 언제까지 수행했는지 나타내는 레지스터인 프로그램 카운터 또한 부모 것을 그대로 복사
부모와 자식의 자원 공유
- 프로세스가 하나 만들어지면 이는 독립적인 프로세스임
- 원칙적으로는 부모와 자식은 서로 경쟁하며 자원을 더 차지하려는 관계가 됨
- 원칙보다 조금 더 advanced 한 개념
- 자식이 부모의 코드, 데이터, 스택을 그대로 카피하면 메모리에 두 카피가 일어남 = 메모리 낭비
- 부모와 자식의 내용이 똑같으면 당장 카피할 필요는 없음
- 리눅스나 일부 모델에서는 모든 걸 부모에서 카피하는 게 아니라, 공유할 수 있는 모든 것은 가능하면 그대로 두고 공유함
- 그렇게 실행하다, 부모와 자식의 내용이 달라지면(사실 별개의 프로세스니까) 그때 부모와 공유하던 메모리 공간의 일부를 자식이 가지게 됨
- = Copy-On-Write 기법(COW)
- = Write 발생 시 그때 copy 하겠다
- = Write 발생(원래 있던 내용 변경)하면 그때 copy 해서(필요한 일부만) 새로운 걸 만들고, 그 전까진 공유된 자원 쓰겠다는 거임
- 일단 복제
- 운영체제에게 자식 프로세스 만들어 달라고 요청
- = 시스템콜
- = fork
- 새로운 걸 덮어씌움
- 일단 복제 생성 후, 필요한 경우에 새로운 프로그램을 덮어씌움
- = exec
fork() 시스템콜
- fork 를 사용해 사용자 프로그램이 프로세스를 만드는 코드
- 운영체제에게 새로운 프로세스 하나 만들어 달라는 요청 = fork 시스템콜
실행 순서
- 부모에서 fork 실행해 자식 생김
- 그럼 프로그램 카운터는 fork 를 가리키게 됨
- 부모는 fork 이후부터 작업 계속 실행하면 되는데, 자식은?
- 자식도 부모의 프로그램 카운터 정보를 복사 받았기에 fork 이루어진 그 이후부터 실행됨
- (부모 프로그램의 컨텍스트를 복제하기에)
- = 자식… 이라기보단 부모1 이 부모2 를 생성한 격
- = 나도 복제본이 아닌 원본이다! 라고 주장하게 됨
- fork 를 통한 복제 생성의 문제점이 이거임
- 운영체제가 복제본 만들어주면 부모와 자식을 구분해야
- fork 실행 후 부모와 자식의 return value 가 다름
- 부모는 fork 결과값 > 0
- 자식은 fork 결과값 = 0
- 이렇게 원본과 복제본 구분하며 다른 작업을 할 수 있음
- 부모
- print ➡️ fork ➡️ …
- 자식
- 프로그램 카운터가 fork 를 가리킴 = 나는 print 구문을 실행했다는 기억을 가지고 있으니 이건 실행 안 할 거야
- fork 이후부터 실행되기에 부모 위치에서의 print 문 실행 안 됨(사실 print 구문은 부모만 실행한 거지만)
exec() 시스템콜
exec 시스템콜
- 어떤 프로세스를 완전 새로운 프로그램으로 태어나게 해줌
- fork 로 자식 생성 후
- pid == 0 , 자식이면 execlp 실행 = exec 시스템콜 실행
- exec = 프로그램의 시작 부분부터 실행, 아예 새로운 삶을 사는 것
- 한 번 exec 하고 나면 다시 되돌릴 수 없음
- fork 후 ➡️ 자식에게 새로운 프로그램 덮어씌우기 위해 exec 실행 ➡️ fork 제외, 처음부터 코드 실행
- fork 없는 두 번째 코드
- 제일 마지막 print 구문은 실행 안 됨
- exec 실행하면 아예 새로운 프로그램이 되어버리기에 밑 코드는 실행할 수 없음 = 되돌아올 수 없음
- 세 번째 코드
- 1 ➡️ echo 실행 ➡️ 3 출력(2는 출력 불가)
- execlp 할 때는 프로그램 이름 두 번 적어주고, 그 프로그램에 전달할 argument 를 순차적으로 적어준 후, (char *) 0 적어줌
wait() 시스템콜
exit() 시스템콜
프로세스와 관련한 시스템콜
wait() 시스템콜
- 부모와 자식이 병렬적으로 실행되는 경우도 있지만
- 자식 프로세스를 낳은 후, 그 자식이 일을 다 수행하고 종료될 때까지 부모 프로세스가 기다리는 실행모델도 있음
프로세스 간 협력
독립적 프로세스
- 원칙적으로 독립적임
- 자식 낳고 나면 자기 먹고 살 건 알아서 챙기라 함
- 직접 코드, 데이터, 스택 만들고 CPU 할당 받으려 노력해야 함
- 원칙적으로 하나의 프로세스가 다른 프로세스에 영향 미치지 못함(부모가 자식 죽이는 경우 제외)
협력 프로세스
- 협력해야 효율적으로 실행되는 경우에는 이렇게 진행
- 서로 정보 주고받으며 실행
프로세스 간 협력 메커니즘
- IPC = 정보를 주고받을 수 있는 방법
- IPC 에는 두 가지 방법이 있음 : message passing / shared memory
- Message passing
- 프로세스 a 가 프로세스 b 에 메시지 전달 후
- 이에 영향 받아서 프로세스 b 가 실행
- 필요하면 프로세스 a 에게 메시지 전달 등
- 내가 다른 프로세스에게 메시지 전달할 수 있는 방법은 원칙적으로 없음
- 프로세스 간 전달 불가
- 그렇기에 커널 통해 메시지 전달
- 커널이 메신저 역할
- Shared memory
- 원칙적으로 프로세스는 독자적 주소 공간을 가지고 있기에
- 코드, 데이터, 스택을 각자 가지고 있어 자기 주소 공간만 볼 수 있는데
- Shared memory 는 그럼에도 불구하고 일부 주소 공간을 두 프로세스가 공유하는 방식
- 프로세스 a, b 각자 코드, 데이터, 스택 개별적으로 가지고 있으나, shared memory 라는 공유 영역을 물리적으로 별도로 매핑해둠으로써 각자의 주소 공간에서 같이 쓸 수 있음
- Shared memory 는 서로 신뢰할 수 있을 때만 사용
- Thread
- 한 프로세스의 주소 공간에서 여러 쓰레드들이 협력
- 쓰레드들 간에는 완전한 협력 가능
- 주소 공간이 완전 공유됨
Message Passing
Message passing
- 다른 프로세스에 정보 전달할 때 운영체제의 커널 통해 메시지 보냄
- 직접/간접 통신 모두 사용자 프로세스 간 무언가 전달 시, 운영체제 커널은 반드시 필요
- 다만 인터페이스 측면에서 직접/간접 방식에 차이가 있을뿐
Direct communication
- 직접 통신
- 메시지 전달하는 프로세스가 어떤 프로세스에게 무슨 메시지를 전달한다는 걸 명시
Indirect communication
- 간접 통신
- 메시지를 전달하는 프로세스가 직접 명시하지 않고, 메일박스에 정보 넣음
- 메일박스에서 정보 꺼내 보는 누군가가 지정된 게 아님
- 메일박스에서 아무나 꺼내가라
Interprocess Communication
CPU and I/O Bursts in Program Execution
Load store, add store, …
- CPU 에서 인스트럭션을 수행하는 기계어
I/O
- 오래 걸리는 작업
- 이 작업 동안 CPU 는 다른 프로세스가 사용
- CPU 를 쓰는 단계와 I/O 작업이 번갈아 작동
CPU burst
- CPU 쓰는 단계
I/O burst
- I/O 작업 진행
- 주로 사람이 사용하는 프로그램에서 CPU burst 와 I/O burst 활발히 일어남
- 한 작업 수행 후 I/O 통해 데이터 가져와 사용자의 화면에 뿌려주는 등
CPU-burst Time의 분포
I/O bound job
- CPU를 짧게 쓰는 대신 빈도가 잦음
- 얘가 문제야
- 주로 interactive 한 작업, 사용자 관련 작업 진행
- 가능하면 사람과 작업하는 이 작업에 더 CPU를 자주 줌으로써 대기시간을 줄여주고 사용자의 답답함을 낮추는 게 효율적 = CPU 스케줄링
CPU bound job
- CPU를 길게 쓰는 대신 빈도가 낮음
프로세스의 특성 분류
CPU bound job
- 중간에 I/O 작업 없어서, CPU를 연속적으로 쓸 수 있음
CPU Scheduler & Dispatcher
CPU scheduler
- 이건 하드웨어가 별도로 있나? 프로그램이 별도로 있나? 이런 걸 잘 알아야!
- 운영체제 안에 CPU 스케줄링하는 코드가 있는데, 그 부분을 일컬음
- CPU를 누구에게 줄지를 결정하는 코드
- 우선순위에 기반한 스케줄링
Dispatcher
- 실제 CPU를 주는 과정
- Context 저장 후 넘겨줘야
- CPU 안에 레지스터 값 세팅 후 넘기기
'CS' 카테고리의 다른 글
운영체제 - 반효경 #6 Process Synchronization (0) | 2023.05.13 |
---|---|
운영체제 - 반효경 #5 CPU Scheduling & Process Synchronization (0) | 2023.04.10 |
운영체제 - 반효경 #3 Process (0) | 2023.03.13 |
운영체제 - 반효경 #2 System Structure & Program Execution (0) | 2023.02.16 |
운영체제 - 반효경 #1 Introduction to Operating Systems (0) | 2023.02.08 |
댓글