프로세스

yalpalyappap·2020년 12월 8일
0

운영체제

목록 보기
1/20
post-custom-banner

OSTEP을 공부하는 내용입니다.

운영체제란 하드웨어와 유저 프로그램의 중간층에 위치한다.

이 운영체제가 하드웨어를 관리한다. CPU, memory, IO devices(disk, network card, mouse, keyborad...) 따라서 우리는 OS 밑에 있는 컴퓨터를 구성하는 복잡한 하드웨어들에 대해서 크게 신경을 쓰지 않아도 된다!

그리고 하드웨어들끼리, 어플리케이션에 대한 독립성을 보장해준다.
예를들어 여러개의 프로그램을 실행하더라도, 각각의 메모리에서 실행되며 하나의 프로그램이 다른 프로그램에 어떠한 문제도 일으키지 않도록 한다.

그렇다면 어떻게 OS는 하드웨어들을 관리할 수 있을까?

컴퓨터를 부팅시킬 때 OS가 커널모드로 실행되어 trap handler 를 설정한다.
trap handler란 OS가 하드웨어를 관리하기 위한 메모리 주소?들에 대한 특수한 명령들을 생성하는 것이다.

그래서 유저가 하드웨어에 특정한 일을 수행하고 싶을 때 OS에게 부탁을해서 제한되었던 행동들을 수행할 수 있게한다.
이때 필요한 것이 system call이다.
User mode에서 프로그램을 실행할 때 system call을 호출하면 trap mode bit가 비 활성화 되어 Kernel mode에서 system call을 수행하고 다시 trap mode bit가 활성화되고 User mode, 프로세스의 메모리 주소로 되돌아온다. (돌아올 메모리 주소를 저장해두고 다시 돌아오는 것임)

그리고 부팅시에 또하나 interrupt timer handler를 설정한다.
interrupt timer handler가 하나의 프로세스가 동작중에 있어도 그 프로세스를 중단하고 다른 동작을 수행할 수 있도록 한다.

이 handler들은 함수들이다. code로 작성되어있으며, 하드웨어에게 exception / interrupt가 발생했을 때 어떤 함수(hander)를 실행하라고 말해주는 것이다.

OS abstraction

process, thread, file, socket, memory page...

OS mechanism

create, schedule, open, write, allocate...

프로그램을 컴퓨터에서 실행할 때 아래와같은 일이 실제로 일어나는 것이다.

  • 컴파일러가 프로그램을 실행 할 수있도록 변환한다. (.c --> a.out)
  • 변환 된 프로그램은 CPU가 이해할 수 있는 instructions, 프로그램의 데이터들로 구성되어있다.
  • CPU의 instructions를 하드웨어가 실행한다. (instructions set architecture를 하드웨어가 실행)

프로그램을 실행할 때 CPU는

  1. 컴퓨터의 메모리가 가리키는 instructions(명령들)를 가져온다.
  2. 그리고 이 instructions에 필요한 데이터들을 register로 옮겨준다.
  3. instructions들을 decode하고 실행한다.
  4. 결과를 메모리에 저장한다.
    그리고 가장 최근에 사용된 instructions들을 더 빠른 접근을 위해서 CPU cache에 저장한다.

OS가 하는 것

  • OS는 프로그램 메모리를 관리한다.
    디스크에 있는 프로그램을 메모리에 할당한다.
  • OS는 CPU를 관리한다.
  • OS는 외부 디바이스들을 관리한다.
    디스크로부터 파일들을 읽기/쓰기

OS는 다양한 프로세스들이 마치 한번에 동작하는 것 처럼 만들어준다.
실제로는 하나의 프로세스가 잠깐 동작하고, 다른 프로세스가 이어서 잠깐 동작하고, 다시 다른 프로세스가 잠깐 동작하는 것이 정말 빠르게 이루어져서 한번에 동작하는 것 처럼 느껴지는 것이다.

OS는 CPU 스케줄러를 지니고 있어서 어떤 프로세스를 실행할지, context switch 어떻게 할지를 결정한다.

Time sharing이란 OS에서 사용되는 기본적인 리소스 공유 방법이다. 반대되는 개념으로 Space sharing이 있다. space sharing은 대표적으로 block storage가 있다.

프로세스

프로세스들은

  • 자신만의 ID를 지니고 있다. (PID)
  • 메모리 이미지를 지니고 있다. (code, data 영역 (static), stack, heap 영역(dynamic))
  • cpu context: register (program counter, current operands, stack pointer)
  • 파일 디스크립터 (열려있는 파일과 디바이스를 가리키는 포인터)

