2️⃣

[운영체제론] Chapter 2.1 Process(프로세스)

작성일자
Sep 25, 2022
태그
SUB PAGE
프로젝트
운영체제론
책 종류
본 게시글은 하단 책을 읽고 학습한 내용을 제 생각으로 요약, 정리한 글입니다.
목차
 

1. Process란?

1) Process: 실행 중인 프로그램의 인스턴스

2) Multiprogramming

  • 메모리에 여러 개의 프로그램 넣어 놓고 이 프로그램 수행하다 저 프로그램 수행하다 하는 것.
  • CPU가 프로세스에서 프로세스로 switch하면서 수행
  • CPU는 코어 하나 있고 어떤 순간에도 한 번에 한 프로그램만 실행 가능하다 가정
notion image
(a) 1개의 물리적인 program counter → process switch
  • PC: 현재 수행중인 instructuon의 주소 담고 있는 것
  • process switch: 메모리에 프로그램 4개 올라와 있어, CPU 하나가 a수행→b수행→c수행→d수행
  • CPU 하나라서 PC도 한 개
(b) 4개의 논리적인 program counter
  • 하드웨어적으론 물리적인 pc 1개만 존재
  • A가 물리적 PC 이용 → A가 쓰던 물리적 PC값을 메모리(논리적 PC)에 저장
  • B, C, D가 물리적 PC 이용 → B,C,D도 수행 멈추면 쓰던 물리적 PC값을 각각 메모리(논리적 PC)에 저장
  • A가 다시 수행될 땐 메모리에 저장해둔 논리적 PC값을 물리적 PC에 load해 물리적 PC이용
(c) 한 순간에 단 하나의 프로세스만 실행하면서, 4개의 프로세스를 멀티프로그래밍 하는 상황 → process switch의 예시(CPU 시간 할당량)
  • CPU 하나라서 A, B를 동시에 수행할 수 없음
  • 시간을 쪼개서 A, B를 수행함
  • 추상적으론 A, B, C, D가 동시에 수행되는 것처럼 보이지만, 실제론 한 순간에 하나씩만 실행되고 있음
  • 멀티프로그래밍에서 한 프로그램 수행하다 다른 프로그램 수행하는 예시
    • ex) A를 수행하다 A가 입출력하는 동안 시간이 오래 걸려서 B로 넘겨 B를 수행함
    • ex) A를 수행하다 시간 다 지나면(CPU의 시간 할당량 다 차면) B로 넘겨 B를 수행함
      • 입출력과 상관 없이 여러 개 프로그램이 CPU 하나를 골고루 나눠 쓰게 하기 위해 시간으로 쪼갬.
      • 시간 할댱량을 프로그램만다 조금씩 줘서 할당량 만큼씩만 CPU 사용하게 해줌.

3) Process 구성

  1. address space(=core image)(=process image)
      • 각 프로세스는 메모리에 자신의 address space(주소 공간) 가짐
        • = 각 프로세스는 core image를 가짐
      • address Space의 구성: 3 segments
        • notion image
        • text: 코드, 명령어
        • data: 정적 변수(static) - 함수 밖에서 선언한 변수
          • malloc()으로 동적 메모리 할당하면 높은 주소 쪽으로 자라남
            • 자라난 곳을 heap이라 부름
        • stack: 자동 변수(automatic) - 함수 안에서 선언한 변수
          • Push하면 낮은 주소쪽으로 자라남
  1. process table entry
      • 운영체제가 관리하는 프로세스 테이블의 엔트리 하나
      • 멀티프로그래밍에서 다른 프로세스로 넘어갈 때 현재 수행하던 프로세스의 상태(레지스터 값 등)를 proess table entry에 저장해둠
      • 그래야 나중에 다시 현재 프로세스 수행 할 때 process table entry값을 load해 저장된 상태에서 이어서 할 수 있음.
       

2. Process States(프로세스 상태)

1) state diagram

  • 프로세스가 거치는 state와 state의 transition 나타냄
    • notion image

