눈팅하는 게임개발자 블로그
Process 본문
프로세스
보조기억장치에 적재되어 있던 프로그램이 실행을 위해 메모리에 적재되어
코드, 데이터, 힙, 스택 메모리 영역을 할당 받아 프로세스가 된다.
프로세스의 Life Cycle
프로세스는 생성에서 소멸까지의 상태가 변하면서
Ready, Running, Terminated, Zombie, Blocked의 5가지 상태를 가질 수 있다.
프로그램이 최초 실행되어 메모리에 적재되면 언젠가 스케줄이 될 수 있도록 Ready 상태가 된다.
이후 스케줄되어 Running 상태로 변하여 프로세스가 실행되며.
프로세스 실행 중 다른 작업이 끝나길 기다리거나 IO 입출력이 실행되면 Blocked 상태로 변해 대기하게 된다.
이후 프로세스가 완료되거나 종료되면 Terminated/Zomibe 상태가 되어 종료 코드를 남긴다.
프로세스 주소 공간
프로세스의 주소 공간은 코드, 데이터, 힙, 스택의 4가지 영역으로 나뉘어진다.
코드 영역 : 프로그램의 코드들(명령어들)이 저장되는 영역.
데이터 영역 : 전역 변수, static 변수들이 저장되는 영역, 초기화 되지 않은 전역변수는 BSS에 저장된다.
힙 영역 : 동적으로 할당된 변수들이 저장되는 영역.
스택 영역 : 지역변수, 매개변수를 받는 함수의 경우 매개변수가 저장되는 영역
논리적 주소 공간, 프로세스 매핑 테이블
프로세스 A와 프로세스 B가 같이 메모리에 올라와 있고,
프로세스 A의 주소는 0부터 시작하며, 프로세스 B의 주소 또한 0부터 시작한다.
이렇게 될 경우 변수의 주소가 겹쳐서 충돌이 발생할 수 있을 것이다.
하지만 프로세스를 통해 확인할 수 있는 주소는 프로세스 내의 상대적 주소 공간일 뿐.
실제 메모리가 위치한 주소가 아니다.
이를 논리적 주소 공간이라 한다.
그리고 이를 가능하게 하는 것이 프로세스 매핑 테이블이다.
프로세스 매핑 테이블은 각 프로세스가 할당 받은 실제 물리 메모리 영역의 주소를
기록하고 있으며 특정 프로세스가 메모리에 액세스를 시도할 경우
매핑 테이블을 통해 물리 메모리에 액세스를 하게 된다.
예를 들어 프로세스 A가 물리적으로 할당받은 메모리 영역의 주소가 100번지라면
프로세스 A가 자신의 0번지 메모리 주소에 액세스를 시도 할 경우
매핑 테이블을 통해 물리 메모리의 100번지 주소에 액세스하게 되는 것이다.
PCB(Process Control Block)
운영체제가 관리하는 운영체제 상의 프로세스들에 대한 정보를 저장하는 구조체.
프로세스 제어 블록에 저장되는 정보들
1. PID(Process ID) : 프로세스의 ID가 되는 정수.
2. PPID(Parent Process ID) : 해당 프로세스의 부모가 가진 PID
3. Process State : 해당 프로세스의 상태(Ready, Running, Blocked 등)
4. CPU Context : CPU 내부 레지스터들의 상태 정보
5. 스케줄링 정보 : 해당 프로세스가 가진 우선순위, nice 값(우선순위의 반대개념), 스케줄 큐에 대한 포인터 등
6. 프로세스 종료 코드 : exit()시스템 호출 시(프로세스 종료 시) 부모 프로세스에게 전달하는 0~255 사이의 정수값
7. 열어 놓은 파일 디스크립터들의 배열
8. 메모리 관리 정보 : 페이지 테이블의 메모리 위치, 프로세스에게 할당된 물리 메모리 주소 등
9. 회계 정보 : CPU 사용 시간, 시간 제한, 프로세스의 총 경과시간 등
10. 프로세스 소유자 이름 : 프로세스를 생성한 사용자의 정보
IPC(Inter-Process Communication)
프로세스 간 통신 방법, 커널의 도움을 받는다.
공유 메모리, 신호(Signal), 파이프가 있다.
공유 메모리
프로세스 간 공유하는 메모리를 "파일"처럼 컴퓨터 내에 저장하여 파일을 사용하듯 공유 메모리를 사용한다.
- 한 컴퓨터 내에서 실행되는 프로세스 사이에서만 통신 가능
- 한 프로세스가 먼저 커널에 요청하여 공유 메모리를 할당(파일 생성)
- 다른 프로세스는 생성된 공유 메모리에 접근 가능
- 공유 메모리 액세스는 파일 액세스와 방법이 같다. (/dev/shm/ 이하의 디렉터리에 생긴 파일처럼 다룬다.)
- 공유 메모리에 액세스하고자 하는 프로세스는 해당 공유 메모리의 이름을 알고 있어야 한다.
- 공유 메모리는 물리 메모리에 생성되며 해당 물리 메모리를 각 프로세스의 가상 메모리에 매핑하여 각 프로세스는 해당 가상 메모리에 액세스하는 방식.
POSIX IPC 라이브러리 함수들.
shm_open() 공유 메모리 생성
ftruncate() 공유 메모리를 필요한 크기로 변경, 이후부터 다른 프로세스에서 접근 가능
mmap() 공유 메모리 영역을 가상 프로세스 주소 공간에 매핑
munmap() 가상 주소 공간 매핑 해제, close()로 해당 공유 메모리(파일)을 닫는다.
shm_unlink() 공유 메모리를 시스템에서 제거.
신호(Signal)
프로세스가 커널에 요청하여 다른 프로세스에게 비동기적 이벤트를 알리는 방법으로 통신.
1. signal()시스템 호출. 신호를 수신할 신호 핸들러를 등록.
2. 목적 프로세스에게 신호 전송(위의 경우 kill() 시스템 호출)
3. 신호 발생(signal generation), kill()시스템 호출을 서비스하는 커널 코드에 의해 실행. 목적 프로세스의 PCB의 신호 큐에 신호가 발생함이 표시된다.
4. 신호 전파(signal delivery) 목적 프로세스의 신호 핸들러 실행, 신호 핸들러가 등록되어 있는 경우 실행.
파이프(pipe)
프로세스들이 메시지를 전송하기 위해 커널에 생성되는 메모리. 원형 큐와 유사하게 작동한다.
- 익명의 파이프(anonymous pipe)
파이프를 생성한 부모와 자식 간에 메시지를 주고 받기 위한 목적, 하나의 컴퓨터 시스템에서만 유효
pipe()시스템 호출, 파이프를 생성하고 매개 변수로 0번째 인덱스에는 수신용 파일 디스크립터를,
1번째 인덱스에는 송신용 파일 디스크립터를 저장한다.
- 이름을 가진 파이프(named pipe, FIFO)
파이프의 이름을 아는 프로세스들끼리 메시지를 주고 받기 위한 목적,
네트워크로 연결된 여러 컴퓨터 시스템에서도 사용 가능.