[OS] 03. Processes

SYiee·2022년 12월 30일
0

🦕Operating System

목록 보기
3/14
post-thumbnail

I. 프로세스

1. Program vs Process

  • Program : 실행이 가능한 형태로 디스크에 저장되어 있는 Binary code, 메모리 로드가 되지 않음
  • Process : 프로그램이 메모리위에 로드된 형태 (초창기)전통적으로 실행과 스케쥴링의 가장 기본 유닛 —> thread가 더 작은 단위이긴함
    ◼ PID (Peocess ID) : table, 모듬 프로세스들이 가지는 고유값

2. Process Concepts

  • 프로그램이 실행되는 인스턴스이다. -> 클래스의 개념과 유사
  • Control Flow의 캡슐화이다. -> User가 몰라도 사용 가능
  • Dynamic & Active -> CPU에 올라가면 작성한 순서대로 차례대로 실행이 된다.

3. Process Address Space

virual memory를 통해 관리

4. ⭐Process State

  • New : Process가 처음 생성됨.
    → 프로그램이 실행이되면 메모리로 로드가 되고 초기화를 하고 PID를 부여받음, 메모리 구조도 만들어 주고나면 OS가 이를 ready queue에 집어 넣는다

  • Ready : 프로세스가 스케쥴러에 의해 선정되어 cpu위에 올라가길 기다린다.

  • Running : 프로세스가 할당되어 실행됨.
    → 다른프로세스에 의해 timer interrupt나 인터럽트가 발생하면 현재 프로세스는 ready 상태가 된다.

  • Waiting : I/O 요청이나 이벤트에 의해 프로세스가 기다린다.

  • Terminated : 프로세스가 실행을 마침.

5. Process Control Block (PCB)

➔ 각각의 프로세스는 자신의 정보 묶음인 PCB를 가짐.

➔ 많은 정보를 가지고 있어서 생각보다 용량이 크다. Linux2.4기준 1456bytes

➔ 각각의 PCB는 Double Linked List의 형태로 이루어져있다

  • Process state: 프로세스의 상태.
  • Program counter: 해당 프로세스가 이어서 실행해야 할 명령의 주소를 가리키는 카운터.
  • CPU registers: 프로세스가 인터럽트 이후 올바르게 작업을 이어가기 위해 참조하는 CPU 레지스터 값.
  • CPU-scheduling information: 프로세스의 중요도, 스케줄링 큐 포인터 등 스케줄링 파라미터 정보.
  • Memory-management information: base, limit 레지스터 값, 페이지 테이블 등 메모리 시스템 정보.
  • Accounting information: 사용된 CPU 총량, 프로세스 개수, 시간 제한 등.
  • I/O status information: 프로세스에 할당된 입출력 장치 목록, 열린 파일 목록 등.

II. Context Switch (CPU Switch) ⭐

↪️ 프로세스가 실행되다가 인터럽트가 발생해 운영체제가 개입하여 프로세서에 할당된 프로세스를 바꿀 때 현재 실행되고 있던 프로세스의 진행상황을 PCB의 형태로 메모리에 저장(register + instruction 값)한다. 인터럽트에 의해 reload된 프로세스의 이전에 진행상황을 알기 위해서 PCB를 불러와서 실행시킨다

💣 단점

  • 오버헤드 발생 → PCB 저장 정보를 불러오는 것 → Process에서 os로 이동할 때, OS도 SW이기 떄문에 OS가 CPU를 점유해서 사용할 때
  • Context switch의 오버헤드는 하드웨어에 따라 다름.

⇒ 그럼에도 불구하고 좋은 방법이라 현재까지 사용되고 있다.

❓ cpu context?
→ 프로세스가 현시점에 어디까지 수행되었는지 register + instruction

프로그램이 바이너리 코드로 형성이 되고 이 바이너리 코드에는 순차적으로 이 프로그램이 어떻게 수행되어야하는지가 명령어의 집합으로 적혀있다. 이 명령어 flow가 현 시점에서 어디까지 수행이 되었는지, 특정 시점에 필요한 레지스터들도 포함해서 context라고 한다.

✅ Batch System

→ CPU utilization↓ (io 끝날 때까지 cpu는 놀아서)

✅ Multiprogramming의 문제

