[OS] 프로세스

장선규·2023년 6월 16일
0

[OS] OSTEP Study

목록 보기
1/28

프로세스

프로세스: 실행 중인 프로그램

  • 사용자는 하나 이상의 프로그램을 동시에 실행시키기를 원함
  • 그러나 CPU는 한정되어 있음

그렇다면 어떻게 CPU가 여러개 존재한다는 것처럼 느끼게 할 수 있을까?

  • 가상화 - 운영체제는 CPU를 가상화 하여 CPU가 여러개 존재하는 것처럼 느끼게 할 수 있음

    • 하나의 프로세스 실행 -> 중단 -> 다른 프로세스 실행 -> 반복...
    • 이를 시분할 이라고 함
    • 시분할 하였을 때, CPU를 공유하므로 각 프로세스의 성능은 낮아짐
  • 정책: 운영체제 내에서 어떤 결정을 내리기 위한 알고리즘

    • 스케줄링 정책: 여러 프로그램 중 어떤 프로그램 먼저 실행시킬지 결정
      • 과거 정보로 결정
      • 워크로드에 관한 지식으로 결정
      • 성능 측정 결과로 결정

1. 프로세스의 개념

프로세스: 실행 중인 프로그램
하드웨어의 상태(machine state)를 이해해야 프로세스의 구성요소를 이해할 수 있음

  • 메모리(주소공간): 모든 명령어, 프로그램이 읽고 쓰는 데이터가 메모리에 저장됨
  • 레지스터: 프로세서에 위치한 고속 메모리, 연산에 필요한 데이터를 일시적으로 저장
    • 명령어들이 레지스터를 직접 읽거나 갱신
    • 프로그램 카운터(PC) - 어느 명령어가 실행중인지 알려주는 레지스터
    • 스택 포인터, 프레임 포인터 - 함수의 변수와 리턴 주소를 저장하는 스택 관리용 레지스터

2. 프로세스 API

운영체제는 몇몇 기본 비긍에 대해서 반드시 API로 제공해야 된다.

  • 생성(Create): 운영체제는 새로운 프로세스를 생성할 수 있는 방법을 제공해야 함
  • 제거(Destroy): 운영체제는 프로세스를 강제로 제거할 수 잇는 인터페이스를 제공해야 함
  • 대기(Wait): 어떤 프로세스의 실행 중지를 기다릴 필요가 있으므로 대기 인터페이스 필요
  • 각종 제어(MiscellaneousControl): 일시정지, 다시시작 등 각종 제어 기능 필요
  • 상태(Status): 프로세스의 상태 정보를 얻어내는 인터페이스 필요, 상태정보에는 얼마동안 실행되었는지, 어떤 상태에 있는지 등 포함

3. 프로세스 생성

그렇다면 프로그램이 어떻게 프로세스로 변형되는가?

1. 프로그램 코드와 정적 데이터를 메모리에 탑재(load)

  • 실행파일을 실행시키면 메모리 어딘가에 올라간다고 생각하면 됨
  • 과거에는 프로그램 실행 전에 코드와 데이터를 모두 메모리에 탑재함
  • 요즘에는 프로그램 실행할 때, 필요한 부분만 메모리에 탑재
  • 페이징(paging)과 스와핑(swapping) 동작은 추후에 자세히 배울 것

2. 스택과 힙 생성 및 초기화

  • 스택 메모리 할당 - 지역변수, 인자, 리턴주소 등을 저장하기 위해
  • 힙 메모리 영역 할당 - 동적/가변적으로 할당되는 데이터를 저장하기 위해

3. 입출력과 관계된 초기화 작업 수행

  • File descriptor: 터미널로부터 입력을 읽고 화면에 출력을 프린트하는 작을 쉽게 할 수 있음 (STDIN, STDOUT, STDERR)

4. 프로그램 실행

  • 시작지점인 main()을 루틴으로 분기(?) <- 다음 장에서 배울 듯...
  • 운영체제는 CPU를 새로 생성된 프로세스에게 넘기고, 프로그램 실행

4. 프로세스 상태

상태

  • 실행(Running): 프로세스가 명령어를 실행하고 있음
  • 준비(Ready): 프로세스는 실행할 준비가 되어 있지만, 운영체제가 어떠한 이유로 해당 프로세스를 실행시키지 않고 대기시킴
    • ex) 다른 프로세스 이미 실행중
  • 대기(Blocked): 프로세스가 다른 사건을 기다리는 동안 프로세스의 수행을 중단시킴
    • ex) 입출력 요청 들어오면, 프로세스는 입출력이 완료될 때까지 대기

프로세스 상태전이

프로세스는 운영체제의 스케줄링 정책에 따라 스케줄이 되면 준비상태에서 실행상태로 전이한다

  • 전이 예시

    • Process0는 3초까지는 실행, Process1은 3초까지 준비(실행하지 않음)
    • 3초에 Process0는 입출력을 시작하므로 이후엔 대기 상태가 됨, 그러므로 이때 Process1이 실행됨
    • Process0의 입출력이 종료되었지만, 아직 Process1이 실행중이므로 Process0은 실행되지 못하고 준비 상태가 됨
    • 이후 Process1이 종료되고 다시 Process0이 싱행됨

5. 자료구조

