OS_05_2 Processes

saewoohan·2023년 7월 28일
0

OS

목록 보기
5/19
post-thumbnail

OS_05_2 Processes

1. Process Creation and Termination

1) Process Creation

  • 새로운 process를 만드는 2가지 방법
    • Build one from scratch (0번 process)
    • Clone an existing one (fork → 0번을 제외한 모든 process)
  • scratch를 통해 process를 만드는 과정
    • Load code and data into memory (code, data영역에 memory 할당)
    • Create (empty) call stack (function call을 사용하기 위해서)
    • Create and initialize a process control block (PCB를 사용해서 process의 정보를 기입)
    • Put the process in the ready queue (scheduling의 대상이 될 수 있음을 확인)
    • Perform scheduling on the ready queue (CPU를 할당 받음)

2) Cloning a Process

  • 0번 프로세스가 scratch를 통해 만들어진 후, 이후 프로세스는 clone을 통해서만 만들어진다.
  • fork() system call을 통해 process를 만드는 과정
    • 현재 process를 멈추고 상태를 저장한다.
    • code, data, stack, PCB를 복사한다. → 새로운 프로세스가 만들어짐. → 이를 child process라고 부른다.
    • PCB 복사본을 ready queue에 올린다. → 새로운 child process가 scheduling의 대상이 될 수 있음을 뜻함
    • scheduling의 대상이 됌.

3) Process Creation via fork() and exec()

  • fork()는 부모의 주소공간과 PCB를 복사한다.
    • fork system call은 parent의 주소 공간과 PCB를 새로운 자식 process를 위해 복사한다.
      • Address space : memory context (code, data, stack)
      • PCB : system and processor context
    • 새로운 자식에게 새로운 식별자를 할당한다.
      • process들은 이 식별자를 통해 구분된다.
    • return value
      • child process에게 0을 할당
      • 이것이 parent process와 구분할 수 있는 식별자이다.
  • exec()는 fork 후에 새로운 프로그램으로 process의 메모리 공간을 대체하기 위해 사용한다.
int main(){
	int chPID; //Child PID
	int stat; // Used by parent wait
	pid_t thischPID;
	struct command_t command;

	//Create a process to execute the command
	if((chPID == fork()) == 0){
		//This is the child
		exec(command.name, command.argv);
	}
	thisChPID = wait(&stat);
	exit(0);
}

4) Swapper and Init Processed

  • Process 0 (swapper, built form scratch)

    • 모든 프로세스의 조상 프로세스이다.
    • 프로세스 0은 idle 작업을 수행한다. → idle task를 scheduling 하고 run하는 역할
      • 과거의 UNIX 시스템에서는 메모리 부족 등의 이유로 스왑(Swap) 기능을 사용하여 프로세스의 메모리를 디스크로 옮기는 방식을 사용했다. 이때 프로세스 0은 스왑 관련 작업을 처리하는 역할을 맡았다. 그러나 현대의 UNIX 시스템에서는 스왑 기능이 사용되지 않기 때문에, 프로세스 0은 스케줄링(Scheduling)을 수행하거나 idle 작업을 실행하는 역할을 맡는다.
      • 예를 들어, Linux에서 프로세스 0은 idle 작업을 수행하는데, 이는 시스템에 실행할 다른 프로세스가 없을 때 CPU를 유휴 상태로 유지하며, 리소스를 보존하고 시스템 성능을 향상시키는 역할을 수행한다. 따라서 프로세스 0은 시스템의 핵심적인 역할을 수행하며, 다른 프로세스들과 함께 시스템의 안정성과 효율성을 유지하는 데 기여한다.
  • Process 1 (init, built form fork by process 0)

    • system이 부팅 될 때, 처음으로 만들어진 user process이다.
    • 모든 user process들의 조상이다.
    • active한 child를 가진 process가 종료 될 때, orphan 상태라고 하는데 init process에서 이들을 관리한다.
  • Process 2 (pagedaemon)

    • 여유 메모리 pool을 유지하는 역할을 한다. 프로세스 2인 pagedaemon은 여유 메모리 풀을 관리하는 역할을 합니다. 메모리 관리 시스템에서 페이지 교체(Paging) 기법을 사용하는 경우, 메모리에 할당된 페이지 중에서 사용되지 않는 페이지를 여유 메모리 풀로 옮기고, 필요한 페이지를 메모리에 로드하는 작업을 수행합니다. pagedaemon은 시스템의 여유 메모리 풀을 유지 관리하여 필요한 경우 페이지 스왑 작업을 수행합니다. 페이지 스왑은 현재 메모리에 로드된 페이지 중에서 사용되지 않는 페이지를 디스크로 스왑하여 여유 메모리 풀에 추가하고, 필요한 페이지를 디스크에서 메모리로 스왑하는 과정입니다. 이를 통해 시스템은 한정된 메모리 공간을 효율적으로 관리하고, 사용되지 않는 페이지를 디스크로 옮김으로써 더 많은 여유 공간을 확보할 수 있습니다.

