[OSTEP] Virtualization) 4. Processes

0

OSTEP 운영체제

목록 보기
1/19
post-thumbnail

[OSTEP] 4. Processes

이 포스팅은 <<Operating Systems: Three Easy Pieces>>, Remzi H. Arpaci-Dusseau & Andrea C. Arpaci-Dusseau을 읽고 개인 학습용으로 정리한 글입니다.

CH 7. 프로세스의 개념

  • 프로세스(process): 실행 중인 프로그램

  • 프로그램: 디스크 상에 존재하는 실행을 위한 명령어와 정적 데이터의 묶음
    -> 프로그램 자체는 생명이 없음
    -> 프로그램을 읽고 실행하여 프로그램에 생명을 불어넣는 것이 운영체제

  • 운영체제는 CPU를 가상화하여 CPU가 여러 개 존재한다는 환상 제공

시분할(time sharing)

  • 하나의 프로세스를 실행하고, 얼마 후 중단시키고 다른 프로세스를 실행하는 작업을 반복

  • CPU를 공유하기 때문에, 각 프로세스의 성능은 낮아진다

메커니즘

  • 메커니즘(mechanism): 필요한 기능을 구현하는 방법이나 규칙

  • ex. 문맥 교환(context switch): CPU에서 프로그램 실행을 잠시 중단하고 다른 프로그램을 실행하는 것

정책

  • 정책(policy): 운영체제 내에서 어떤 결정을 내리기 위한 알고리즘

  • ex. 스케쥴링 정책(scheduling policy): 실행 가능한 여러 프로그램들이 있을 때, 운영체제는 어느 프로그램을 실행시켜야 하는지 결정하는 알고리즘

1. 프로세스의 개념

  • 프로세스(process): 운여엧제가 제공하는 실행 중인 프로그램의 개념

  • 특정 순간의 프로세스를 간단하게 표현하려면, 실행되는 동안 접근했거나 영향을 받은 자원의 목록을 작성하면 된다

하드웨어 상태

  • 프로그램이 실행되는 동안 하드웨어 상태(machine state)를 읽거나 갱신할 수 있다

  • 메모리
    - 프로세스의 하드웨어 상태 중 가장 중요한 구성 요소
    - 메모리에 명령어 & 실행 프로그램이 읽고 쓰는 데이터가 저장됨
    - 프로세스가 접근할 수 있는 메모리 = 프로세스의 주소 공간(address space)

  • 레지스터
    - 프로세스의 하드웨어 상태의 구성 요소 중 하나
    - 많은 명령어들이 레지스터를 직접 읽거나 갱신

    • ex. 프로그램 카운터(program counter, PC): 프로그램의 어느 명령어가 실행 중인지 알려줌 (= 명령어 포인터(instuction pointer, IP))
    • ex. 스택 포인터(stack pointer) & 프레임 포인터(frame pointer): 함수의 변수와 리턴 주소를 저장하는 스택을 관리할 때 사용
  • 프로그램은 영구 저장장치(persistent storage)에 접근하기도 함
    -> 이 입출력 정보는 프로세스가 현재 열어 놓은 파일 목록을 가지고 있다

2. 프로세스 API

  • 운영체제가 반드시 API로 제공해야 하는 기본 기능

  • 생성(Create)
    쉘에 명령어를 입력하거나 응용 프로그램의 아이콘 더블 클릭하여 프로그램 실행시키면 운영체제는 새로운 프로세스를 생성

  • 제거(Destroy)
    많은 프로세스는 실행되고 할 일을 다하면 스스로 종료한다
    그러나 프로세스가 스스로 종료하지 않는 경우 필요없는 프로세스를 중단시켜야

  • 대기(Wait)
    때로는 어떤 프로세스의 실행 중지를 기다릴 필요가 있음
    여러 종류의 대기 인터페이스 존재

  • 각종 제어(Miscellaneous Control):
    ex. 대부분의 운영체제는 프로세스를 일시정지하거나 재개하는 기능 제공

  • 상태(Status)
    프로세스 상태 정보를 얻어내는 인터페이스 제공
    (프로세스의 상태 정보: 얼마 동안 실행되었는지, 프로세스가 어떤 상태에 있는지 등 포함)

3. 프로세스 생성: 좀 더 자세하게

  • 운영체제는 어떻게 프로그램을 준비하고 실행시키는가?
    실제로 어떻게 프로세스를 생성하는가?

(1)

  • 프로그램 코드와 정적 데이터(static data)를 메모리, 프로세스의 주소 공간에 탑재(load)해야 한다

  • 프로그램은 디스크 또는 플래시-기반 SSD에 특정 실행 파일 형식으로 존재
    -> 운영체제는 디스크의 해당 바이트를 읽어서 메모리의 어딘가에 저장해야 한다

  • 초기 운영체제들은 프로그램 실행 전에 코드와 데이터를 모두 메모리에 탑재하였음

  • 현대의 운영체제들은 프로그램을 실행하면서 코드나 데이터가 필요할 때 필요한 부분만 메모리에 탑재한다

