Process Concept(프로세스 개념)
운영 체제는 다양한 프로그램을 실행합니다.
- 배치 시스템 - jobs
- Time-shared systems(시분할 시스템) - user programs 또는 tasks
- 교재에서는 job과 process라는 용어를 번갈아가면서 사용할 거라고 하네요
프로세스
- 실행 중인 프로그램(a program in execution)
프로세스는 다음을 포함합니다.
- 프로그램 코드(code), 텍스트 섹션(text section)이라고도 함
- 전역 변수 및 정적 변수를 포함하는 데이터 섹션(data section)
- 임시 데이터를 포함하는 스택(stack)
- 함수 매개변수, 반환 주소, 로컬 변수
- 실행 중 동적으로 할당된 메모리를 포함하는 힙(heap)
- 프로그램 카운터(program counter), 프로세서 레지스터 등의 현재 활동
Process State(프로세스 상태)
- 프로세스가 실행되면서 상태가 변경됩니다.
- 새로 생성됨 (New): 프로세스가 생성 중입니다.
- 실행 중 (Running): 명령어가 실행되고 있습니다.
- 대기 (Waiting, blocked나 sleep이라고도 함): 이벤트가 발생하기를 기다리고 있습니다.
- 준비 완료 (Ready): 프로세스가 프로세서에 할당되기를 기다리고 있습니다.
- 종료됨 (Terminated): 프로세스 실행이 완료되었습니다.
Diagram of Process State(프로세스 상태 다이어그램)
Process Control Block(PCB, 프로세스 제어 블록)
- 데이터를 관리하기 위한 메타데이터
- 프로세스에 대한 프로세스 제어 블록 (PCB), 태스크에 대한 태스크 제어 블록 (TCB)
- 예: 리눅스의 task_struct
- 파일에 대한 파일 제어 블록 (FCB)
- 예: 유닉스 파일 시스템의 vnode
- 프로세스에 대한 프로세스 제어 블록 (PCB), 태스크에 대한 태스크 제어 블록 (TCB)
각 프로세스와 관련된 정보
- 프로세스 ID (Process ID)
- 프로세스 상태 (Process state)
- New, ready, running, waiting, terminated
- 프로그램 카운터 (Program counter)
- 다음 명령어의 주소
- CPU 레지스터 (CPU registers)
- 스택 포인터, 범용 레지스터 등
- CPU 스케줄링 정보 (CPU scheduling information)
- 우선순위 등
- 메모리 관리 정보 (Memory-management information)
- 페이지 테이블, 세그먼트 테이블 등
- 회계 정보 (Accounting information)
- 사용된 CPU 양 등
- I/O 상태 정보 (I/O status information)
- 열린 파일, 할당된 I/O 장치 등
Process Scheduling Queues(프로세스 스케줄링 큐)
- Ready queue
- 메인 메모리에 상주하며 실행을 기다리는 모든 프로세스의 집합
- Device queues
- I/O 장치를 기다리는 프로세스의 집합
- 프로세스는 다양한 큐 사이를 이동합니다.
Ready queue와 다양한 I/O device queues
프로세스 스케줄링의 표현
Schedulers(스케줄러)
- CPU 스케줄러 (CPU scheduler)
- 다음에 실행될 프로세스를 선택하고 CPU를 할당합니다.
- 프로세스는 다음과 같이 분류될 수 있습니다.
- I/O 바운드 프로세스 (I/O-bound process)
- 계산보다 I/O를 더 많이 수행합니다.
- 짧은 CPU 버스트가 많습니다.
- CPU 바운드 프로세스 (CPU-bound process)
- 계산(computations)을 더 많이 수행합니다.
- 긴 CPU 버스트가 몇 개 있습니다.
- I/O 바운드 프로세스 (I/O-bound process)
- 스케줄링 알고리즘은 나중에 학습합니다.
Context Switch(컨텍스트 스위치)
- CPU가 다른 프로세스로 전환할 때 시스템은
- 이전 프로세스의 상태를 저장하고,
- 새 프로세스의 저장된 상태를 로드해야 합니다.
- 컨텍스트 스위치 시간은 순수 오버헤드(overhead)입니다.
- 전환(switching) 중 시스템은 유용한 작업을 수행하지 않습니다.
- 컨텍스트 스위치 시간은 하드웨어에 따라 다릅니다.
- 레지스터 세트가 다릅니다.
프로세스 간의 CPU 스위치
Process Creation(프로세스 생성)
- 부모 프로세스(Parent process)는 자식 프로세스(child process)를 생성합니다.
- 자식 프로세스는 다른 프로세스를 생성합니다.
- 최종적으로 프로세스 트리를 형성합니다.
자식 프로세스는 resource를 필요로 합니다.
- OS가 제공하거나 부모가 공유합니다.
Resource sharing
- 부모와 자식이 모든 resource를 공유
- 자식이 부모의 resource 일부(subset)를 공유
- 부모와 자식이 resource를 공유하지 않음
Execution
- 부모와 자식이 동시에 실행되거나
- 부모가 자식이 종료될 때까지 기다림
Address space
- 자식이 부모를 복제하거나
- 자식에게 새로운 프로그램이 로드됨
프로세스 생성 요약
- OS 커널 내에서 PCB 생성
- 메모리 공간 할당
- 바이너리 프로그램 로드
- 프로그램 초기화
UNIX 예시
이 부분은 유닉스 프로그래밍 들었으면 잘 아는 부분일거에요
- fork system call은 새로운 프로세스를 생성합니다.
- 부모의 PCB를 복제합니다.
- 메모리 공간을 할당합니다.
- execve system call은 fork 이후에 사용됩니다.
- 디스크에서 바이너리 프로그램을 로드합니다.
- 초기화합니다.
Process Termination(프로세스 종료)
- 프로세스는 마지막 명령을 실행하고 운영 체제에 자신을 삭제하도록 요청합니다 (exit).
- 자식 프로세스는 상태 값을 부모에게 반환합니다 (wait).
- 자식 프로세스의 resources는 운영 체제에 의해 할당 해제됩니다.
- 부모는 자식 프로세스의 실행을 종료할 수 있습니다 (abort).
- 자식이 할당된 자원을 초과했을 경우
- 자식에게 할당된 작업이 더 이상 필요하지 않은 경우
- 일부 운영 체제는 부모가 종료되면 자식이 존재하는 것을 허용하지 않습니다. 프로세스가 종료되면 모든 자식도 종료되어야 합니다.
- 계단식 종료 (cascading termination): 모든 자식, 손자 등은 종료됩니다.
- 종료는 운영 체제에 의해 시작됩니다.
- 부모 프로세스는 wait() 시스템 호출을 사용하여 자식 프로세스의 종료를 기다릴 수 있습니다. 이 호출은 종료된 프로세스의 상태 정보와 PID를 반환합니다.
pid = wait(&status);
- 부모가 기다리지 않으면 (wait()를 호출하지 않음) 프로세스는 좀비(zombie) 상태가 됩니다.
- 부모가 wait를 호출하지 않고 종료되면 프로세스는 고아(orphan) 상태가 됩니다.
Process Creation & Termination
프로세스 생성 및 종료
- 별도의 프로세스를 포크하는 C 프로그램 예시
int main() {
pid_t pid;
pid = fork();
if (pid < 0) { /* 오류 발생 */
fprintf(stderr, "Fork Failed");
exit(-1);
} else if (pid == 0) { /* 자식 프로세스 */
execlp("/bin/ls", "ls", NULL);
} else { /* 부모 프로세스 */
wait(NULL);
printf("Child Complete");
exit(0);
}
}
fork, exec, exit, wait System call
참고)
- fork(): 부모 프로세스에서 자식 프로세스를 생성
- exec(): 자식 프로세스에서 새로운 프로그램을 로드
- exit(): 프로세스 종료
- wait(): 부모 프로세스가 자식 프로세스의 종료를 기다림
Cooperating Processes
- Independent process
- 다른 프로세스의 실행에 영향을 주거나 영향을 받지 않습니다.
- Cooperating process
- 다른 프로세스의 실행에 영향을 주거나 영향을 받습니다.
프로세스 협력(process cooperation)의 장점
- 정보 공유 (Information sharing)
- 예: 공유 파일
- 계산 속도 향상 (Computation speed-up)
- 하위 작업을 통한 병렬 실행
- 모듈화 (Modularity)
- 시스템 기능을 별도의 작업으로 분할
통신 모델 (Communications models)
Producer-Consumer Problem(생산자-소비자 문제)
- 생산자 (producer) 프로세스는 소비자 (consumer) 프로세스가 소비하는 정보를 생성합니다.
- 예: 컴파일러(compiler)는 어셈블러(assembler)가 소비하는 어셈블리 코드를 생성합니다.
- 어셈블러(assembler)는 로더(loader)가 소비하는 오브젝트 모듈을 생성합니다.
- 무한 버퍼 (unbounded-buffer)
- 버퍼 크기에 실질적인 제한이 없습니다.
- 유한 버퍼 (bounded-buffer)
- 고정된 버퍼 크기를 가정합니다.
Shared memory solution(공유 메모리 솔루션)
- 공유 데이터
#define BUFFER_SIZE 10
typedef struct { ... } item;
item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
- in: 다음 빈 위치
- out: 첫 번째 채워진 위치
- 버퍼가 비어 있는 경우, in == out
- 버퍼가 가득 찬 경우, ((in + 1) % BUFFER_SIZE) == out
Producer process
item nextProduced;
while (true) {
/* nextProduced에 항목 생성 */
while (((in + 1) % BUFFER_SIZE) == out) ; /* 아무것도 하지 않음 -- 빈 버퍼 없음 */
buffer[in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
}
Consumer process
item nextConsumed;
while (true) {
while (in == out) ; // 소비할 것이 없음
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
return nextConsumed;
}
Message passing(메시지 전달)
- 프로세스는 주소 공간을 공유하지 않고 서로 통신합니다.
기본 연산 두 가지
- send(message)
- receive(message)
P와 Q가 통신하기를 원한다면
- 둘 사이에 통신 링크를 설정해야 합니다.
- send/receive를 통해 메시지를 교환합니다.
통신 링크 구현
- 물리적 (예: 하드웨어 버스, 네트워크 등)
- 논리적 (예: 직접/간접, 동기/비동기 등)
Direct Communication(직접 통신)
- 프로세스는 명시적으로 서로의 이름을 지정해야 합니다.
- send(P, message) - 프로세스 P에게 메시지를 보냅니다.
- receive(Q, message) - 프로세스 Q로부터 메시지를 받습니다.
- 프로세스의 식별자가 변경되면?
- 모든 이전 식별자에 대한 참조를 찾아서 변경해야 합니다.
Indirect Communication(간접 통신)
메시지는 메일박스로 보내지고 메일박스로부터 수신됩니다.
- 메일박스(Mailbox)
- 프로세스가 메시지를 놓을 수 있고, 메시지를 제거할 수 있는 객체입니다.
- 각 메일박스는 고유한 ID를 가집니다.
- 프로세스는 메일박스를 공유하는 경우에만 통신할 수 있습니다.
- Operations
- 새로운 메일박스를 생성합니다.
- 메일박스를 통해 메시지를 보내고 받습니다.
- 메일박스를 제거합니다.
- Primitives는 다음으로 정의된다:
- send(A, message) - 메일박스 A로 메시지를 보냅니다.
- receive(A, message) - 메일박스 A로부터 메시지를 받습니다.
Synchronization(동기화)
- 메시지 전달은 blocking 또는 non-blocking이 될 수 있습니다.
- Blocking은 synchronous(동기적)으로 간주됩니다.
- Blocking send은 메시지가 수신될 때까지 전송자를 블록합니다.
- Blocking receive은 메시지가 올 때까지 수신자를 블록합니다.
- Non-blocking은 asynchronous(비동기적)으로 간주됩니다.
- Non-blocking send은 전송자가 메시지를 보내고 계속 진행합니다.
- Non-blocking receive은 수신자가 유효한 메시지 또는 null을 수신합니다.
'Computer Science > 운영체제' 카테고리의 다른 글
[운영체제] 06. Synchronization Tools (0) | 2024.06.19 |
---|---|
[운영체제] 05. CPU Scheduling (0) | 2024.06.19 |
[운영체제] 04. Threads & Concurrency (0) | 2024.06.18 |
[운영체제] 02. Operating System Structures (0) | 2024.06.18 |
[운영체제] 01. Introduction to Operating System (0) | 2024.06.18 |