이 포스팅은 Operating Systems: Three Easy Pieces, Remzi H. Arpaci-Dusseau & Andrea C. Arpaci-Dusseau을 읽고 개인 학습용으로 정리한 글입니다.
프로세스(process): 실행 중인 프로그램
프로그램: 디스크 상에 존재하는 실행을 위한 명령어와 정적 데이터의 묶음
-> 프로그램 자체는 생명이 없음
-> 프로그램을 읽고 실행하여 프로그램에 생명을 불어넣는 것이 운영체제
운영체제는 CPU를 가상화하여 CPU가 여러 개 존재한다는 환상 제공
하나의 프로세스를 실행하고, 얼마 후 중단시키고 다른 프로세스를 실행하는 작업을 반복
CPU를 공유하기 때문에, 각 프로세스의 성능은 낮아진다
메커니즘(mechanism): 필요한 기능을 구현하는 방법이나 규칙
ex. 문맥 교환(context switch): CPU에서 프로그램 실행을 잠시 중단하고 다른 프로그램을 실행하는 것
정책(policy): 운영체제 내에서 어떤 결정을 내리기 위한 알고리즘
ex. 스케쥴링 정책(scheduling policy): 실행 가능한 여러 프로그램들이 있을 때, 운영체제는 어느 프로그램을 실행시켜야 하는지 결정하는 알고리즘
프로세스(process): 운여엧제가 제공하는 실행 중인 프로그램의 개념
특정 순간의 프로세스를 간단하게 표현하려면, 실행되는 동안 접근했거나 영향을 받은 자원의 목록을 작성하면 된다
프로그램이 실행되는 동안 하드웨어 상태(machine state)를 읽거나 갱신할 수 있다
메모리
- 프로세스의 하드웨어 상태 중 가장 중요한 구성 요소
- 메모리에 명령어 & 실행 프로그램이 읽고 쓰는 데이터가 저장됨
- 프로세스가 접근할 수 있는 메모리 = 프로세스의 주소 공간(address space)
레지스터
- 프로세스의 하드웨어 상태의 구성 요소 중 하나
- 많은 명령어들이 레지스터를 직접 읽거나 갱신
프로그램은 영구 저장장치(persistent storage)에 접근하기도 함
-> 이 입출력 정보는 프로세스가 현재 열어 놓은 파일 목록을 가지고 있다
운영체제가 반드시 API로 제공해야 하는 기본 기능
생성(Create)
쉘에 명령어를 입력하거나 응용 프로그램의 아이콘 더블 클릭하여 프로그램 실행시키면 운영체제는 새로운 프로세스를 생성
제거(Destroy)
많은 프로세스는 실행되고 할 일을 다하면 스스로 종료한다
그러나 프로세스가 스스로 종료하지 않는 경우 필요없는 프로세스를 중단시켜야
대기(Wait)
때로는 어떤 프로세스의 실행 중지를 기다릴 필요가 있음
여러 종류의 대기 인터페이스 존재
각종 제어(Miscellaneous Control):
ex. 대부분의 운영체제는 프로세스를 일시정지하거나 재개하는 기능 제공
상태(Status)
프로세스 상태 정보를 얻어내는 인터페이스 제공
(프로세스의 상태 정보: 얼마 동안 실행되었는지, 프로세스가 어떤 상태에 있는지 등 포함)
프로그램 코드와 정적 데이터(static data)를 메모리, 프로세스의 주소 공간에 탑재(load)해야 한다
프로그램은 디스크 또는 플래시-기반 SSD에 특정 실행 파일 형식으로 존재
-> 운영체제는 디스크의 해당 바이트를 읽어서 메모리의 어딘가에 저장해야 한다
초기 운영체제들은 프로그램 실행 전에 코드와 데이터를 모두 메모리에 탑재하였음
현대의 운영체제들은 프로그램을 실행하면서 코드나 데이터가 필요할 때 필요한 부분만 메모리에 탑재한다
일정량의 메모리가 프로그램의 실행시간 스택(run-time stack) 용도로 할당 되어야 한다
C 프로그램은 지역 변수, 함수 인자, 리턴 주소 등을 저장하기 위해 스택 사용
⚡운영체제는 스택을 주어진 인자로 초기화한다
-> main()함수의 인자인 argc와 argv 벡터를 사용하여 스택 초기화
프로그램의 힙(heap)을 위한 메모리 영역을 할당한다
C 프로그램에서 힙은 동적으로 할당된 데이터를 저장하기 위해 사용된다
-> malloc()을 호출하려 필요한 공간 요청
-> free()를 호출하여 사용했던 공간 반환
힙은 연결 리스트, 해시 테이블, 트리 등 크키가 가변적인 자료구조를 위해 사용됨
⚡프로그램이 실행되면 malloc() 라이브러리 API를 호출하여 메모리를 요청하고, 운영체제가 이를 충족하도록 메모리를 할당한다
입출력과 관계된 초기화 작업을 수행한다
⚡Unix 시스템에서 각 프로세스는 기본적으로 세 개의 파일 디스크립터(file desctiptor)를 갖는다
-> 표준 입력(STDIN), 표준 출력(STDOUT), 표준 에러(STDERR)
-> 이 디스크립터들을 사용하여 프로그램은 터미널로부터 입력을 읽고 화면에 출력을 프린트하는 작업을 쉽게 할 수 있다
(1) 코드와 정적 데이터릴 메모리에 탑재하고, (2) 스택과 (3) 힙을 생성하고 초기화하고, (4) 입출력 셋업과 관계된 다른 작업을 마치게 되면, 운영체제는 프로그램 실행을 위한 준비를 마치게 된다
프로그램의 시작 지점(entry point), 즉 main()에서부터 프로그램 실행을 시작하는 마지막 작업만 남는다
-> main() 루틴으로 분기
-> 운영체제는 CPU를 새로 생성된 프로세스에게 넘김
-> 프로그램 실행 시작
프로세스의 상태는 다음 세 상태 중 하나에 존재할 수 있다
실행(Running):
프로세스는 프로세서에서 명령어를 실행 중이다
준비(Ready):
프로세스는 실행할 준비가 되어 있지만 운영체제가 다른 프로세스를 실행하고 있는 등의 이유로 대기 중이다
대기(Blocked):
프로세스가 다른 사건을 기다리는 동안 프로세스의 수행을 중단시키는 연산
ex. 프로세스가 디스크에 대한 입출력 요청을 하였을 때 프로세스는 입출력이 완료될 때까지 대기 상태가 되고, 다른 프로세스가 실행 상태로 될 수 있다
운영체제도 일종의 프로그램이다
-> 다른 프로그램들과 같이 다양한 정보를 유지하기 위한 자료구조를 가짐
xv6 커널에서 각 프로세스를 추적하기 위해 운영체제가 필요로 하는 정보
-> Linux, Mac OS X, Windows 같은 운영체제들도 이와 비슷한 프로세스 구조를 가짐
실행, 준비, 대기 이외에 다른 상태들 존재
초기(initial) 상태: 프로세스가 생성되는 동안 초기 상태에 머무른다
최종(final) 상태: 프로세스는 종료되었지만 메모리에 남아있는 상태
-> 프로세스가 성공적으로 실행했는지를 다른 프로세스(보통 부모 프로세스)가 검사하는 데 유용하다
부모 프로세스는 자식 프로세스의 종료를 대기하는 시스템 콜(ex. wait())을 호출한다
-> 이 호출은 종료된 프로세스와 관력된 자원들을 정리할 수 있다고 운영체제에게 알리는 역할도 한다
⚡Unix-기반 시스템에서는 최종 상태를 좀비(zombie) 상태라고 부른다
-> 프로세스가 성공적으로 종료되었으면 0을, 그렇지 않으면 0이 아닌 값을 반환한다