운영체제 챕터3 Process

김규회·2023년 3월 16일
0
post-thumbnail

3.1 Process Concept

프로세스란?

  • 현대 컴퓨터 시스템이 일의 단위
  • 실행 중인 프로그램

그러면 왜 프로세스가 필요한가?

  • 멀티로 프로세스를 실행하다보니, 구분 단위가 필요해짐.

3.1.1 The Process

Memory Layout of a process

  • Memory Space Size는 총 4GB로 32bit 주소체계를 가지고 있다.

OS Kernal Space

  • 총 1GB짜리 영역으로 사용불가하다.(커널의 코드가 들어가 있기 때문)
  • 커널의 공간 안에 Kernal Stack이라는 것이 존재하는데 System Call이나 커널 함수를 처리할 때 쓰인다. => 보안상의 이유 때문에(8KB Size)

Text Section

  • 실행 가능한 코드가 들어있다.
  • 바이너리 프로그램 코드가 돌아가는 영역이다.

Data Section

  • 실행하거나 실행되지 않은 전역 변수들이 존재한다.

Heap Section

  • 프로그램이 실행될 때 메모리가 동적으로 할당된다.
  • 동적 메모리가 할당될 때 위로 성장한다.

Stack Section

  • Heap과 마찬가지로 메모리가 동적으로 할당된다.
  • (function parameter, return 주소값) 등 다양한 함수들이 일시적으로 저장되었다가 쓰인다.
  • 메모리가 할당될 때 밑으로 성장한다.

그래서 3.1.1 단원을 통해 알 수 있는 process의 개념

program -> passive entity(수동적인 실체)

  • 명령 리스트를 disk안에 저장하는 일을 함.

process -> active entity(능동적인 실체)이다.

  • 명령을 실행하고 자원을 할당을 해줌.

program이 process가 되는 경우

  • 실행 파일(안에 command line 있음.)이 메모리로 할당될 때

3.1.2 Process State

  • New : 프로세스가 실행되었을 때
  • Ready: 실제 일을 할 수 있는 상태
  • Waiting: Running 도중에 디스크에 가서 데이터를 읽어와야 할 때
  • Running: 실행 중 일때
  • Terminated: 종료된 상태
  • interrupt: OS가 Ready queue 상태로 다시 돌려 놓음.
  • scheduled: OS가 CPU를 할당해줌
  • I/O or event wait : 디스크에 있는 데이터를 가져와야 할 때 기다림.

3.1.3 Process Control Block

PCB란?

프로세스와 관련된 정보를 담은 구조체를 process control block(pcb)라고 한다.

  • Process State : new, ready, running, waiting, halted 등의 상태를 담고 있다.
  • Program Counter: 이 프로세스를 실행하기 위한 다음 명령어의 주소값을 가지고 있다.
  • CPU Register : 레지스터가 종류에 따라 다양하고, 컴퓨터 아키텍쳐에 의존한다. accumulater, index register, stack pointer, 일반적인 레지스터등을 포함하고 있다.
  • CPU Scheduling information : process priority, queue를 스케쥴링 하기 위한 pointers 등의 정보를 포함하고 있다.(자세한건 5단원에서 다룰 예정이다.)
  • Memory-management information : 기본값과 제한된 레지스터, page tables, segment tables에 대한 정보를 담고 있다.(자세한 내용은 챕터 9에서 다룰 예정이다.)
  • Acounting information : CPU, 실사용 시간, Time limits, account numbers, job or process numbers등의 정보를 담고 있다.
  • I/O status information : I/O device가 process에게 할당할 리스트, 오픈 파일 정보 리스트를 담고있다.

3.1.4 Thread

Thread란?

  • 스레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미한다.
  • 모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행한다.
  • 또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 한다.
    -> 멀티 코어를 통해 스레드를 병렬로 배치하여 돌릴 수 있게 되었다고 함.

Thread의 detail은 4단원에서 다뤄볼 예정이다.

3.2 Process Scheduling