2) 상태

  • Running(실행 중)
    • 현재 CPU를 사용하고 있는 프로세스
  • Ready(준비됨)
    • 실행 가능(Runnable)하지만 다른 프로세스가 실행되는 것을 허용하기 위해 자기 자신은 일시적으로 멈춰있는 프로세스
    • Time Sharing: 하나의 CPU를 시간으로 쪼개어 여러 프로세스가 번갈아가며 나눠 사용하게 해줌으로써 여러 프로세스를 수행함
      • 현재 CPU 가진 프로세스가 Running상태, 나머지 프로세스는 Ready 상태
      • ex) A에게 할당된 10ms 시간 다 지나면 Running 상태의 A를 Ready 상태로 끌어내리고, Ready 상태에서 대기하고 있던 프로세스 중에 하나를 Runnign 상태로 올림 (2, 3번 transition).
        • A는 Ready 상태의 프로세스들이 서있는 줄(queue)의 맨끝에 세움
        • Ready 상태에 줄 서있는(queue에 있는) 프로세스 중 맨 앞에 있는 프로세스를 Running상태로 보냄
        • 운영체제의 스케줄러라는 코드 부분이 올리고 내리고 하는 역할을 함
  • Blocked
      1. Running 상태에 있는 프로세스가 i/o 요구(파일 리드, 키보드 input read) 같은 것을 했을 때, 입출력을 수행하는 동안엔 (입출력을 기다려야 해서) CPU를 사용하지 못하기에 해당 프로세스는 Blcoked 상태로 보내짐. (1번 transition)
      1. 비어진 Running 자리는 Ready 상태 프로세스 중 맨 앞에 있는 것이 차지함. Ready 상태 프로세스들끼리 돌아가면서 수행됨. (2, 3번 transition)
      1. 시간이 흘러 요구했던 입출력이 완료되었을 때, Blocked 상태로 갔던 프로세스는 원하는 파일을 읽었으니 처리를 계속할 수 있기에 Ready 상태로 감. (4번 transition)
          • input becomes available: 입력을 요구했을 때 입력이 들어와서 입력이 사용 가능해짐
          Blocked → Ready 과정 (interrupt)
          1. 디스크가 파일 내용 다 읽었다면 CPU에게 파일 다 읽었다고 하드웨어적 신호 보냄.
          1. CPU의 pin에 interrupt 신호가 가서 CPU가 interrupt 걸리게 됨.
          1. interrupt에 걸리면 CPU는 일단 실행 중인 프로세스를 일시정지 시킴
          1. 입출력 요구의 대상 프로세스 파악함.
          1. 디스크로부터 읽어 들인 내용을 버퍼에 저장하고 Blocked 상태의 프로세스를 Ready 상태로 보내줌
      1. 언젠가 자기 차례 오면 Runnig으로 감. Running 가서 수행 일어나는 순간 Read process call로부터 return되어 데이터 들어와 있음. 이를 처리해줌.
 

3. Process Hierarchies(프로세스 계층 구조)

1) 부모 프로세스는 자식 프로세스 생성 가능 → Process tree

notion image

2) Unix

  • Process group: 부모 프로세스와 지식 프로세스들을 전부 합쳐서 부르는 말
    • 모든 프로세스는 처음 시스템 부팅됐을 때 생기는 init 프로세스에서 파생됨
  • Prptection: 프로세스를 시작하면 해당 프로세스를 시작한 사람의 유저아이디(UID)를 자기 속성 중 하나로 부여 받게 됨.
    • 자식 프로세스는 부모속성을 그대로 물려 받기에 부모와 같은 UID 가짐
    • UID: 시스템 사용을 허락 받은 사람만 system admin으로부터 받음
    • GID: 각 그룹을 나타내는 id. 유저는 그룹 멤버가 될 수 있음.

3) Windows os

  • 프로세스 계층 구조 개념 존재하지 않고 모든 프로세스가 동등한 개념으로 존재함
 

4. 프로세스의 구현 → Process Table

1) Process Table: 운영체제가 관리하는 자료 구조 중 하나

  • 프로세스마다 한 entry(process controll block)를 차지함
  • 한 entry에 저장되어 있는 것: Process가 Running 상태에서 Ready나 Blocked으로 빠지는 상황에서, 나중에 다시 자기 차례로 돌아왔을 때 (table entry 읽어서 load해가서) 이어서 시작하기 위해 저장해둬야 할 정보들
    • notion image
      Process management
      • register(나중에 다시 수행할 때 load해감)
      • program counter
      • program status word(kernel, user 나타내는 bit 하나)
      • stack pointer(현재 스택이 어디까지 차있는지)
      • process state(Running, Ready, Blocked)
      • acounting scheduling information
      Memory Management
      • address space에 대한 정보
      • memory allocation 정보
      File management
      • root directory
      • file descriptor(해당 프로세스가 open한 file에 대한 정보)
      • userid(프로세스 실행시킨 사용자의 id)
       

5. Process Creation(프로세스 생성)

1) Process Creation System Call

  • 일반적으로 새로운 프로세스는 기존에 존재하는 프로세스가 Process Creation System Call(Unix에선 fork)을 수행함으로써만 생성됨.

