1. 프로세스 종료 절차
실행(running)을 끝마친 프로세스는 바로 컴퓨터 시스템에서 사라지는 것이 아니라, 일련의 과정 (exit - terminated - wait)을 거친다.
프로세스 종료 조건
- exit() 시스템 콜을 호출받은 경우
- 처리할 수 없는 (non-handling) 시그널을 받은 경우
- CPU 내부 프로그램 에러가 발생한 경우
- 부모 프로세스가 하위 프로세스의 종료를 요청할 경우
Exit (release) 과정
- 실행이 끝난 직후 처리되는 시스템 콜. 메인 메모리 중 커널 내의 PCB를 제외한 코드, 데이터, 스택 등을 회수한다.
Terminated(zombie) 상태
- Exit() 처리를 통해 프로세스는 Terminated 상태로 진입한다.
- 부모 프로세스에 의해 Wait() 시스템 콜이 호출되면 소멸된다.
Wait 과정
- 부모 프로세스가 실행 통계(Accounting Information)를 읽어간다.
- 남아있던 PCB 데이터들을 완전히 삭제시킨다.
- 소멸되는 프로세스에게 하위 프로세스가 존재했다면, Init 프로세스(root)의 PCB로 전이시킨다.
2. 프로세스 간 통신 (Inter-Process Communication, IPC)
규모가 큰 서비스의 경우 서비스를 구성하는 프로그램들을 분할시키는데, 이들 간의 데이터 교환 방법론을 의미한다.
기본적으로 운영체제는 타 프로세스 간의 데이터 교환을 감시하고 있다.
Message Passing
- 고유식별자를 가진 메시지 큐(Message Queue)를 통한 통신 방식
- 메시지를 전송한 프로세스가 커널로 모드를 변환하여 큐에 집어넣는다. (Send)
- 메시지를 수신할 때도 커널로 이동하여 큐에 있는 메시지를 가져온다. (Receive)
- 구현은 쉬우나, 프로그램 동작 간 상대적으로 높은 비용을 요구한다. 원인은 프로세스의 잦은 커널 변환
Shared Memory
- Shared Memory라고 하는 메모리 공간이 별도로 할당된다.
- 프로세스가 커널 모드로 변환하여 메시지를 주고 받을 필요가 없어진다.
- 성능 면에서 유리하나, 메모리 공간에서 충돌이 발생할 수 있어 동기화가 필요하다.
- DB에서의 Transition 과정에서 이루어지는 충돌 방지 규칙과 유사
- 플래그 지정 등의 복잡한 코드 구성을 필요로 한다.
Interrupt / Signal
프로세스 간 이벤트가 발생했을 때 운영체제에게 처리를 요청하는 방법을 Interrupt라 하며,
일반 프로세스들에게 알리는 경우를 Signal이라 한다.
Signal을 수신한 경우, 아래 리스트 중 하나가 실행된다.
1) 프로세스 소멸
2) 프로세스 중지
3) 프로세스 무시
4) 사전 정의된 함수 실행
3. 쓰레드
프로세스 내부 실행 단위. CPU가 실행할 Instruction들의 그룹. 리눅스에서는 Lightweight Process(경량 프로세스)라고 부르기도 한다.
쓰레드와 프로세스
- 운영체제로부터 Instruction들을 할당받아 갖고 있는 것이 프로세스이고, 프로세스 내부에서 직접 돌아가는 실행체들을 쓰레드라고 칭하는 것이다. 따라서 쓰레드는 프로세스 내부에 존재한다고 볼 수 있다.
- 한 프로세스에 여러 개의 쓰레드가 존재할 수 있다.
- 쓰레드가 추가될 때마다, 해당 쓰레드의 레지스터 값과 스택을 저장하는 쓰레드 컨트롤 블럭(TCB)을 필요로 한다.
- 펑션들을 호출할 때 임시 정보를 저장하기 위해 스택을, 쓰레드 스위치 간에 주소 저장을 위해 레지스터를 별도로 갖는다.
- 레지스터 값과 스택을 제외한 프로세스의 코드, 데이터, 파일은 전역적으로 공유하여 사용한다.
- 리눅스 환경에서 clone() 시스템 콜을 통해 쓰레드를 복제한다.
파일
우리가 흔히 부르고 사용하는 파일은 프로세스 내부의 자원 이름이다.
기본적으로 운영체제에 의해 세 개의 파일이 주어지는데, 이는 입출력을 위한 장치 파일이다. (stdin,stdout,stderr)
쓰레드의 이점
- 프로세스를 생성, 소멸, 이동하는 것보다 효율적이다.
- 통신 과정에서도 프로세스(IPC)보다 더 효율적이다.
멀티쓰레드
CPU가 하나라고 가정하기 때문에, 쓰레드 간 + 프로세스 간의 일하는 시간은 겹치지 않는다. (Concurrent Programming)
복수의 CPU가 존재할 경우 동시간 대에 병렬적으로 처리하는 Overlapping이 발생한다. (Parellel Programming)
4. 쓰레드 종류
쓰레드의 생성 주체에 따라 두 가지 종류로 나뉜다.
유저 레벨 쓰레드
커널 외부 유저 프로그램 내부에 존재하는 쓰레드 라이브러리에 의해 생성되는 쓰레드
- 모드체인지가 필요 없기 때문에 쓰레드 생성과 관리 속도가 빠르다.
- 유저 레벨 쓰레드를 통해 복수의 쓰레드를 생성하여도 커널 입장에서는 하나의 쓰레드로 간주한다.
- 따라서 쓰레드가 커널에게 블록 요청을 보낼 경우 다른 쓰레드에게 전달하는 것이 아닌 아예 다른 프로세스로 넘겨 버린다. (=Concurrent하게 실행될 수 없다.)
커널 레벨 쓰레드
- Concurrent하게 쓰레드를 처리할 수 있다.
- 모드 체인지가 필요하기 떄문에 쓰레드 생성, 통신 시간이 상대적으로 많이 소요된다.