→ 만약에 I/o 없이 동작하는 프로세스의 경우 Process 하나가 cpu 를 독점할 수 있다.
→ 이 문제를 해결하기 위해 timer interuppt를 통해 하나의 프로세스가 사용가능한 max time을 지정해서 fairness를 보장해준다. ⇒ time sharing

Timesharing & Multiprogram
interrupt, trap, scheduling을 통해 cpu 위에 올라가는 건 1개의 프로세스이지만 여러개의 프로세스를 왔다갔가 하며 실행할 수 있도록 OS가 관리를 한다.


III. Schedulers

A. Long-term scheduler (or job scheduler)

→ 한정된 메모리에 여러 프로세스를 올려야 하는데 디스크에 저장되어 있는 프로그램 중에서 어떤 것을 ready queue에 넣을 건인지.

B. Short-term scheduler (or CPU scheduler)

→ ready queue에 대기 하고 있는 프로세스 중 어떤 것을 cpu에 올려줄 것인가

C. Medium-term scheduler (or swapper)

→ 메모리가 부족해졌을 때 어떤 프로세스를 다시 디스크로 내릴 것인가

Operations on Processes

✅ Process creation

  • fork() : 수행 중이던 프로세스가 새로운 프로세스를 만드는 것은 운체에게 요청

✅ Process execution

  • exec() : 새롭게 프로세스가 만들어짐. 이 상태에서 디스크에 있는 아직 프로세스가 되지 못한 프로그램을 수행시키위해서는 프로세스 형태를 갖추야 하는데 기존의 프로세스에 실행되어야 하는 프로그램의 내용을 덮어씌워서 실행시킴 fork된 프로세스 위에 새로운 프로그램 덮어서 사용

✅ Process termination (종료와 관련)

  • exit() : 사후처리를 하고 프로세스를 종료시켜라 (버터플로싱, 아이오버퍼 없애기, dll 해제, 메모리 맵 할당 해제 원래 운체꺼니까)
  • _exit() : 사후처리 없이 종료 시키키 → 쓸 일이 거의 없다.
  • abort() : 비정상 종료가 일어나는 경우에 사용 그 로그 정보를 리포팅해줄 수 있는 것.
  • wait() : 멀티 프로세싱으로 프로그램이 동작이 될 때 부모자식관계에서 부모가 자식이 동작이 끝날 때까지 기다려라

✅ Cooperating processes

  • Inter-Process Communication (IPC) : 여러개의 프로세스가 종작할 때 이 프로세스가 단독 , 협업을 할 때 가각그이 프로세스가 독립적인데 , 프로세스간의 data가 오고 가는 것

Process Creation: Unix/Linux (POSIX)

📌 fork()

  1. 새 PCB를 만들고 초기화된다
  2. 새 memory address space가 만들어지고 초기화된다.
  3. parent의 address space전체를 copy
  4. child의 PCB를 ready queue에 넣는다.
  5. fork()의 return값으로
    • Parent process에게는 child peocess의 pid를 return
    • Child process에게는 0을 return
  • 부모 프로세스가 커널에 허락을 받고 사용하고 있는 resource를 자식 프로세스도 똑같이 부여 받은 채 태어난다.
  • Sharing of open files between parent and child after fork
#include <sys/types.h>
#include <unistd.h>
int main()
{
	int pid;
	if ((pid = fork()) == 0)
		/* child */
		printf (“Child of %d is %d\n”, getppid(), getpid());
	else
		/* parent */
		printf (“I am %d. My child is %d\n”, getpid(), pid);
}
  • getppid → 내 부모의 pib값을 가져옴
  • getpid → 내 pib값

↪️ 결과

 % ./a.out
I am 31098. My child is 31099.
Child of 31098 is 31099.

% ./a.out
Child of 31100 is 31101.
I am 31100. My child is 31101.

⇒ 스케쥴러에 의해 패러트가 먼저 자식이 먼저 수행될 수도 있기 때문에 순서가 뒤바뀔 수 있다. pib값도 매번 실핼시킬 때마다 다르 수 있다