Multi Programming

  • 여러 프로그램을 여러 프로세스로 수행한다.

Multi Programming 하는 이유

  • CPU의 활용감을 극대화 하기 위해서 -> 로딩되어 있는 다른 프로세스를 곧바로 돌려서 CPU가 놀지 못하도록 한다.

Time-sharing

  • 멀티 프로그래밍 상태에서 process switch를 빠르게 수행을 한다.

Time-sharing 하는 이유

  • 프로세스를 병렬로 수행하는 것처럼 보이기 위해서

이 2가지 목적을 달성하기 위해서는 process scheduler가 필요하다.


프로세스 스케줄려는 코어에서 실행가능한 여러 프로세스 중에서 하나의 프로세스를 선택해서 실행한다.

  • 단일 CPU 코어가 있는 시스템의 경우에는 한 번에 2개 이상 프로세스는 실행할 수 없다.
  • 현재 메모리에 있는 프로세스 수를 다중 프로그래밍 정도라고 한다.

++ 그러나 멀티 프로그래밍 및 시간 공유의 목표를 균형있게 유지하려면 I/O Bound나 CPU Bound를 고려해야한다.
(바운드는 ~위주의 라는 뜻으로 받아주면 된다.)

=> 즉 I/O bound process는 계산보다 I/O에 더 많은 시간을 소비하는 프로세스 이다.
반대로 CPU-bound process는 계산에 더 많은 시간을 사용하여 I/O request를 많이 만들지 않는다.


3.2.1 Scheduling Queue

프로세스는 결국 queue에 들어간다.

프로세스가 시스템에 들어가면 ready queue에 들어가서 준비 상태가 되어 실행되기를 기다린다.
일반적으로 linked list에 저장이 된다.
-> ready queue header에는 리스트의 첫 번째 pcb를 가리키는 포인터가 저장되고 각 pcb에는 다음 pcb를 가리키는 포인터가 있다.


프로세스에는 CPU 코어가 할당되어 프로세스가 실행되면 종료되거나 I/O Request가 완료 되는 이벤트도 기다린다.

프로세스가 디스크 같은 장치에 I/O 요청을 한다고 가정을 할때 프로세스가 I/O request보다 더 빠르므로 disk에 I/O request 시간 동안 대기 상태가 발생할 수 있다.
그래서 프로세서는 프로세스를 계속 코어에 올려놓는 것이 아닌 ready queue에 올려놓는다. -> 다른 프로세스를 실행하게 할 수 있다.

Queuing Diagram

프로세스 scheduling의 일반적인 예시가 queuing diagram이다.

  • 프로세스가 처음에 I/O request 후 wait queue에 들어간다.
  • Child 프로세스를 생성한 다음 똑같이 Child process의 종료를 기다리는 wait queue에 들어간다.
  • 이때 인터럽트가 발생되거나 time slice가 만료 되었을때는 프로세스가 코어에서 강제로 제거되어 ready queue로 돌아간다.

위의 세가지 중 2가지 경우는 wait queue에서 다시 ready queue로 돌아간 뒤 이 주기를 프로세스가 종료될 때까지 반복한다.

이때 프로세스가 종료되면 모든 queue에서 제거되고 PCB 및 자원이 반환된다.

3.2.2 CPU Scheduling

실제로 프로세스를 실행하는 CPU도 CPU scheduling이 있다.

CPU Scheduling의 역할

  • ready queue에 있는 process 중에서 선택된 하나의 프로세스에 cpu 코어를 할당하는 것이다.
    -> cpu scheduling도 많이 실행되어야 process scheduling과 함께 효율적으로 관리할 수 있다.

Swapping 이란?

스케쥴러의 형태 인데 챕터 9에서 자세하게 다룰 예정이다.

메모리에 적재된 프로세스를 관리하는 것 : 프로세스 스케쥴링이라고 보면 되겠다.

3.2.3 Context Switch