업로드중..

  • 생각보다 fork만 수행하고 exec는 수행하지 않을 때가 많다.
  • 가상 메모리를 사용하면 Parent의 메모리가 그냥 child memory가 된다. 그래서, fork의 비용이 0이기 때문에, scratch보다 효율적인 방식이다.

5) Process Termination

  • Normal termination
    • 프로세스가 마지막 문장을 실행한 후 OS에게 결정을 요청한다. (exit())
    • Process의 자원은 OS에 의해서 deallocate 된다.
  • Abnormal termination
    • process는 다른 process에 의해 종료 될 수 있다. (SIGKILL → kill())

2. Cooperation Processes

1) Cooperating Processes

  • 독립적인 프로세스는 다른 프로세스의 실행에 영향을 주거나 받을 수 없다.
  • Cooperating process는 다른 프로세스의 실행에 영향을 받거나 줄 수 있다.
  • process cooperation의 장점
    • Information sharing
    • Computation speed-up
    • Modularity
    • Convenience

2) Producer-Consumer Problem

  • Cooperating process들의 paradigm
    • producer process는 consumer process에 의해 소비되는 정보를 제공한다.
    • unbounded-buffer는 buffer의 크기에 대해 실제적인 제한이 없다.
    • bounded-buffer은 고정된 buffer size를 가진다.
  • Bounded Buffer
    • in : points to the next free position
    • out : points to the first full position
    • in == out : empty
#define BUFFER_SIZE 5
typedef struct {
	...
} item;
item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
item nextProduced;

while(1){
	buffer[in] = nextProduced;
	in = (in + 1) % BUFFER_SIZE;
}
item nextConsumed;

while(1){
	nextConsumed = buffer[out];
	out = (out + 1) % BUFFER_SIZE;
}
  • 생산자가 아직 buffer에 쓰지 않았는데, 소비자가 소비하는 문제가 생길 수 있다.
  • 역으로 소비자가 아직 buffer에 쓰인 것을 소비하지 않았는데 생산자가 생산할 수 있다.
item nextProduced;

while(1){
	while((in % BUFFER_SIZE) == out)
		; /* do nothing */
	buffer[in] = nextProduced;
	in = (in + 1) % BUFFER_SIZE;
}
item nextConsumed;

while(1){
	while (in == out)
		; /* do nothing */
	nextConsumed = buffer[out];
	out = (out + 1) % BUFFER_SIZE;
}
  • 만약 in =4, out = 4인 경우에서는 Producer와 Consumer 모두 기다리고 있다.
item nextProduced;

while(1){
	while(((in+1) % BUFFER_SIZE) == out)
		; /* do nothing */
	buffer[in] = nextProduced;
	in = (in + 1) % BUFFER_SIZE;
}
item nextConsumed;

