프로그램 : 디스크에 저장되어 있는 프로그램
프로세스 : 현재 실행중인 프로그램
로더 : 프로그램을 메모리에 적재하는 역할
커널 : 프로세스의 생성부터 종료까지 (PCB)관리
PCB(Process Control Block) : 프로세스의 정보를 저장하는 자료구조
상태(state) : 프로세스가 중단되었다가 다시 실행될 때, 원래 상태를 복원할 수 있는 충분한 정보
프로그램과 프로세스의 차이는, 프로그램은 디스크에 저장되어 있는 것이고, 프로세스는 프로그램을(더블 클릭 등으로) 실행했을 때 생기는 것이다. 동일한 프로그램을 두 번 실행시킬 수도 있다.
프로세스 상태
struct task_struct {
pid t_pid;
long state;
unsigned int time_slice
struct task_struct *parent;
struct list_head children;
struct filed_struct *files;
struct mm_struct *mm;
}
실제로 PCB 는 더 많은 필드를 갖고 있지만 UNIX 계열에서 공통적으로 사용하는 것들은 위 코드에 있다.
t_pid : 프로세스 고유 id
state : 프로세스 상태
time_slice : 스케줄링 관련된 건데 이건 RR 스케줄링에서 사용하는 듯. 나중 강의에서 나옴.
parent : 부모 프로세스 정보
children : 자식 프로세스 정보
files : 파일 정보
mm : 할당된 메모리 공간에 대한 정보
new -> (ready -> running -> waiting) -> terminate
new : 프로세스가 생성될 때
ready : CPU의 자원을 받을 준비가 되어있을 때
running : 프로세스가 실행중일 때
waiting : 프로세스가 I/O 등의 작업으로 잠시 중단되었을 때
terminate : 프로세스가 종료되었을 때
프로세스가 running 상태가 되려면 반드싱 ready queue 를 거쳐야 한다. running 상태에서 프로세스가 중단 되면 waiting 상태가 되고, interupt 가 발생하면 ready queue 로 들어간다. wating 상태에서 다시 실행할 준비가 되면 ready queue 로 들어간다. waiting 상태에서 running 상태로 갈 수는 없다.
spawn(알을 낳다) : 부모가 자식 프로세스를 생성
parent : 부모 프로세스, 모든 프로세스는 부모 프로세스를 갖는다.
child : 자식 프로세스
orphan : 고아, 부모 프로세스가 자식 프로세스보다 먼저 죽은 경우. 원래는 자식 프로세스가 먼저 종료되어야 하고 부모 프로세스는 자식 프로세스가 종료될 때까지 wait() 해야한다.
wait : 자식 프로세스가 종료될 때까지 기다릴 뿐만 아니라, 자식 프로세스가 종료되면 사용 중이던 자원을 회수한다.
zombie : 자식 프로세스가 죽었음에도 불구하고 자원이 회수되지 않은 상태
Q. 모든 프로세스는 부모 프로세스를 갖는다고 했는데, 그럼 루트 프로세스는?
A. 아래에 나온다.
init process : 모든 프로세스의 부모(조상)
bios -> 부트로더 -> 커널 순서로 실행된다. 부트로더가 부트 프로시저를 수행하고 나면 init 프로세스로 바뀐다.
만약 자식 프로세스보다 부모 프로세스가 먼저 종료되면, 자식 프로세스는 프로세스 트리 구조에서 연결이 끊긴다. 이 자식 프로세스는 신호를 받고 종료된다.
자식 프로세스가 종료되었지만 부모가 wait 하고 있지 않으면 부모가 zombie 가 된다. 라고 하셨는데 이 부분이 잘 이해가 안 간다. 아마 부모가 종료된 자식의 메모리 등을 회수해야 하는데 회수되지 않은 상태(자원 누수)를 가리키는 것이 아닌가 싶다.
context
context switching 할 때 context 와 동일. 위에서 언급한 상태와 비슷한 개념으로 보면 될 것 같다.
- file descriptors : 사용할 수 있는 file fescriptor 에 대한 정보들 (input, output 등)
- permissions : 권한 (APIs, memory protection)
- environment : 환경변수 경로
- shared resources : 프로세스 간 공유하는 메모리 등
UNIX 예제
UNIX 의 프로세스 관리
실제로는 더 여러 가지 시스템 콜이 있지만 여기서 다루는 내용은 fork, exec, wait
fork()
fork 는 "갈라지다"라는 뜻을 가지고 있다. 하나의 프로세스가 두 개의 프로세스로 나뉜다.
int pid = fork()
위 코드에서 pid 값에 따라서 부모 프로세스인지 자식 프로세스인지 구분할 수 있다. 부모의 경우 자식 프로세스의 id 가 저장되고 자식의 경우 0 이 저장된다. 만약 에러가 발생할 경우 -1 이 저장된다.
fork() 의 구현
- PCB 초기화
- 메모리 할당
- 부모 프로세스의 메모리 복사 (상황에 따라 불필요한 부분은 복사하지 않을 수도 있다.)
- 부모 프로세스의 context 복사
- 레디큐에 넣기
exec() 의 구현
- fork() 에서 확보한 메모리 공간에 적재, 만약 라이브러리같이 이미 메모리에 적재된 데이터라면 메모리에서 불러와야 하고 그게 아니라면 디스크에서 읽어와야 한다.
- 프로그램을 실행할 때 사용한 옵션에 따라 설정을 해줘야 한다.
- EIP ESP 초기화
wait() : 자식 프로세스가 종료되기를 기다린다.
- 인천대학교 컴퓨터공학부 3학년 전공필수 과목인 박문주 교수님의 운영체제 강의를 듣고 작성한 글입니다.
'공부 > OS' 카테고리의 다른 글
[운영체제] 프로그램 로딩(program loading) (0) | 2021.04.19 |
---|---|
[운영체제] 운영체제 만들기 (0) | 2021.04.19 |
[운영체제] 스레드(thread) (0) | 2021.04.19 |
[운영체제] 컨텍스트 스위칭은 언제 일어나야 하는가? (0) | 2021.04.18 |
[운영체제] 컨텍스트 스위칭(context switching) (0) | 2021.04.18 |