Context Switch란?

  • CPU 코어를 다른 프로세스로 교환하려면, 이전의 프로세스 상태를 보관하고 새로운 프로세스의 보관된 상태를 복구하는 작업을 말한다.

  • Context Switch가 발생하면, 커널은 과거의 프로세스의 Context를 PCB에 저장하고 새로운 프로세스의 Context를 불러온다.

  • 이때 Context Switch가 일어날 때는 시스템이 오버헤드가 발생하게 된다.

3.3 Operations on Process

운영체제는 프로세스를 생성 또는 종료를 위한 기법들이 존재한다.

3.3.1 Process Creation

프로세스는 여러 개의 새로운 프로세스들을 생성할 수 있다.


EX) 리눅스 시스템의 tree 구조의 프로세스이다.

  • 이들을 예로 들자면 시스템이 부팅되면 systemd 프로세스는 다양한 사용자 프로세스를 생성한다.

여기서 보면 Parent Process는 Child Process를 생성하게 되는데 이를 통해 tree 구조의 process를 만들게 된다.

  • 이때 parent process는 child process에게 모든 자원을 공유한다.
  • child process는 이때 resource를 직접 운영체제로 부터 얻거나, parent proess의 가진 resource의 일부분만 사용하도록 제한될 수 있다.

프로세스가 새로운 프로세스를 만들때
두 가지의 실행 방법이 존재한다 :
1. parent와 children process가 같이 수행하거나
2. parent가 children process가 종료될 때까지 기다리는 2가지의 형식을 가지고 있다.
__
또한 새로운 프로세스에 대한 두 가지의 주소 공간의 가능성도 가지고 있다:
1. child process는 parent process의 공간을 복제할 수 있다.(이때 부모의 code, data, stack을 복사한다.)
2. child process가 새로운 프로그램을 load할 수도 있다.


Process Creation in UNIX/LINUX system

fork() System Call

  • 새로운 프로세스를 형성한다.
    -> parent process를 완전히 복제한다.
    -> parent와 child는 fork 이후 동시에 작동한다.
    -> fork()이후 return value는 2개이다.
    ( parent process => child process의 번호, child process => pid = 0)

exec() System Call

  • 자기 자신의 메모리에 있는 공간을 모두 비우고 지정된 파일을 읽어서 그걸로 채운다.
  • system call이 실패했을 때는 return 값이 나온다. -> 오류 처리용

wait() System Call

  • parent가 child가 끝날때까지 기다릴 수 있도록 해준다.

fork() 시스템 호출을 사용한 프로세스 생성

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main() {
	pid_t pid; (이때 pid를 저장하기 위한 integer 변수)
	pid = fork()
	if (pid<0) { 
			fprintf(stderr, “Fork failed”);
			return 1;
	} /* error 부분*/
	else if (pid==0) { 
			execlp(“/bin/ls”,”ls”,NULL);/* exec의 변종, 백지되고, ls코드로 바꿔치기 */
	}/* child 부분*/
	else { 
			wait(NULL); /*child가 끝날때까지 기다림.*/
			printf(“Child complete”);
	}/* parent 부분*/
	return 0;
} /*exit호출을 받음*/

3.3.2 Process Termination

일반적으로 프로세스가 마지막 명령을 수행한 후 OS에게 exit() 명령어를 이용하여 알려준다. (system call)

  • child가 parent에게 output data를 보내고
  • 프로세스의 각종 자원들이 할당해제가 되어 다시 OS에게 반환된다.

하지만
프로세스가 exit()를 하지 않더라도 종료되는 경우가 있는데
다른 프로세스가 적당한 시스템 호출로 다른 프로세스의 종료를 유발할 수 있다. -> Parent process
parent process만이 children process를 종료시킬 수 있다.
process가 process를 만들 때에는 PID가 꼭 부모에게 전달되어야 한다.
-> 아니면 사용자 또는 오작동으로 다른 프로세스가 종료될 수 있다. 이를 kill이라고 한다.