(2)

  • 일정량의 메모리가 프로그램의 실행시간 스택(run-time stack) 용도로 할당 되어야 한다

  • C 프로그램은 지역 변수, 함수 인자, 리턴 주소 등을 저장하기 위해 스택 사용

  • ⚡운영체제는 스택을 주어진 인자로 초기화한다
    -> main()함수의 인자인 argc와 argv 벡터를 사용하여 스택 초기화

(3)

  • 프로그램의 힙(heap)을 위한 메모리 영역을 할당한다

  • C 프로그램에서 힙은 동적으로 할당된 데이터를 저장하기 위해 사용된다
    -> malloc()을 호출하려 필요한 공간 요청
    -> free()를 호출하여 사용했던 공간 반환

  • 힙은 연결 리스트, 해시 테이블, 트리 등 크키가 가변적인 자료구조를 위해 사용됨

  • ⚡프로그램이 실행되면 malloc() 라이브러리 API를 호출하여 메모리를 요청하고, 운영체제가 이를 충족하도록 메모리를 할당한다

(4)

  • 입출력과 관계된 초기화 작업을 수행한다

  • ⚡Unix 시스템에서 각 프로세스는 기본적으로 세 개의 파일 디스크립터(file desctiptor)를 갖는다
    -> 표준 입력(STDIN), 표준 출력(STDOUT), 표준 에러(STDERR)
    -> 이 디스크립터들을 사용하여 프로그램은 터미널로부터 입력을 읽고 화면에 출력을 프린트하는 작업을 쉽게 할 수 있다

(5)

  • (1) 코드와 정적 데이터릴 메모리에 탑재하고, (2) 스택과 (3) 힙을 생성하고 초기화하고, (4) 입출력 셋업과 관계된 다른 작업을 마치게 되면, 운영체제는 프로그램 실행을 위한 준비를 마치게 된다

  • 프로그램의 시작 지점(entry point), 즉 main()에서부터 프로그램 실행을 시작하는 마지막 작업만 남는다
    -> main() 루틴으로 분기
    -> 운영체제는 CPU를 새로 생성된 프로세스에게 넘김
    -> 프로그램 실행 시작

4. 프로세스 상태

  • 프로세스의 상태는 다음 세 상태 중 하나에 존재할 수 있다

  • 실행(Running):
    프로세스는 프로세서에서 명령어를 실행 중이다

  • 준비(Ready):
    프로세스는 실행할 준비가 되어 있지만 운영체제가 다른 프로세스를 실행하고 있는 등의 이유로 대기 중이다

  • 대기(Blocked):
    프로세스가 다른 사건을 기다리는 동안 프로세스의 수행을 중단시키는 연산
    ex. 프로세스가 디스크에 대한 입출력 요청을 하였을 때 프로세스는 입출력이 완료될 때까지 대기 상태가 되고, 다른 프로세스가 실행 상태로 될 수 있다

  • 프로세스는 스케쥴링 정책에 따라 준비 상태 <-> 실행 상태로 전이한다

5. 자료 구조

  • 운영체제도 일종의 프로그램이다
    -> 다른 프로그램들과 같이 다양한 정보를 유지하기 위한 자료구조를 가짐

  • xv6 커널에서 각 프로세스를 추적하기 위해 운영체제가 필요로 하는 정보
    -> Linux, Mac OS X, Windows 같은 운영체제들도 이와 비슷한 프로세스 구조를 가짐

레지스터 문맥(register context)

  • 프로세스가 중단되었을 때 해당 프로세스의 레지스터 값 저장
    -> 이 레지스터값들을 복원하여 운영체제는 프로세스 실행을 재개한다

가능한 프로세스 상태

  • 실행, 준비, 대기 이외에 다른 상태들 존재

  • 초기(initial) 상태: 프로세스가 생성되는 동안 초기 상태에 머무른다

  • 최종(final) 상태: 프로세스는 종료되었지만 메모리에 남아있는 상태
    -> 프로세스가 성공적으로 실행했는지를 다른 프로세스(보통 부모 프로세스)가 검사하는 데 유용하다

  • 부모 프로세스는 자식 프로세스의 종료를 대기하는 시스템 콜(ex. wait())을 호출한다
    -> 이 호출은 종료된 프로세스와 관력된 자원들을 정리할 수 있다고 운영체제에게 알리는 역할도 한다

  • ⚡Unix-기반 시스템에서는 최종 상태를 좀비(zombie) 상태라고 부른다
    -> 프로세스가 성공적으로 종료되었으면 0을, 그렇지 않으면 0이 아닌 값을 반환한다

📌참고자료

profile
Be able to be vulnerable, in search of truth

0개의 댓글