운영체제도 일종의 프로그램이다.
운영체제도 다른 프로그램처럼 다양한 정보를 유지하기 위한 자료구조를 가진다.

  • 프로세스 리스트: 프로세스 상태를 파악하기 위한 리스트

  • 레지스터 문맥(register context): 프로세스가 중단되을 때 해당 프로세스의 레지스터 값들을 저장

    • //프로세스를 중단하고 이후에 재개하기 위해 xv6가 저장하고 복원하는 레지스터
      struct context{ 
      	int eip; // 다음에 실행할 명령어 주소를 가지는 레지스터
          int esp; // 하나의 스택프레임의 끝 지점에 주소 저장하는 레지스터
          int ebx; // 등등
          int ecx; 
          int edx; 
          int esi; 
          int edi; 
          int ebp; 
      }; 
      
    • 이 레지스터 값들을 복원하여 운영체제는 프로세스 실행을 재개 (문맥교환, context switch)

  • 현재 실행중인 프로세스, 대기중인 프로세스를 위한 자료구조도 있음

문제

process-run.py 프로그램은 프로세스가 실행되면서 변하는 프로세스의 상태를 추적할 수 있고,프로세스가 CPU를 사용하는지(예,add명령어 실행) 입출력을 하는지(예,디스크에 요청을 보내고 완료되기를 기다린다)를 알아볼 수 있다.상세한 사항은 README 파일을 확인하기 바란다.

참고) process-run.py -l x:y 이런식으로 프로세스 생성 가능.
x는 프로세스가 돌아가는데 걸리는 시간이고, y는 CPU 혹은 IO를 이용하는 정도이다. (y=100 이면 CPU만 사용, y=0이면 IO만 사용)

process-run.py 깃허브 링크

문제 1

./process-run.py -l 5:100,5:100 실행시켰을 때 CPU 이용률은?

  • 예상: 100%, cpu 둘 다 100퍼 사용하므로

문제 2

./process-run.py -l 4:100,1:0 실행시켰을 때, 두 프로세스가 모두 종료되는데 걸리는 시간은?

  • 예상: 5, CPU 4 틱 실행되고 그 뒤에 1틱 IO 실행
  • IO 실행시 1틱은 RUN(CPU), 5틱동안 IO 사용, 마지막 1틱 IO DONE(CPU) => 총 7틱 소요
  • 따라서 소요되는 시간은 4+7 = 11

문제 3

./process-run.py -l 1:0, 4:100 실행시켰을 때, 두 프로세스가 모두 종료되는데 걸리는 시간은? (문제 2에서 순서 바꾼것)

  • 예상: 이제 IO에서 총 7의 시간이 소요되는 것을 앎. IO 실행 중에 CPU에 프로세스를 실행시킬 수 있으므로 총 7의 시간이 소요될 것

문제 4

./process-run.py -l 1:0,4:200 -cp -S SWITCH_ON_END 실행시켰을 때, 어떤 결과?

(SWITCH_ON_END 플래그 사용하면, 입출력 하는 동안 다른 프로세스 전환 x, IO 요청 다 될 때까지 기다림)

  • 예상: 7+ 4*2 = 15
  • 4:200이라서 CPU 프로세스 두개 실행시키는줄 알았는데 오타인 것 같다...
  • ./process-run.py -l 1:0,4:100 -cp -S SWITCH_ON_END
    -> 7+4 = 11

문제 5

./process-run.py -l 1:0,4:100 -cp -S SWITCH_ON_IO 실행시, 어떤 결과?

(SWITCH_ON_IO 플래그 사용하면, 입출력 하는 동안 다른 프로세스로 전환함)

  • 예상: 문제 3처럼 7초

문제 6

./process-run.py -l 3:0,5:100,5:100,5:100 -S SWITCH_ON_IO -I IO_RUN_LATER -cp 실행시 어떤 결과?

(IO_RUN_LATER가 지정되면 입출력이 완료되을 때 입출력을 요청한 프로세스가 바로 실행될 필요가 없다. 완료 시점에 실행 중이던 프로세스가 계속 실행된다)

  • 예상: 21틱?, 7틱 동안 IO 실행 (근데 그동안에 CPU로 전환하여 다른 프로세스 실행) * 3 = 21

  • 실제로 첫번째 IO 실행까지는 맞음. 첫 7틱동안 IO 실행되고, CPU로 전환하여 다른 프로세스 실행시킴.

  • 근데 이후에 IO_RUN_LATER 플래그로 인해 IO 실행을 나중에 함. 그동안 CPU를 사용하는 프로세스를 계속 수행함. 그래서 7+5+5

  • 이후에 IO를 수행하므로 +7+7

  • 따라서 7+5+5+7+7 = 31

문제 7

./process-run.py -l 3:0,5:100,5:100,5:100 -S SWITCH_ON_IO -I IO_RUN_IMMEDIATE -cp 실행시 어떤 결과?

(IO_RUN_IMMEDIATE 플래그는 입출력이 완료되면, 요청 프로세스가 곧바로 실행되는 동작을 의미)

  • 예상: 이번엔 진짜로 21, 7틱동안 IO 실행하고, 실행되는 중에 CPU 프로세스 동시에 실행
profile
코딩연습

0개의 댓글