parent process가 children process를 종료시키는 대표적인 3가지 경우

  1. child가 자신에게 할당된 자원을 초과하여 사용할 때
    ->parent는 child의 상태를 알 수 있어야 초과 여부를 알 수 있다.
  2. child에게 할당된 task가 없을 때
    ->child가 하는 일이 없을 때
  3. parent가 exit하는데, 운영체제는 부모가 exit한 후에 child가 실행하는 것을 허용하지 않을 때
    -> 운영체제마다 다르다.

Cascading termination

몇몇 시스템에서는 parent 없이는 child process가 실행될 수 없다. 그래서 종료된다.

Zombie process

프로세스가 종료하면 사용하던 자원이 운영체제가 다시 가져가는데 프로세스의 종료 상태가 저장되는 프로세스 테이블의 해당 항목은 parent process가 wait()를 호출할 때 까지 남아 있게 된다.
-> 정리하자면 프로세스는 종료되었지만 parent process가 아직 wait()을 호출하지 않을 프로세스가 있다는 말이다.

이때 parent process가 wait()을 호출하지 않고 종료한다면

-> 그 child process는 orphan(고아)가 된다.

  • 계속 wait()을 하지 않는다면 init process가 wait()해서 받아온 뒤 다 처리한다.

3.4 Interprocess Communication

프로세스들은 독립적일 수도 있고 상호 협조적일 수도 있습니다.
cooperating한 프로세스들은 공유 data를 포함해 프로세스들 끼리 영향을 준다.
cooperating한 프로세스들이 허락하고 환경을 제공하는 몇가지 이유들이 있다.

  • 정보 공유
  • computation 속도 향상
  • 모듈화
    이를 위해 IPC가 필요로 하는데

IPC란?

IPC는 Inter-Process Communication 의 줄임말로 프로세스간의 통신을 위한 메커니즘을 의미한다. 즉 IPC는 프로세스간의 통신을 돕는다.

IPC 모델은 크게 두가지 방법이 존재한다. 첫째는 Message Passing 방식이고 다른 하나는 Shared Memory 방식이다.
Message Passing 방식은 모든 메시지 전송에 대해 시스템 호출이 필요하므로 속도가 느리지만 설정이 더 간단하고 여러 컴퓨터에서 잘 작동한다.
Shared Memory 방식은 인접한 process 사이에shared된 공간이 존재해서 system call을 부를 필요가 없다. -> 커널에 대한 의존성이 낮다. 그만큼 속도도 빠르고 communication에 대한 편의도 가져올 수 있다. 그러나 위의 그림처럼 생성공간에 대한 제한이 존재한다.

3.5 IPC in Shared Memory Systems

Shared Memory란?

Shared Memory 방식은 말 그대로 프로세스들이 공유하는 메모리를 이용해 통신하는 것이다. 이때 공유할 item을 생성하는 생산자(producer) 프로세스와 생성한 item을 소비하는 소비자(consumer) 프로세스가 나뉘게 된다.

  • 일반적으로 shared memory system에서 shared memory는 처음에는 특정 프로세스 공간 내에 있으며, 해당 메모리를 하나 이상의 다른 프로세스에서 공개적으로 사용할 수 있도록 하려면 system call을 수행해야 된다.
  • shared memory를 사용하려는 다른 프로세스는 shared memory 영역을 address 공간에 연결하기 위해 자체 system call을 만들어야 한다.

3.6 IPC in Message-Passing Systems

프로세스들 끼리 대화하고 동기화가 이루어지도록 하는 메커니즘이다. 이 때 message passing 방식은 send(전송), receive(수신) 연산을 통해 통신하게 된다. 만약 프로세스 P와 Q가 통신하고 싶다면, 둘은 communication link를 둘 사이에 만들어야 한다.

3.6.1 Naming

Direct Communication

프로세스간 서로의 이름을 명확히(explicitly) 알고, 직접 통신한다.

  • send(P, Message) : 프로세스 P에게 메시지를 전송
  • receive(Q, Message) : 프로세스 Q로부터 메시지 수신

Indirect Communication