while(1){
	while (in == out)
		; /* do nothing */
	nextConsumed = buffer[out];
	out = (out + 1) % BUFFER_SIZE;
}
  • buffer의 size는 5이지만, 4칸만 차도 producer는 buffer가 꽉 찬걸로 본다.
  • full(buffer가 모두 찬 것)과 empty(buffer가 비어있는 상태)를 구분 위의 코드는 생산자-소비자 문제를 해결하기 위한 버퍼 상태를 체크하는 방법입니다. 코드에서 while 루프를 사용하여 버퍼의 "full" 또는 "empty" 상태를 확인하고, 상태에 따라 생산자와 소비자의 동작을 조절합니다.
    1. 생산자 코드:
    • while(((in+1) % BUFFER_SIZE) == out)은 버퍼가 "full" 상태인지 확인합니다. 즉, 다음에 데이터를 넣을 위치가 소비자가 가져갈 위치와 같으면 버퍼가 가득 차있다는 의미입니다. 이 경우 루프를 돌며 기다리게 됩니다.
    • 버퍼가 "full" 상태가 아니면 buffer[in] = nextProduced를 통해 데이터를 버퍼에 넣습니다.
    • in = (in + 1) % BUFFER_SIZE는 다음에 데이터를 넣을 위치를 갱신합니다.
    1. 소비자 코드:
    • while (in == out)은 버퍼가 "empty" 상태인지 확인합니다. 즉, 다음에 가져올 데이터가 없는 상태입니다. 이 경우 루프를 돌며 기다리게 됩니다.

    • 버퍼가 "empty" 상태가 아니면 nextConsumed = buffer[out]를 통해 데이터를 가져옵니다.

    • out = (out + 1) % BUFFER_SIZE는 다음에 가져올 위치를 갱신합니다.

      이러한 코드는 버퍼의 "full"과 "empty" 상태를 체크하여 생산자와 소비자의 동작을 동기화합니다. "full" 상태에서는 생산자가 기다리고, "empty" 상태에서는 소비자가 기다립니다. 이를 통해 버퍼의 안전한 사용과 생산자-소비자 간의 협력이 보장됩니다.

3) Interprocess Communication (IPC)

  • Mechanisms
    • Shared memory communication → 공동의 영역에 write and read
      • write and read operation으로 수행된다. (buffer나 slot이 없다.)
    • Message passing communication → 공동의 영역이 아니라 그냥 연결시키는 것.
      • send and receive operation으로 수행된다.
  • Communication links
    • Logical link
    • Physical link (e.g., shared memory, harware bus)
  • Communication types
    • Direct와 indirect communication
    • Synchronous와 asynchronous communication

a. Direct Communicaion

  • Process들이 프로세스들의 이름이나 식별자를 명시적으로 지정하여 통신하는 방법이다.
    • send (P, message) - send a message to process P
    • receive (Q, message) - receive a message from process Q
  • communication link의 속성
    • 자동적으로 links들이 지정됌. → 통신을 시작하면 시스템이 링크를 자동으로 생성하고 연결한다.
    • 링크는 정확히 하나의 통신 프로세스 pair과 연관된다. → 각 프로세스는 링크를 통해 하나의 특정 프로세스와 통신한다.
    • 각 pair 사이에는 정확히 하나의 link가 존재한다. → 두 개의 프로세스가 통신을 수행할 때에는 하나의 linkf를 통해 서로 통신한다.
    • link는 단방향일 수도 있지만 보통 양방향이다.

b. Indirect Communication

  • Operations
    • 새로운 mailbox를 만든다.
    • mailbox를 통해서 message들을 ‘send’ and ‘receive’
    • mailbox를 지운다.
  • 연산이 동작하는 방식
    • send(A, message) - mailbox A에 message를 보낸다
    • receive(A, message) - mailbox A로부터 message를 받는다.

c. Synchronization

  • Message passing은 blocking이나 non-blocking일 수 있다.
    • Blocking → synchronous
      • e.g, 휴대전화 → 서로가 만날 때 까지 blocking
    • Non-blocking → asynchronous
      • e.g, message → 아무때나 data를 던지고, 아무때나 data를 가져감
  • send와 receive 연산 동작은 blocking일수도, non-blocking 일수도 있다.

d. Bounded Buffer

item nextProduced;

while(1){
	while(((in+1) % BUFFER_SIZE) == out)
		; /* do nothing */
	buffer[in] = nextProduced;
	in = (in + 1) % BUFFER_SIZE;
}
item nextConsumed;

while(1){
	while (in == out)
		; /* do nothing */
	nextConsumed = buffer[out];
	out = (out + 1) % BUFFER_SIZE;
}
  • Message passing 방식
    • 물리적으로 같은 memory를 사용하기 때문이다.
  • Asynchronous 방식
    • blocking이 있지만 서로 만나기 위한 block이 아니라, 정상적으로 수행하기 위해 사용하는 block이기 때문이다.

0개의 댓글