2) 프로세스 생성되는 주요 상황들

  • 전부 실제로 프로세스 생성될 땐 fork system call이 관여함
  1. 시스템 초기화
      • 전위 프로세스
      • 후위 프로세스(Daemons)
        • 미리 정해진 기능을 수행하며 background에서 도는 프로세스
        • email 수신, webpage 요청 수신
  1. 실행 중인 프로세스가 fork system call
  1. 사용자가 프로세스 생성을 요청
      • windown 더블클릭, unix shell에 커멘드 입력 → 시스템 프로세스가 fork system call
  1. 배치 작업 → 배치 관리자 프로세스가 fork system call
 

6. Process Termination(프로세스 종료)

1) 프로세스 종료되는 상황들

  1. 정상 종료(자발적)
      • 정상적으로 수행하고 return을 만남(ex. c 프로그램) → 컴파일 후 컴파일러가 시스템 콜 함
      • 사용자가 프로세스 종료를 지시함. (ex. word, powerpoint 등을 x 버튼 눌러서 끄기)
  1. 에러 종료(자발적)
      • 잘못된 입력
      • 컴파일할 파일이 없는 걸 프로세스가 발견
  1. fatar 에러(비자발적)
      • 프로그램 버그 (존재하지 않는 메모리 접근, 나누기 0, 잘못된 명령어 실행)
  1. 다른 프로세스에 의해 킬 됨(비자발적)
 

7. 프로세스 관리 위한 System Call

1) 종류

  • 프로세스 시작 / 종료
  • 프로그램을 다른 프로그램으로 덮어씀 (Core image를 다른 걸로 덮어씀)
  • 자식 프로세스가 종료되기를 기다림
  • 더 많은 메모리를 요청(동적 memory allocation) / 사용하지 않는 메모리를 배포

2) 프로세스 관리 위한 System Call 사용하는 shell의 뼈대

shell의 소스코드 → shell process가 수행되고 있는 상황
  • shell은 while 루프 돌면서 명령 받아들이고 처리하고 받아들이고 처리하고를 반복함.
type_prompt( );
  • shell prompt를 출력.
  • 사용자가 입력하기를 기다림
read_command (command, parameters)
  • 사용자가 입력한 command 읽기
  • ex. ls 입력 -> read_command('ls',)
if (fork() != 0)
  • shell 프로세스가 fork system call해서 child 프로세스 만듦
  • child 프로세스는 parent 프로세스인 shell 프로세스를 clone한 것임(카피한 것. 똑같이 생김)
  • fork()를 call할 땐 프로세스가 하나 뿐이었는데, fork()로부터 return 받을 땐 두 프로세스가(shell 프로세스와 만든 자식 프로세스) 각각 리턴함.
    • fork() 시스템콜을 수행하고 있는 중간에 자식 프로세스가 생기고 이 역시 shell 프로세스이기에 fork()를 call함.
    • 즉, 둘 다 fork를 call했다고 생각하는 상황임.
  • return 값
    • 부모 프로세스 → 새롭게 clone으로 만들어진 자식 프로세스의 pid(process id)
    • 자식 프로세스 → 0
  • forn()의 return 값이 0이 아닌 걸 조건으로 걸면 부모 프로세스만 if문 안으로 들어갈 수 있음
waitpid( -1, &status, 0);
  • 첫 번째 인자: 종료 기다려야 할 프로세스의 pid. -1이면 자식 프로세스.
  • child process인 ls process가 종료될 때까지 기다림
  • ls process가 종료되면 waitpid가 return 되어 if문 빠져나가고 while문 처음부터 다시 반복.
else
  • fork()의 return 값이 0인 자식 프로세스만 들어갈 수 있음.
execve(command, parameters, 0);
  • execve system call: 현재 프로세스의 core image를 다른 걸로 덮어씀
  • ex) execve(’ls’, ,0);
    • 이를 실행하는 순간 하드디스크에는 shell process의 image가 ls의 image로 overwrite됨.
    • 원랜 부모랑 똑같이 shell process였는데 return했을 땐 ls process가 됨. → 부모를 클론한 것에서 image가 바뀐 자식 프로세스가 됨

3) brk system call

  • data segment가 끝날 새 주소를 지정하는 시스템 콜
    • data segment 바운더리를 확장 → data segment를 키워줌 == heap 부분을 만들어줌
      • notion image
    • 프로그램에서 동적 메모리 할당할 때(malloc을 call) brk system call이 heap 부분 만들어 프로그램에 할당해줌
 

8. Handling of Interrupt(인터럽트 처리)