메시지가 mailBox를 통해 송수신 된다.

  • 모든 mailBox 는 고유한 id를 가진다.
  • mailBox를 공유해야지만 프로세스간에 통신할 수 있다.
  • send(A, Message) : mailBox A에게 메시지를 전송
  • receive(A, Message) : mailBox A로부터 메시지 수신

3.6.2 Synchronization

message passing은 synchronize와 asychronize로 알려진 blocking과 non blocking으로 나눌 수 있다.

Blocking : synchronous 하다고 생각 할 수 있다.

  • Blocking send : 메시지를 송신한 프로세스는 수신 측 프로세스가 메시지를 받을 때까지 기다린다.
  • Blocking receive : 수신 측 프로세스는 메시지를 받을 때까지 기다린다.

Non-Blocking : asynchronous 하다고 생각 할 수 있다.

  • Non-Blocking send : 메시지를 송신한 프로세스는 다시 자기 할 일(operation)을 한다.
  • Non-Blocking receive : 수신 측 프로세스는 valid(유효한) 메시지나 NULL 메시지를 받는다.

3.6.3 Buffering

communication은 direct 또는 indirect하게 되는데, message에 의한 communicating process는 temporary queue에 상주한다. 이때 기본적으로, queue는 3가지 방법으로 구현된다.

zero capacity : 0개의 메시지

  • 송신 측은 무조건 수신자를 기다려야 한다.

Bounded capacity : n개의 메시지

  • 송신 측은 link 가 꽉차면 기다려야 한다.

Unbounded capacity : 무한한 길이

  • 송신 측은 절대 기다리지 않는다.

3.7 Examples of IPC System

3.7.1 POSIX Shared Memory

  1. POSIX 시스템에서 shared memory에 대한 대체 접근 방식을 보여준다. 이 접근방식에서 shared memory를 사용하는 첫번째 단계는 다른 파일 열기 명령과 유사한 방식으로 shm_open()을 사용해서 공유 메모리 개체를 만드는 것이다.
fd = shm_open(name,O_CREAT | O_RDRW,0666);
  1. 다음 단계는 ftruncate()를 사용하여 파일 크기를 설정하는 것이다.
ftruncate( fd, 4096 );

마지막으로 mmap() system call은 사용자 프로그램 공간의 메모리 주소에 매핑하고 공유한다.

ptr = mmap( 0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0 );

Mach Message Pssing

  • 모든 시스템 호출 및 프로세스 간 통신을 포함하여 Mach의 대부분의 통신은 포트라고도 하는 사서함으로 전송된 메시지를 통해 수행된다.
  • 작업( 프로세스 )이 생성될 때마다 커널 사서함과 알림 사서함이라는 두 개의 특수 사서함을 자동으로 가져온다.
    -> 커널은 커널 메일함을 사용하여 작업과 통신한다.
    -> 커널은 알림 메일함으로 이벤트 알림을 보낸다.
  • 메시지 전송에는 세 가지 시스템 호출이 사용된다.
    -> msg_send( )는 사서함으로 메시지를 보낸다.
    -> msg_receive( )는 메시지를 수신한다.
    -> msg_rpc( )는 메시지를 보내고 발신자의 응답으로 정확히 하나의 메시지를 기다린다.
  • Port_allocate( )는 메시지를 보관하기 위한 새 사서함 및 관련 큐를 생성한다
  • 한 번에 하나의 작업만 지정된 사서함에서 메시지를 소유하거나 받을 수 있지만 양도할 수 있다.
  • 동일한 발신자가 동일한 수신자에게 보낸 메시지는 FIFO 순서로 도착하는 것이 보장되지만 여러 발신자의 메시지에 대해서는 보장되지 않는다.
  • 메시지는 고정 길이 헤더와 가변 길이 데이터로 구성된다.
    ->헤더에는 수신자와 발신자의 사서함 번호(주소)가 포함된다.
    ->데이터 섹션은 각각 유형, 크기 및 값을 포함하는 유형이 지정된 데이터 항목 목록으로 구성된다.
  • 수신자의 사서함이 가득 찬 경우 발신자는 다음 네 가지 선택 사항이 있다.
    ->사서함에 공간이 생길 때까지 무한정 기다린다.
    ->최대 N밀리초 동안 기다린다.
    -> 기다리지 않는다.
    ->사서함을 사용할 수 있을 때 배달할 수 있도록 메시지를 커널과 함께 임시로 캐시한다.
    ++ 주어진 시간에 주어진 발신자로부터 주어진 수신자에게 이러한 메시지 하나만 보류될 수 있다.
    ++ 일반적으로 "클라이언트"에게 작업 완료를 알려야 하지만 사서함을 사용할 수 있을 때까지 기다릴 수 없는 인쇄 스풀러와 같은 특정 시스템 작업에서만 사용된다.

Pipes

프로세스 간의 단방향 커뮤니케이션

Ordinary Pipe

  • 한 쪽에서는 보내고, 다른 한 쪽에서는 받기로만 한다.
  • Unix 시스템에서는 일반 파이프를 pipe(int fd[ ])함수를 사용하여 구성된다. 이 때 int fd[ ] 를 통해 액세스 되는 파이프를 만든다. 여기서 fd[0]은 읽기끝이고, fd[1]은 쓰기끝이다.
  • 일반 파이프는 이를 만든 프로세스 외부에서 액세스를 할 수 없다.
  • 상위 프로세스는 파이프를 생성하고 fork()를 통해 하위 프로세스와 통신한다.
  • child process는 parent로부터 파일을 상속받는데 파이프도 같이 상속받는다.

Named Pipe

Ordinary pipe의 업그레이드 버전이다.

  • 양방향 통신이 가능하고
  • parent child 관계가 필요가 없다.
  • 독립된 개체라서 life cycle이 process와 무관하다.
    -> 만든 프로세스와 관계 없다.
  • mkfifo() system call을 사용한다.
  • open(), read(), write(), close() system call을 사용할 수 있다.
  • 한 기계 안에 있는 프로세스 간에만 가능하다
    -> 다른 기계들끼리 사용할려면 socket 통신을 이용해야 한다.

3.8 Communication in Client Server System

Socket

  • 소켓은 통신을 위한 끝점이다.
  • 네트워크를 통해 통신하는 두 프로세스는 종종 연결된 소켓 쌍을 통신 채널로 사용한다.
  • 위의 그림과 같이 소켓은 포트 번호와 연결된 IP 주소로 식별된다.

소켓을 통한 통신 채널은 2가지 형식으로 나눌 수 있는데

TCP

  • Connection oriented 연결을 통해 전송된 모든 패킷은 다른 쪽 끝 부분으로 전송되고 전송된 순서로 수신된 process에게 전달된다.
  • 이때 TCP 게층은 전송된 모든 패킷을 확인하고, 필요한 경우 패킷을 다시 보내고, 수신된 패킷을 적절한 순서로 정렬하는 단계를 수행한다. ** 여기서 오버헤드가 발생되며 하나의 패킷이 누락되는 순간 시간이 지연된다.

UDP

  • TCP보다는 빠르지만 특정 패킷이 손상되지 않을 것이라는 보장도 없고 순서대로 전달된다는 보장도 없어서 전송 후 자체 오류 검사나 복구 절차를 구현해야된다.

Remote Procedure Calls(RPC)

별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 함수나 procedure를 실행할 수 있게 하는 process간 통신 기술을 말한다.
정리하자면, RPC를 이용하면 로컬이든 원격이든 상관없이 동일하게 기능을 수행할 수 있다는 점이다.

RPC 사용하는 곳

일반적으로 process는 자신의 주소공간 안에 존재하는 함수만 호출하여 실행 가능하다.
그러나 RPC 경우 자신과 다른 주소 공간에서 동작하는 프로세스의 함수를 실행할 수 있게 해준다.

profile
프론트엔드 Developer

0개의 댓글