💁🏻‍♀️ 그래서 folk 어디에 쓸까?

  • 부모와 새로 생성된 자식 프로세스가 협력해야할 때
    ex) web server
    ex) 네이버 서버 → 싱클 패스 → 망함 : 검색을 했는데 서버가 계속 리스닝하다가 요청이 오면 검색어로 검색 엔진을 돌리는 동안 다른 원격 사용자가 리퀘스트를 보내면 리스닝을 안하고 있으니가 메세지가 discard됨.

  • 아팟치의 코드

    While (1) {
    	int sock = accept();
    	if ((pid = fork()) == 0) {
    		/* Handle client request - */
    	} else {
    		/* Close socket - 부모는 소켓을 닫거나 리스닝 하거나*/
    	}
    }

exec()
int exec (char *prog, char *argv[])
: 보통 fork랑 같이 수행이 된다. 새로운 프로그램을 프로세스 형태로 실행시켜주는 system call

  • prog : 실행하고자 하는 프로그램의 이름, 경로
  • 시스템 콜을 호출하는 프로세스에다가 prog에 명시되어 있는 프로그램을 memory address space에 올려서 실행을 시켜달라

⇒ child가 더 이상 부모와 같은 형태가 아니라 다른 역할을 하게 되다

[ 진행 과정 ]

  1. 현재 실행 중이 프로세스를 멈춘다

  2. prog에 명시되어 있는 프로그램을 exec을 수행한 프로세스의 memory address space에 로드한다.

  3. HW context, argv를 초기화

  4. PCB를 ready queue에 올린다

    새로운 process를 만드는 것이 아니라 exec을 호출하고 있는 프로세스에 새 프로그램을 덮어써서 사용 ⇒ 그래서 보통 fork and exec 이라고 한다.

현재 아직 실행되지 않은 것을 뒤집어 씌워서 부모와는 전혀 다른 새로운 것이 됨

→ 실행가능한 바이너리 이미지를 메모리에 로드 (덮어쓰기) → 그 프로그램을 실행할 때 필요한 하드웨어 리소스 초기화 → … → PCB 정보도 지금 실행하고 있는 것으로 완전히 바뀜 → PCB를 ready queue에 넣는다.

int main()
{
	while (1) {
		char *cmd = read_command();
		int pid;
		if ((pid = fork()) == 0) {
			/* Manipulate stdin/stdout/stderr for 
			pipes and redirections, etc. */
			exec(cmd);
			panic(“exec failed!);
		} else {
			wait (pid);
		}
	}
}

pid =0 —> idle process

Process Creation/Execution: Windows

CreateProcess()

—> folk + exec

—> system call이 다르기 때문에 window의 프로그램은 unix 계열에서 안돌아간다. 반대도 마찬가자지!

  • 멀티스레드를 사용

Process Termination

  1. Normal termination
    • return from main() 정상적 : main함수에서 return 되면 끝
    • calling exit() 함수에서 → 마지막에서 _exit가 호출됨
    • calling _exit() 쓸일 이 없다

2. Abnormal termination : 비정상

  • calling abort() : 사후처리 핸들링 다 해주고 어떠한 비정상적으로 인해 종료 되었는디 로그 남겨주기
  • terminated by a signal : kill

3. Wait for termination of a child process

  • calling wait() : 자식 프로세스가 끝날 때 까지 부모 프로세스가 기다리는 경우 (동기화를 맞추기 위해) , 자식 프로세스가 종료가 될 때 자식 프로세스가 가지고 있는 여러 리소스들에 대한 정리가 필요한데 이런 것들이 부모 프로세스를 통해 ~~ 만약 부모가 종료되지 않고 살아있는데 wait호출을 안하면, 자식 입장에서 보고할 곳이 없어지는 것. —> zombie process
  • If no parent waiting (did not invoke wait()), process is a zombie → 부모 프로세스가 살아있긴 한데 wait 호출을 안해서 둥둥 떠다니는 경우
  • If parent terminated without invoking wait, process is an orphan : 고아
    → 자식 프로세스가 종료될 때 반납을 해야하는데, 자식이 동작하다가 엄맘? 하고 봤는데 엄마가 없어. 자식 프로세스보다 부모 프로세스가 먼저 종료된 경우 그 핸들링을 하는 것이 init이다.

Multiprocess in Application Program

Google Chrome Browser is multiprocess with 3 different types of processes:

  • Browser process : user interface, disk and network I/O를 담당
  • Renderer process renders web pages, deals with HTML, Javascript
    • A new renderer created for each website opened
    • Runs in sandbox restricting disk and network I/O, minimizing effect of security exploits
  • Plug-in process for each type of plug-in

✔ https → 보안성을 강화한 형태