1) Interrupt 발생하기까지의 과정 → blocked

  1. Running 상태의 어떤 프로세스가 Read System Call(입력 요구)함.
  1. 운영체제가 해당 프로세스를 Blocked 상태로 보냄.
  1. 운영체제의 스케줄러가 빈 Running 자리를 Ready 상태의 프로세스 중 하나로 메꿈.
  1. 운영체제의 System Call handler가 Read System Call을 처리함.
  1. 운영체제는 Read System Call 처리하기 위해 Disk(하드웨어)로부터 파일 읽어야하므로, Disk에게 특정 디스크 블록 읽어달라고 요청함.
  1. 디스크에서 파일 읽는 게 완료되면, disk controller 하드웨어는 CPU에게 interrupt를 걸며 자신의 device number(→interrupt number)를 알려줌.’
  1. 다른 프로세스 실행 중이던 CPU는 disk controller(하드웨어)로부터 interrupt signal과 interrupt number를 받음.

2) Interrupt 발생 후 8가지 스텝

notion image
  1. 하드웨어적으로 interrupt가 걸린 것이기에 CPU가 현재 수행 중이던 (Running 상태의) 프로세스를 중단하고 프로세스의 Current stack에 PC, register값 같은 프로세스의 현재 상태를 저장함.(임시)
  1. CPU가 어떤 하드웨어로부터 온 interrupt인지 알아채고, 해당 하드웨어에 대한 interrupt service routine 주소를 PC에 로드함.
      • Interrupt Vector로부터 PC값 load하면 됨.
      • Interrupt Vector: Interrupt Handler routine의 주소
      • Interrupt Handler(Service) routine: 특정 device로 인해 걸린 interrupt를 처리해주는 루틴
      • Interrupt Vector table: Interrupt vector들이 모여 있는 곳. Interrupt number를 index로 씀.
      • ex) disk의 device number(Interrupt number)가 5일 때
        • 5로 메모리의 Interrupt vector table을 인덱싱함.
        • 인덱싱한 곳에 디스크로 인한 interrupt를 처리해주는 루틴(Interrupt Handler routine)의 주소인 Interrupt Vector가 있음.
        • 주소를 CPU PC값에 load함으로써 interrupt 처리 루틴(Interrupt Handler routine)을 실행함.
  1. [Assembly] 1번에서 current stack에 저장한 Register 값을 pop()해서 읽어서, 운영체제가 관리하는 proces table의 엔트리(interrupt로 인해 수행하다 중단된 process의 엔트리)에 저장함.
      • stack에 있던 PC값도 저장함.
      • interrupt 걸렸을 때의 상태를 1번에서 임시로 스택에 저장하고, 2번 수행 후에, 3번에서 메모리에 저장함.
  1. [Assembly] Interrupt Service routine이 수행되면서 사용할 수 있는 temporary stack(운영체제의 stack)을 set up함.
      • stack pointer 값에 temporary stack의 시작 주소를 setting하는 것임.
      • 기존: user process의 stack → 운영체제의 stack
  1. [C] 본격적인 Interrupt Service routine 해주고, blocked의 프로세스를 ready로 보내줌.
      • ex) 디스크로부터 read가 끝나서 걸린 interrupt였다면, Read한 값을 Kernel Buffer로 옮김. (후에, user program의 버퍼로 전달됨)
      • 추가적으로, Read system call해서 blocked로 갔던 process는 이제 버퍼로 값이 들어와 Read가 완료되었으니 운영체제가 Ready로 보내줌(큐에 줄 세움)
  1. Interrupt Service routine 완료되어 가니, 운영체제 스케줄러가 어떤 프로세스를 Running으로 올려줄지 결정함.
      • 일반적으로 아까 멀쩡히 수행하고 있다가 interrupt 맞아 중단된 프로세스를 택함
      • 1,2,3번에 의해 상태가 저장되어 있어 다시 수행 가능함
  1. 5번이 C로 짜여 있어 다시 Assembly 코드로 돌아옴
  1. [Assembly] 새로운 프로세스(6번에서 택한 interrupt 맞은 프로세스)를 시작함.
      • interrupt 맞은 프로세스가 다시 수행됨.
      • 어셈블리 코드로 짠 이유: 새로운 프로세스 시작하기 위해선 process table entry 값 모두 읽어서 레지스터에 load 해야 하기 때문.
      • 시간 더 지나고 돌다보면 blocked에서 ready로 가서 기다리고 있던 프로세스도 언젠가 수행됨. 이때, Read System Call로부터 return하여 버퍼에 디스크로부터 읽은 게 들어와있음.
 
[운영체제론] Chapter 2.1 Process(프로세스)