프로세스의 state

프로세스는 아래와 같은 상태들중에 하나이다.

  • Running : CPU에서 실행중
  • Ready : 스케줄링을 기다림
  • Blocked : 실행되지 않고, 잠시 멈춤

이 3가지 state가 순환하면서 프로세스가 동작하게 된다.
OS는 효율적으로 프로세스들을 동작하게 하기위해 프로세스들을 추적을 한다.

mechanism, policy

mechanism

mechanism은 how에 관한 항목이다.
어떻게 프로세스를 실행시킬지를 결정한다.
A, B라는 프로세스가 있을 때 A를 짧게 실행시키고, B도 짧게 실행시킬지 또는 A와 B모두 길게 동작시킬지 결정하는 것에 관한 내용이다.

policy

pilicy는 what또는 which에 관한 항목이다.
어떤 프로세스를 지금 당장 실행시킬것인가?와 같은 내용이다.

OS data structure

OS는 프로세스 리스트를 지니고 있어서 현재 실행중인 프로세스들을 추적할 수 있다.
그리고 프로세스 하나의 정보를 추적하기 위해서 register context라는 것도 지니고 있다.

프로세스의 API

API란 Application Programming Interface의 약자로써 user program을 만드는데 사용되는 함수로 이해하면 된다.

OS에서 API는 system call의 집합이다.
System call이란 OS에서 호출하는 함수들인데, CPU에 대한 좀더 높은 권한을 가지고 있다.
예를들어 하드웨어에 접근해야하는 경우 일반적인 함수보다 더 높은 권한을 필요로 한다.
그리고 몇몇 blocking system call은 프로세스를 block시키고, descheduled한다. 예를들면 read from disk

대부분의 OS들은

  • Create : 새로운 프로세스를 생성한다.
  • Destroy : 실행중인 프로세스를 중지시킨다.
  • Wait : 프로세스가 멈추길 기다린다.
  • Miscellaneous Control : 프로세스를 잠시 멈추고 나중에 다시 사용한다.
  • Status : 프로세스의 상태 정보를 얻어온다.

와 같은 API를 가지고 있다.

system call과 관련된 프로세스

  • fork() : 자식프로세스를 생성함. 모든 프로세스들은 부모 프로세스로부터 fork()된 것이다.
    init 프로세스는 모든 프로세스의 조상이다.
  • exec() : 프로세스를 실행한다.
  • exit() : 프로세스를 종료한다.
  • wait() : 부모 프로세스를 자식 프로세스가 종료될 때까지 block시킨다.
  • ...그밖에도 여러가지가 있다.

fork()


자식 프로세스를 생성하면 부모 프로세스 메모리 이미지를 복사해서 자식 프로세스가 갖게된다.
그리고 새로운 프로세스가 OS process list에 추가되고 schedule된다.
부모 프로세스와 자식 프로세스는 각각 별도로 실행되고, 부모 프로세스에서 값을 변경해도, 자식 프로세스에서 변경되지 않는다.

wait()

프로세스가 종료되는 것은 exit()을 통해서 또는 비 정상적인 프로세스로인해 OS가 강제로 종료하는 경우이다.
부모 프로세스는 자식 프로세스가 종료될 때 까지 block된다.
만약 자식 프로세스가 살아있는데 부모프로세스가 종료되는 경우에는 init프로세스가 자식프로세스를 정리해준다.

exec()

부모 프로세스에서 자식 프로세스를 생성한 이후, 같은 코드를 돌리는 것은 의미가 크게 없다.
그래서 일반적으로 부모프로세스에서 자식프로세스를 생성한 이후에는 다른 코드를 동작시키는데
exec() 관련 함수를 활용하면 자식 프로세스의 메모리 이미지를 다른 프로그램으로 사용할 수 있다.

fork(), exec() separating

fork()와 exec()가 나뉘어있는 이유는 무엇일까?
어차피 fork이후 다른 프로그램을 사용한다면 forkandexec()를 만들었으면 되지 않았을까? 라는 의문이 든다면 I/O redirection, pipe를 위해서 fork()와 exec()는 나뉘었다고 답할 수 있다.

출처 : https://www.d.umn.edu/~gshute/os/images/process-diagram.png

profile
안녕하세요! 개발 공부를 하고있습니다~
post-custom-banner

0개의 댓글