프로세스와 쓰레드
2020, Feb 01
Program
: 실행 가능한 코드, 바이너리로 파일로 저장되어 있습니다.Process
: 실행 중인 프로그램입니다. 프로세스는 프로그램의 이미지, 메모리 인스턴스, 커널 리소스 등의 정보를 포함합니다. 그리고 하나의 프로세스에는 하나 이상의 쓰레드를 포함하고 있습니다.Thread
: 프로세스의 실행 단위입니다. 가상화된 프로세스, 스택, 레지스터 및 명령어 포인터 등 프로세서의 상태를 포함하고 있습니다. 프로세스 내의 모든 쓰레드는 같은 주소 공간을 공유합니다. 특히, 글로번 변수 같은 경우는 쓰레드들 끼리 공유됩니다.(로컬 변수는 공유 안됨)
- 프로세스가 가지는 메모리 영역을 표현하면 위와 같이 표시할 수 있습니다.
- 여기서
max
가 메모리의 최대값을 나타냅니다. - 프로세스가 메모리에 올라가게 되면 위 그림과 같이 크게 4가지 영역으로 나뉘게 됩니다.
text 영역
은 compile된 프로그램의 코드가 올라가게 됩니다. (object 파일, executable 파일 등)data 영역
은 다양한 데이터가 있는데 기본적으로 전역 변수가 들어간다고 보면 됩니다.head 영역
은 동적 메모리를 할당할 때 사용되는 영역입니다.stack 영역
은 동적 메모리 할당에 사용되지 않고 함수의 로컬 변수나 함수를 호출하거나 리턴할 때 사용됩니다.(재귀 함수 시에도 사용됨)
- 위 그림처럼
stack
과heap
의 메모리가 누적되는 방향이 다릅니다. 따라서stack
의 크기가 커지거나heap
의 크기가 커져서 꽉 차게 되면 메모리 영역에 stack과 heap 메모리가 마주치게 됩니다. - 물론 메모리 해제가 발생하면 다시 쌓였던 메모리가 없어지게 됩니다.
- 위 그림은 하나의 프로세스에서 쓰레드가 하나인 경우와 쓰레드가 여러개인 경우의 상태를 나타냅니다.
- 쓰레드가 여러개이더라도 code, data, file들은 공유가되고 register, stack들은 각 쓰레드별로 따로 가지는 것을 알 수 있습니다.
- 프로세스들은 위 그림과 같이 계층 구조를 가지고 있습니다.
- 이 계층 구조에서 상위 구조에 있는 프로세스가 부모(Parent) 프로세스이고 하위 구조에 있는 프로세스가 자식(Child) 프로세스입니다. 즉 트리 형태를 가지게 됩니다.
- 이렇게 계층구조를 가지는 이유는 부모 프로세스가 자식 프로세스를 생성할 수 있기 때문입니다.
- 각 노드를 보면 프로세스의 이름 이외에 프로세스의 아이디인
pid
가 있습니다.pid
는 프로세스 별로 유니크한 값을 가지게 되어 프로세스를 식별할 수 있는 아이디가 됩니다. - 가장 상위 계층인
init
프로세스는 커널이 부팅하는 과정에서 만들어 주는 프로세스로 가장 상위 계층에 있는 프로세스이고 부모 프로세스는 없습니다. 가장 처음 만들어지는 프로세스이므로pid = 1
입니다. - 그러면 어떻게 프로세스를 복제 및 생성하는 지 알아보도록 하겠습니다.
- 첫번째로 알아볼 API는
fork
입니다. - 부모 프로세스에서
fork
를 실행하면 자식 프로세스를 하나 만들어 주는데 이 떄, 부모 프로세스의 메모리 상태를 그대로 복사해서 자식 프로세스를 만들게 됩니다. - 복제된 2개의 프로세스가 생기므로 구분을 할 필요가 있는데,
fork
를 성공적으로 호출하였을 때, 반환값으로pid_t
라는 정수 형태의 값을 반환받는데 이 값을 통하여 부모 프로세스와 자식 프로세스를 구분하고 있습니다. - 성공적으로 호출하였을 때, 부모 프로세스의 경우 자식 프로세스의
pid
를 반환받게 되고 자식 프로세스의 경우에는 0 값을 반환받으므로 부모와 자식 프로세스가 어떤 것인 지 구분할 수 있습니다. (이후에 살펴볼 코드를 보시면 더 자세하게 이해하실 수 있습니다.) - 호출을 실패하였을 때, 부모 프로세스는 -1의 값을 가지게 되고 자식 프로세스는 생성되지 않습니다.
- 즉,
부모 프로세스 기준
으로 반환값이 양의 값을 가지면 fork가 성공적으로 호출되어 자식 프로세스가 생성된 것이고 음수 값을 가지면 fork 호출이 실패한 것입니다.
- 현재 프로세스 관련
pid
를 알아보기 위해서는getpid
와getppid
API를 사용할 수 있습니다. - 현재 프로세스의
pid
를 알아보려면getpid
를 사용하여 확인할 수 있고 현재 프로세스의 부모 프로세스를 알아보려면getppid
함수를 이용하면 됩니다.