Process
프로세스 = 실행 중인 프로그램
Process = Batch system : jobs = Time-shared system : user programs or tasks)
프로그램은 디스크에 저장된 passive entity(exe file)이며 프로세스는 active
프로그램이 메모리에 로딩돼서 실행되면 하나의 프로세스가 됨
하나의 프로그램이 여러 프로세스가 될 수 있음
프로그램의 실행은 마우스 클릭, 명령어 입력, 터치, 음성 등으로 시작
Text Section : 프로그램 코드
현재 활동은 Program counter, Process register를 포함
Stack : 일시적인 데이터 (함수 파라미터, 반환 주소, 지역 변수) - Data : 글로벌 변수, 정적 변수, 상수
Heap : 동적으로 할당되는 메모리
main 함수의 파라미터는 스택 위의 별도 영역에 할당
- Text : 코드의 크기
- data : 초기화된 데이터 영역
- bss : 초기화되지 않은 데이터 영역
- dec : 위 3개의 합
프로그램을 실행한 상태에서 두 번째 실행하면 메모리에 code(text)는 올라가지 않음
Mac이나 iOS는 2번째 실행해도 각각 코드가 올라가서 최적화되어서 빠르게 실행
Program Counter란?
->현재 실행되고 있는 프로세스가 다음에 실행할 명령어의 주소를 가리키고 있는 레지스터
모든 프로세스마다 필요 (레지스터는 CPU 코어 옆에 존재, 메모리상에 X)
Process State
new : 프로세스가 실행되고 메모리에 올라오기 전
ready : 프로세스가 메모리에 올라옴, OS도 인지, CPU에는 X
running : 명령어가 실행 중인 상태, CPU를 차지, ready 상태에서 OS가 허락하면 CPU로 올라옴
waiting : I/O 이벤트 등 큰 이벤트를 기다리는 상태
terminated : 프로세스가 실행을 완료한 상태, 흔적은 남음
Process Control Block (PCB)
- OS가 프로세스를 관리하기 위해 만들어 놓는 자료구조
- Process Number : 프로세스의 번호
- Process State : 프로세스의 상태
- Program Counter : 한 프로세스의 스레드가 여러 개이면 여러 개가 필요
- CPU Registers : 모든 프로세스 중심 레지스터의 내용
- CPU Scheduling Information : 우선순위, 스케줄링 큐 포인터 등
- Memory 관리 정보 : 프로세스에 할당된 메모리
- Accounting 정보 : 사용된 CPU, 시작 이후 경과된 시간, 시간 제한
- I/O 상태 정보 : 프로세스에 할당된 I/O 장치, 열려있는 파일 목록
Context Switch Overhead
P0이 멈추고 P1이 시작될 때까지의 시간
P0의 PCB를 저장하고 P1의 PCB를 로드하는 시간
Linux의 task_struct (C의 구조체로 표현)
mm : memory map 메모리 접근을 어떻게 수행하는지에 대한 정보
time_slice : 한번 CPU를 차지하면 실행되는 시간
Process Scheduling
OS의 목적은 CPU의 활용도를 극대화하는 것 / Time Sharing을 위해 CPU 상의 프로세스를 빠르게 Switch함
Process Scheduler는 현재 Ready 상태인 프로세스 중에서 어떤 것을 CPU에 넘길지 결정하는 것
- Job Queue : 시스템 내의 모든 프로세스를 모아놓은 큐
- Ready Queue : 메인 메모리에 상주하고 Ready 상태인 모든 프로세스를 모아놓은 큐
- Device Queue : I/O 장치를 기다리는 프로세스의 집합, I/O 장치마다 하나의 큐가 있음
새 프로세스는 초기에 Ready Queue에 놓인 후, 실행을 위해 선택(Dispatch)될 때까지 Ready Queue에서 기다림
일단 프로세스에 CPU가 할당되면, 아래 사건 중 하나가 발생할 때까지 해당 프로세스가 CPU에서 실행됨
프로세스가 입출력 요청하여 I/O Queue에 넣어짐
인터럽트 또는 할당된 시간 간격이 만료되어 프로세스가 코어에서 강제로 제거되어 준비 큐에 돌아갈 수 있음 (time slice expired)
프로세스가 새 자식 프로세스를 생성하고 자식 프로세스의 종료를 기다리는 동안 대기 큐에 놓일 수 있음 (fork a child)
프로세스가 인터럽트(timer event) 발생을 기다림
Schedulers
Short-term Scheduler (or CPU Scheduler)
- 다음에 실행될 프로세스를 선택하고 CPU를 할당 (일반적인 Process Scheduling)
- 밀리초 단위로 자주 호출되며 빠르게 실행되어야 함
Long-term Scheduler (or job Scheduler)
- Ready Queue에서 (메모리에서) 가져올 프로세스를 선택
- 초, 분 단위로 드물게 호출되며 느릴 수 있음
- Multiprogramming의 정도를 제어
- 프로세스의 좋은 조합을 제공하여야 함
프로세스의 2가지 종류
- I/O-bound Process : 계산보다 I/O 작업에 더 많은 시간을 소비 / 짧은 CPU burst가 많음 (파일 검색)
- CPU-bound Process : 계산 작업에 더 많은 시간을 소비 / 긴 CPU burst가 적음 (정렬)
Medium-term Scheduler (Swapping)
- 다중 프로그래밍 정도를 줄여야 할 필요가 있을 때 추가함
- 메모리에서 프로세스를 제거하고 디스크에 저장한 후, 디스크에서 메모리로 다시 가져와 실행을 계속함
Context Switch
CPU가 다른 프로세스로 전환될 때, 이전 프로세스의 상태를 저장하고 새 프로세스의 상태를 로드하는 작업
프로세스의 Context는 PCB에 나타남
Context Switch의 시간은 overhead이며 스위칭하는 동안 시스템은 유용한 작업을 하지 않음
복잡한 OS와 PCB는 더 긴 Context Switch가 걸림
하드웨어에 따라 시간이 결정 / CPU당 레지스터가 많으면 여러 Context를 한 번에 로드 가능함
Process Creation
부모 프로세스가 자식 프로세스를 생성, 이 자식 프로세스들은 또 다른 프로세스를 생성 -> 프로세스 트리
일반적으로 프로세스는 Process Identifier(PID)를 통해 식별/관리
Resource sharing 옵션 : 부모와 자식이 모든 리소스 공유 / 자식이 부모 리소스의 일부분 공유 / 공유 X
Execution 옵션 : 부모와 자식이 동시에 실행 / 부모는 자식이 종료될 때까지 대기 (wait 함수)
Process Creation 과정
- 실행할 수 있는 이진 파일을 Storage에서 메모리로 로드
- Runtime Stack 영역 / Heap 영역 할당 (Code랑 Data 영역은 이미 갖고 있음)
- I/O 설정 (기본적으로 3개의 파일 디스크립터가 할당 (Standard input, Standard output, Standard error)
- OS -> 생성된 프로세스로 제어가 이동하면 main() 함수가 시작
주소 공간
- 자식이 부모의 주소 공간을 복제
- 자식은 그 주소에 새 프로그램이 로드된 상태
- fork()로 복사해서 새 프로세스를 만들고 exec()이 실행되면 자식의 메모리가 덮어써짐
- system() : fork() + exec() + wait()
Process Termination
프로세스는 마지막 명령을 실행한 후, exit() 시스템 콜을 통해 OS에게 자신을 삭제하도록 요청
자식이 부모에게 상태 데이터를 반환 / OS에 의해 프로세스 리소스가 해제, PCB 해제
부모는 abort() 시스템 콜을 이용해 자식의 실행을 종료할 수 있음
- 자식이 할당된 리소스를 초과한 경우
- 자식에게 할당된 작업이 더 이상 필요하지 않은 경우
- 부모가 종료되고 OS가 자식이 계속되는 것을 허락하지 않는 경우
- cascading termination : 모든 자식이 종료됨. 종료는 OS에 의해 시작됨 (안정성을 중요시하는 시스템)
부모는 wait() 시스템 콜을 통해 자식이 끝나는 것을 기다릴 수 있음
이 콜은 상태 정보와 종료된 프로세스의 pid 값을 반환
기다리는 부모가 없다면 (wait() 호출을 안 한 경우) -> zombie process (문제가 될 수 있음)
부모가 wait() 호출 없이 종료되었다면 -> orphan process (부모가 없어지면 그 위가 부모가 되므로 문제 X)
Android 프로세스 계층
모바일 운영체제는 제한된 시스템 자원을 회수하기 위해 종종 프로세스를 종료시킴
가장 낮은 순위의 프로세스부터 종료함
프로세스의 중요도 계층
- Foreground 프로세스 : 사용자가 직접 사용
- Visible 프로세스 : Foreground가 참조하는 활동을 수행하는 프로세스
- Service 프로세스 : 예시 - 음악 스트리밍
- Background 프로세스
- Empty 프로세스 : 프로세스 간의 통신을 할 때 중간 매개체로 활용 (리소스 공유 목적, 명령어는 X)
Interprocess Communication (IPC)
시스템 내의 프로세스는 independent(독립적) or cooperating(협력적)
협력적 프로세스는 다른 프로세스에 영향을 미칠 수 있거나 받을 수 있음
협력적 프로세스는 IPC가 필요
협력적 프로세스의 이유
- 정보 공유
- 계산 속도 향상
- 모듈성
협력적 프로세스 모델
- Shared Memory
- Message Passing
- Pipe
- (Signal)
공유 메모리 : 속도가 빠름 & 동기화가 필요
메시지 패싱 : 메시지는 헤더, 데이터 등의 포맷이 존재, 속도가 느림
Shared Memory
- 통신을 위해 프로세스 사이에 공유되는 메모리 영역
- 통신은 OS가 아니라 사용자 프로세스의 제어 아래에서 이루어짐
- 사용자 프로세스가 공유 메모리에 접근할 때 동기화할 수 있는 메커니즘을 제공하는 것이 중요
- unbounded-buffer : 버퍼의 크기에 실질적인 제한이 없는 공간
- bounded-buffer : 고정된 버퍼의 크기를 가정 (write 할 수 있는 공간을 정함)
- Producer 프로세스는 Consumer 프로세스가 소비하는 정보를 생산
Shared Memory - Producer 프로세스와 Consumer 프로세스
- 컴파일러는 어셈블러가 사용하는 어셈블리 코드를 생산
- 어셈블러는 목적 모듈(object module)을 생산하고, 이는 로더에 의해 사용
- 생산자/소비자 프로세스들은 동시에 수행
- 프로세스들은 공유 메모리(버퍼)를 통해 상호 통신
- 생산자는 항목(item)을 생산하고 이를 버퍼에 저장
- 소비자는 버퍼에 있는 항목(item)을 소비
- 가용한 항목이 있을 때만 소비자 프로세스가 소비할 수 있도록, 소비자-생산자 프로세스는 동기화 필요
Shared Memory - 공유 버퍼 (Bounded-Buffer)
- 두 개의 논리적 포인터인 in과 out을 갖는 원형 배열로 구현
- (BUFFER_SIZE-1)개보다 많은 원소를 저장할 수 없음 (full/empty의 구분을 위해)
- 공백(empty) : when in == out (Consumer 공백이면 잠시 멈춤)
- 가득 참(full) : when (in+1)&BUFFER_SIZE == out (Producer가 가득 차면 잠시 멈춤)
Message Passing
- 프로세스가 통신하고 작업을 동기화하는 메커니즘
- 프로세스가 공유된 변수를 사용하지 않고 서로 통신
- 작업 종류 : send & receive / 메시지의 크기 : 고정 & 가변
- 두 프로세스가 통신하기 위해서는 그들 사이의 통신 링크 구현, send/receive 메시지 교환이 필요
- 통신 링크의 구현 : 특정 메모리 공간을 메시지 큐로 잡아주는 과정
- 물리적 : 공유 메모리, 하드웨어 버스(주로 I/O 기기), 네트워크
- 논리적 : 직접 / 간접, 동기화 / 비동기화, 자동 버퍼링 / 명시적 버퍼링
Message Passing - Direct Communication
- 프로세스는 명시적으로 서로 이름을 붙임
- send(P, message) : P에게 메시지를 보냄
- receive(Q, message) : Q로부터 메시지를 받음 - 통신 링크의 속성
- 링크는 자동으로 설정 / 링크는 정확히 한 쌍의 통신 프로세스와 연관
- 각 쌍 사이에 정확히 하나의 링크가 존재 / 링크는 단방향일 수 있지만 일반적으로 양방향
Message Passing - Indirect Communication
- 메시지를 메일박스(혹은 포트)로 보내고 받음 / 각 메일박스는 고유 id를 가짐
- 프로세스는 그들이 메일박스를 공유할 때만 통신 가능
- 통신 링크의 속성
- 링크는 프로세스들이 같은 메일박스를 공유할 때만 설정 / 링크는 많은 프로세스와 관련될 수 있음
- 각 프로세스 쌍은 여러 통신 링크를 공유 가능 / 링크는 단방향, 양방향 모두 가능 - 연산 : 새 메일박스 생성 / 메일박스를 통한 send, receive / 메일박스 파괴
- send(A, message) : 메일박스 A로 메시지를 보냄
- receive(A, message) : 메일박스 A로부터 메시지를 받음 - 3개의 프로세스가 한 메일박스를 공유할 때, P1이 보낸 메시지는 P2, P3 중에 누가 받는가?
- 하나의 링크가 최대 2개의 프로세스와 관련될 수 있도록 허용
- 한 번의 하나의 프로세스만 수신 작업을 실행하도록 허용
- 시스템이 수신자를 임의로 선택하도록 허용, 송신자에게 수신자가 누구인지 알림
Message Passing - 메시지 패싱 방식
- Blocking : 동기화
- Blocking Send : 메시지가 수신될 때까지 송신자는 차단
- Blocking Receive : 메시지가 사용 가능할 때까지 수신자를 차단 - Non-blocking : 비동기화
- Non-blocking Send : 송신자는 메시지를 보내고 계속 진행
- Non-blocking Receive : 수신자는 가능한 메시지 혹은 null 메시지를 수신 - 다양한 조합이 가능 / send, receive 모두 blocking 상태이면 랑데부(rendezvous) 발생
Buffering
- Zero capacity : 큐에 메시지가 들어가지 않고 송신자는 수신자를 기다려야 함 (랑데부) (Blocking send/receive)
- Bounded capacity : 유한한 길이의 큐 / 송신자는 링크가 가득 찼으면 기다려야 함
- Unbounded capacity : 무한한 길이의 큐 / 송신자는 기다리지 않음
Pipes
프로세스 사이의 통신을 가능하게 하는 역할
- 단방향 or 양방향
- 양방향인 경우, half-duplex or full-duplex (서로 주고받을 때 한쪽만 가능한지 양쪽 모두 가능한지)
- 통신하는 프로세스 사이에 관계(부모-자식)가 필요한가?
- 파이프를 네트워크상에서 사용 가능한가?
Ordinary pipes
- 생성한 프로세스 외부에서 접근 불가능, 일반적으로 부모가 생성하고 자식과 통신하는데 사용
- 표준적인 생산자-소비자 스타일의 통신 가능
- 부모-자식의 관계가 필요
- 단방향 통신 -> fd[1]에서 쓰기 / fd[0]에서 읽기
- Windows에서는 익명 파이프(anonymous pipes)라고 부름
Named pipes
- 부모-자식 관계가 필요하지 않음
- 양방향 통신
- 여러 프로세스가 Named pipe를 이용하여 통신 가능
- UNIX와 Windows 모두 제공
FIFO in UNIX
- mkfifo()로 생성, open(), read(), write(), close() - Named pipes on Windows
- byte- or message-oriented data 지원
- CreateNamePipe(), ReadFile(), WriteFile()
'Operating System [OS]' 카테고리의 다른 글
[OS] 06. Threads & Concurrency (2) | 2024.01.02 |
---|---|
[OS] 05. Virtual Memory (2) | 2024.01.02 |
[OS] 04. Main Memory (2) | 2024.01.02 |
[OS] 03. CPU Scheduling (3) | 2024.01.01 |
[OS] 01. Operating System Structures (1) | 2023.12.29 |