✔ 샌드박스 : 격리된 환경, 이곳에서 보안문제가 있는지 미리 돌려보고 확인하기

Multiprocess in Mobile Systems

■ Some mobile systems (e.g., early version of iOS) allow only one process to run, others suspended

■ Due to screen real estate, user interface limits iOS provides for a

  • Single foreground process- controlled via user interface → 현재 내 눈 앞에 보이는 것을 의미
  • Multiple background processes– in memory, running, but not on the display, and with limits
  • Limits include single, short task, receiving notification of events, specific longrunning tasks like audio playback

■ Android runs foreground and background, with fewer limits

  • Background process uses a service to perform tasks
  • Service can keep running even if background process is suspended
  • Service has no user interface, small memory use

💁🏻‍♀️ 역사

ios
→ ios라 불리기 이전에는 멀티프로세싱이 안 되었다.
→ 사람들의 요구로 인해 멀피트로세싱이 지원, 하지만 제한적이다.
→ 모바일 디바이스와 관련되어 있는 분야에서 보안 킹임. 애플이 내는 화이트해커 내용이 거의 백서임
→ ios는 기반이 next step의 커널을 쓴다.

android

→ 반면 태생이 리눅스 커널이라 처음부터 멀티프로세싱이 지원이 되었다. 그러나 느리고 리소스가 많이 필요했다
→ 상대적으로 멀티 프로세싱이 잘 되며 자유도가 높다 → 보안이 취약하다

Inter-Process Communication (IPC)

1. message passing

= ✉️ 메모리 패싱은 우편이다.

커널에서 버퍼를 만듬, 여기에 접근할 수 있는 녀석이 프로세스 에이 비다 지정

✅ 단점

  • 오버 헤드가 크다. 메세지를 집어 넣을 때마다 context switch가 빈번하게 발생

✅ 장점

  • 동기화문제를 고려하지 않아도 된다 프로세스 a가 b에게 받을 데이터가 있는데 아직 b가 이를 쓰지 않음. a는 b가 쓸 때까지 기다려야 하는데 그 메커니즘을 커널이 다 해준다. → 동기화 문제를 개발자가 고려하지 않아도 커널이 알아서 해준다
  • 안정성이 높다.

2. shared memory

= 📋 shared memory는 게시판이다

💭 Process B가 A한테 무언가 전달하고 싶을 때…

→ 커널에게 요청, 나한테 에이와 비가 동시에 접근해도 괜찮은 메모리 영역을 할달 해줘
→ 커널이 그래 잘 쓰고 반납해라 하고 shared memory 할당
→ 개발자 입장에서 비가 에이한테 뭔가 전달하려고 할 때 에이가 비가 공유된 곳에 무언가를 넣은 것을 알 수가없다. 그래서 그런 메커니즘을 모두 개발자가 신경써야 함.

✅ 장점

  • 커널의 개입하는 횟수가 훨씬 적으니 빠르다.

✅ 단점

  • 동기화의 문제해결을 위한 코드를 개발자가 개발 해야한다.

■ Cooperating processes

  • Example: Bounded buffer problem (Producer-Consumer problem) 협력하는 프로세스 중 정보를 생산하는 프로세스를 생산자(Producer), 정보를 소비하는 프로세스를 소비자(Consumer)라고 부른다. 생산자-소비자 문제는 두 프로세스가 동시에 동작할 때 일어나는 이슈 를 말한다. 보통 정보가 생산되는 속도가 소비하는 속도보다 빠르기 때문에 동기화 문제가 발생하는데, 이를 해결하기 위해 생산된 데이터를 담아두는 버퍼(Buffer)를 사용한다.

Client-Server Communication

  • Sockets : 프로세스간의 통신 → 원격에 있는 프로세스들 간의 통신 IPC
  • Remote Procedure Call (RPC) → 원격에 있는 function들을 불러와서 사용 → 클라이언트가 서버에 구현되어 있는 어떤 기능을 내가 돌리기에는 리소스가 부족해서 서버에게 소켓으로 보낸다. 실행을 시키고 리턴값을 가져와서 처리를 한다. 클라이언트 단에서는 크게 리소스를 쓰지 않고도 내가 원하는 것을 수행가능
  • Remote Method Invocation (RMI in Java)
  • Marshalling parameters

profile
게임 개발자

0개의 댓글