티스토리 뷰
● 도입
- 일반적으로 프로세스가 생성될 때 아래와 같은 과정으로 생성된다.
1. .exe 파일을 더블 클릭해서 실행
2. OS가 해당 프로그램의 코드 영역과 데이터 영역을 메모리에 로드하고 빈 stack과 빈 heap을 만들어 공간을 확보한다.
3. 해당 프로세스 관리를 위한 PCB를 만들어서 값을 초기화한다.
(프로그램이 메모리에 올라갔으므로 프로세스라고 부른다.)
- 위에서 설명한 프로세스 생성 과정은 OS가 부팅된 후 0번 프로세스가 생성될 때 딱 한 번만 실행된다.
- 나머지 모든 프로세스들은 새로 생성하지 않고 0번 프로세스를 복사해서 사용하게 된다.
- 복사에는 fork() 함수를 사용한다.
- 아래 그림의 1번, 2번, 3번 프로세스 모두 0번 프로세스를 복붙해서 생성된 프로세스들이다.
- 0번 프로세스를 복사해서 생성된 1~3번 프로세스를 자식 프로세스라고 한다.
- 반대로 자식 프로세스 입장에서 0번 프로세스는 부모 프로세스가 된다.
- 프로세스를 복사하는 이유는 새로 생성하는 것보다 복사를 하는게 속도가 더 빠르기 때문이다.
- 자식 프로세스는 부모 프로세스의 코드 영역, 데이터 영역, 스택 영역, PCB의 모든 내용을 전부 복사한다.
Q. 0번 프로세스의 코드와 데이터를 모두 복사해서 자식 프로세스가 생성되는데
이러면 자식 프로세스를 실행하면 결국에는 0번 프로세스가 똑같이 실행되는거 아닌가?
A.
- 맞음. 0번 프로세스를 그대로 복붙했으니 자식 프로세스를 실행해도 0번 프로세스가 실행된다.
- 그렇다면 자식 프로세스가 자신이 원하는 코드를 실행하는 방법은 무엇일까?
- 바로 exec() 함수를 이용하는 것이다.
- fork 함수를 이용해 0번 프로세스(부모 프로세스)를 복사한 후 exec 함수를 실행시키면 부모를 복사한 자식 프로세스의 코드와 데이터 영역을 원하는 값으로 덮어쓸 수 있다.
- 이때부터 자식 프로세스는 부모 프로세스와 완전히 다르게 동작하게 된다.
● fork, exec 자세히 알아보기
- 아래 코드를 보면서 자세히 알아보자
1. 왼쪽 부모 프로세스의 8번 라인에서 fork 함수를 호출
2. OS는 부모 프로세스와 동일한 프로세스를 복사(오른쪽 자식 프로세스)
3. fork 함수의 반환값으로 부모 프로세스에게는 0이 아닌 값을, 자식 프로세스에게는 0을 반환한다.
4. 이제 2개의 프로세스는 CPU 스케줄링에 따라 실행되는데 어떤 프로세스가 먼저 실행될지는 OS의 결정에 달렸다.
- 부모 프로세스가 먼저 실행된다고 가정해보자(위 사진에서 왼쪽 부모 프로세스의 코드가 실행되는 상태)
1. 부모 프로세스는 fork 함수의 반환값으로 1을 받았다.
2. 10번 라인의 (if문 = false)가 되어 17번 라인의 wait() 함수를 호출한다.
3-1. 여기서 wait() 함수는 자식 프로세스에게서 exit() 신호가 올때까지 기다리는 시스템 함수이다.
3-2. Context switching을 거쳐 부모 프로세스에게 CPU가 할당되어도 자식 프로세스의 exit() 신호가 오기 전까지는 다른 코드를 실행하지 않는다.
4. CPU 스케줄링으로 자식 프로세스가 실행된 상황이 됐다.
5. 자식 프로세스는 fork 함수의 반환값 = 0 이기에 12번 라인이 실행된다.
6. execlp() 함수로 InternetBrowser 프로그램을 실행시킨다.
7. InternetBrowser 프로그램에서 코드와 데이터 영역을 가져와 자식 프로세스를 덮어쓰게 된다.
7-1. 이제부터 부모 프로세스와는 완전히 다른 코드가 실행되는 것이다.
cf) fork 함수를 이용해 0번 프로세스(부모 프로세스)를 복사한 후 exec 함수를 실행시키면 부모를 복사한 자식 프로세스의 코드와 데이터 영역을 원하는 값으로 덮어쓸 수 있다.
8. InternetBrowser를 사용하다가 종료가 되면 13번 라인의 exit() 함수를 호출하고 프로세스의 종료를 알린다.
(나 작업 끝났다.)
9. CPU 스케줄링으로 다시 부모 프로세스가 실행된 상황이 됐다.
10. 현재 부모 프로세스는 wait() 함수로 자식 프로세스의 종료를 기다리고 있는데 마침 자식 프로세스에서 exit() 함수를 호출해 프로세스를 종료시켰으니 부모 프로세스는 자식 프로세스를 완전히 종료시킨다.
11. 이제 18번 라인의 printf() 함수를 실행시킨다.
12. 19번 라인의 exit() 함수로 프로세스 종료를 알린다.(나 작업 끝났다.)
● 좀비 프로세스
- exit() 함수는 자식 프로세스가 부모 프로세스에게 정상 종료를 알리는 함수이다.
- 부모 프로세스는 자식 프로세스의 Exit Status를 읽고 자식 프로세스를 정리한다.(Exit Status = 0 정상 종료)
- 만약 부모 프로세스가 자식 프로세스보다 먼저 종료되거나 자식 프로세스가 비정상적으로 종료돼 exit() 신호를 주지 못해
Exit Status를 읽지 못해 메모리에 계속 살아있는 상태를 좀비 프로세스라고 부른다.
- 컴퓨터를 오래 켜두면 속도가 느려지는데 이는 여러 프로세스가 메모리에 올라온 것도 있고 좀비 프로세스가 많아져서 메모리를 차지하는 경우가 있다.
- 재부팅하면 메모리가 초기화되기 때문에 속도가 다시 빨라진다.
'CS > 운영체제' 카테고리의 다른 글
#12 CPU 스케줄링 개요 (0) | 2023.03.09 |
---|---|
#11 프로세스와 Thread (0) | 2023.03.03 |
#9 컨텍스트 스위칭(Context switching) (0) | 2023.02.26 |
#8 프로세스 상태 with 시분할 처리 (0) | 2023.02.24 |
#7 PCB(Process Control Block) - 프로세스 제어 블록 (0) | 2023.02.22 |
- Total
- Today
- Yesterday
- Phaser
- nosql
- 운영체제
- 빅데이터
- spring
- 프로그래머스
- db
- OS
- MongoDB
- 메모리
- 빅데이터 분석기사
- Stream
- SQL
- DART
- java
- 코테
- API
- node.js
- 알고리즘
- Java8
- 프로세스
- git
- 자료구조
- 코딩테스트
- jpa
- MySQL
- SpringBoot
- Spring Boot
- Phaser3
- Advanced Stream
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |