본문 바로가기
카테고리 없음

Operating System - Ch03. Process

by NCTP 2022. 4. 27.

본 글은 Operating System Concepts 10판을 기준으로 작성되었습니다...!

"시험공부하면서 작성중"

 

 

Program: 디스크에 존재하는 실행 가능한 파일 (.exe), 메모리에 로드되면 프로세스가 된다. 정적입니다.

 

Process: 프로그램이 실행된 상태. 스레드 이전에는 스케줄링의 기본 단위였다. 커널이 process ID(PID)를 통해 프로세스를 관리한다. (Table 이용) 프로그램을 실행하게 되면 프로그램의 복사판인 프로세스를 만들어 메모리에 올리는 것. 동적인 존재입니다.

 

프로세스의 메모리 공간

Text (code): 실행할 코드의 모음

Data: 전역 변수들

Heap: 프로그램 실행 시 동적으로 할당되는 메모리

Stack: 함수 수행을 위해 사용되는 임시 저장소, 함수가 실행되면 데이터가 쌓였다가, 리턴하면 사라짐

 

 

프로세스의 상태를 나타내는 State diagram

new : 프로세스의 생성, 로드하고, 초기화 작업하고, PID부여받고 등등...

 

running : 프로세스가 실행중인 상태. ready에서 스케줄러에 의해 코어를 할당받으면 (dispatch) running.

 

ready : 새로운 프로세서에 할당되기를 기다리는 상태, 지금 당장 CPU에 올라가 일을 수행해도 되는 상태. waiting 상태인 다른 프로세스가 요청한 I/O가 완료되어 interrupt가 걸리면 running에서 ready로 온다. 또는 프로세스에게 주어진 time이 끝나 timer interrupt가 발생하면 ready로 온다.

 

waiting : I/O요청이 왔을 때나 이벤트를 기다릴 때만 이쪽으로 옴. I/O완료나 이벤트 완료를기다리는 상태. 끝나면 ready로 간다.

 

terminated : 프로세스가 종료됨.

 

 


 

Process Control Block(PCB)

아~주 많은 프로세스들이 동작하기 때문에 이들을 관리하기 위해서 PCB가 있다.

커널에서 관리되고 있는 프로세스의 모든 정보를 가지고 있는 구조체. 한 프로세스에 하나씩.

PCB는 이렇게 구성되어있다.

 

Process state : 프로세스의 상태

Process number

Program counter : 어디까지 했는지를 저장. 프로세스에서 다음에 실행할 명령어의 주소

CPU register : 실행할 명령어를 수행하는 데 어떤 값들을 사용해서 연산할 것인지를 저장, 프로그램 카운터와 함께 다시 로드됐을 때 스케줄링할 때 필요

CPU scheduling information : CPU 스케줄링을 위한 정보. 

Memory-management information

Accounting information : 멀티 유저 환경에서 필요한 정보

I/O status information : 연결되어 있는 I/O 장치에 대한 정보

등등

리눅스 2.4.18 기준 1456bytes만큼 차지한다. 데이터 많다!

 

 

Context Switch (CPU Switch)

 컴퓨터의 멀티태스킹을 위해 두 가지 프로세스를 빠르게 번갈아가며 수행하기 위해서 필요한 것이 바로 Context switching. 일반적으로 초당 100 or 1000번 정도 발생한다.

  현재 프로세스가 실행중일 때 인터럽트나 시스템 콜이 들어오면 PCB에 현재 프로세스의 정보(문맥)들을 저장하고, 다른 프로세스의 정보가 저장되어 있는 PCB에서 정보를 CPU에 로드하여 수행. 그 후 일이 끝나면 CPU의 레지스터 정보를 현재 프로세스의 PCB에 복사 후 다시 원래 프로세스의 PCB에서 정보를 불러와 CPU에 로드한 후 원래 프로세스를 다시 수행.

 

  단점: 무조건 오버헤드임. Context switch하는 동안에는 달리 유의미한 행동을 하지 않기 때문. Context switch할 때 하는 작업들(pcb에 정보를 저장하고, 꺼내는 것) 자체가 오버헤드다. 

 

 


 

Long-term scheduler (or job scheduler)

실행해야 하는 프로세스들이 많을 때 어떤 프로세스를 메모리에 올려줄지를 고르는 스케줄러.

ex) 메모리가 8G밖에 안되고, 내가 실행하고 싶은 프로그램이 1.5G일 때, 운영체제가 쓰는 1GB빼고 7GB의 공간에는 4개의 프로그램이 올라간다. 어떤 프로그램을 메모리에 올릴 것인가...

 

Short-term scheduler

레디 큐에 있는 프로세스들 중에서 어떤 녀석을 CPU에 올려줄 것인지를 고르는 스케줄러. 

 

Medium-term scheduler

쓰다보니 메모리에 올라간 프로그램이 점점 메모리를 많이 먹게 될때는 메모리에 있는 프로세스중 하나를 내려야 한다. 이를 처리하는 것이 Medium-term scheduler이다.

 

 

디스크에서 메모리로 올리는 것이 swap in, 그 반대가 swap out.

 

 


 

  프로세스는 PCB로 관리되는데, PCB들은 레디 큐 안에 로 doubly-linked-list로 연결이 되어 있다. CPU에서 바로 레디 큐로 돌아갈 수도 있지만, 대기 큐로 가는 경우도 있다. (I/O 요청이 있을 때) 이 때 대기 큐에서도 PCB들이 똑같이 doubly-linked-list로 연결이 되어 있다.

 

Queueing diagram

 

 

 


Operation on Processes

POSIX

 

Process creation : fork()

Process execution : exec()

Process termination : exit(), _exit(), abort(), wait()

Cooperating processes : Inter-Process Communication(IPC)

 

exit() : 프로세스가 종료되기 위한 여러 사후처리를 한 뒤에 종료, 이 안에서 _exit()역시 호출함.

_exit() : 그냥 종료, 사후처리같은건 없다!

abort() : 비정상적으로 종료된, 뭔가 잘못된 상황에 활용됨. 오류 코드를 보고하며 이 안에서도 _exit()을 호출함. 일반 프            로그램에서는 사용하지 않고, 경우에 따라 라이브러리 구현에 사용된다. 

return from main() : 정상 종료, 메인 함수의 끝.

wait() : 자식 프로세스가 끝날 떄까지 기다림. 만약 부모가 wait하지 않으면 자식 프로세스가 zombie상태가 되고                   invoking wait없이 부모가 종료되면 자식 프로세스가 orphan상태가 됨. 

 

 

int fork(): int를 반환하는 함수형 시스템 콜.

 - PCB를 만들고 초기화함

 - 새로운 메모리 공간을 만들고 초기화함

 - 부모와 완전 같은 정보를 복사한 자식을 만들고 자식 PCB를 레디 큐에 넣는다. 

 - 부모의 fork()가 끝나면 자식의 PID를 반환하고, 자식의 fork()가 끝나면 정수값 0이 반환된다.

 

fork()는 부모와 자식이 협력해서 무언가를 처리할 때 아주 유용함.

 

int exec(char *prog, char *argv[]): 보통 fork()와 같이 실행됨, prog을 메모리 위에 올려서 실행해줘!

 - 현재 프로세스를 멈춘다.

 - prog을 메모리 주소로 로드한다. (prog는 프로그램)

 - 하드웨어 문맥과 새로운 프로그램에 필요한 인수들을 집어넣고 초기화함.

 - 새로운 프로그램을 로드한 이 프로세스는 실행 가능한 상태가 됬으니 레디 큐에 집어 넣음.

 

*exec()은 새로운 프로세스를 생성하는 것이 아니라 지금 exec()하고 있는 프로세스에 새로운 프로그램을 덮어쓰는 것. 따라서 일반적으로 fork()->exec()임. 

Process Tree in UNIX/LINUX

 

WINDOWS

 

Creation/Execution

bool CreateProcess()char *prog, char *args,...) --> fork() + exec()

 

 

 

 

 


 

 

 

Inter Process Communication (IPC)

 

프로세스가 다른 프로세스와 데이터를 공유하면 협력적(cooperating), 그렇지 않으면 독립적(independent)라고 한다.

프로세스간 협력은 필요한데, 그 이유를 세 가지 들어보면 : 

1. Information sharing : 여러 어플리케이션이 같은 정보를 사용하거나 동시에 접근할 수 있는 방법을 제공해야 한다.

2. Computation speedup : 멀티코어의 경우 특정 작업을 빠르게 처리하기 위해서 병렬적으로 처리함.

3. Modularity: 시스템 함수들을 분리된 프로세스나 스레드로 나눔

 

프로세스간의 협력에는 IPC가 있어야한다. IPC에는 두 가지 커뮤니케이션 모델이 있는데, Message passing과 Shared memory가 있다. 대부분의 운영체제에서 둘 다 구현이 되어있다. 

 

Message passing & Shared memory

 

  Message passing : 작은 데이터를 주고받을 때 유용하다. 또한 shared memory처럼 두 프로세스가 메모리에 붙어있을 필요가 없음므로 분산 체계의 경우 구현하기 좋다. 시스템 콜을 사용하기 때문에 커널과 함께 작업하므로 shared memory에 비해 시간이 더 걸린다.

  Shared memory : Message passing보다는 빠르다. shared memory를 만들면 시스템 호출할 일이 없다.

 

  

 

 

 

 

 

 

 

 

 

 

댓글