프로세스와 쓰레드

프로세스와 쓰레드

2020, Feb 01    


  • Program : 실행 가능한 코드, 바이너리로 파일로 저장되어 있습니다.
  • Process : 실행 중인 프로그램입니다. 프로세스는 프로그램의 이미지, 메모리 인스턴스, 커널 리소스 등의 정보를 포함합니다. 그리고 하나의 프로세스에는 하나 이상의 쓰레드를 포함하고 있습니다.
  • Thread : 프로세스의 실행 단위입니다. 가상화된 프로세스, 스택, 레지스터 및 명령어 포인터 등 프로세서의 상태를 포함하고 있습니다. 프로세스 내의 모든 쓰레드는 같은 주소 공간을 공유합니다. 특히, 글로번 변수 같은 경우는 쓰레드들 끼리 공유됩니다.(로컬 변수는 공유 안됨)


Drawing


  • 프로세스가 가지는 메모리 영역을 표현하면 위와 같이 표시할 수 있습니다.
  • 여기서 max가 메모리의 최대값을 나타냅니다.
  • 프로세스가 메모리에 올라가게 되면 위 그림과 같이 크게 4가지 영역으로 나뉘게 됩니다.
    • text 영역은 compile된 프로그램의 코드가 올라가게 됩니다. (object 파일, executable 파일 등)
    • data 영역은 다양한 데이터가 있는데 기본적으로 전역 변수가 들어간다고 보면 됩니다.
    • head 영역은 동적 메모리를 할당할 때 사용되는 영역입니다.
    • stack 영역은 동적 메모리 할당에 사용되지 않고 함수의 로컬 변수나 함수를 호출하거나 리턴할 때 사용됩니다.(재귀 함수 시에도 사용됨)
  • 위 그림처럼 stackheap의 메모리가 누적되는 방향이 다릅니다. 따라서 stack의 크기가 커지거나 heap의 크기가 커져서 꽉 차게 되면 메모리 영역에 stack과 heap 메모리가 마주치게 됩니다.
  • 물론 메모리 해제가 발생하면 다시 쌓였던 메모리가 없어지게 됩니다.


Drawing


  • 위 그림은 하나의 프로세스에서 쓰레드가 하나인 경우와 쓰레드가 여러개인 경우의 상태를 나타냅니다.
  • 쓰레드가 여러개이더라도 code, data, file들은 공유가되고 register, stack들은 각 쓰레드별로 따로 가지는 것을 알 수 있습니다.


Drawing


  • 프로세스들은 위 그림과 같이 계층 구조를 가지고 있습니다.
  • 이 계층 구조에서 상위 구조에 있는 프로세스가 부모(Parent) 프로세스이고 하위 구조에 있는 프로세스가 자식(Child) 프로세스입니다. 즉 트리 형태를 가지게 됩니다.
  • 이렇게 계층구조를 가지는 이유는 부모 프로세스가 자식 프로세스를 생성할 수 있기 때문입니다.
  • 각 노드를 보면 프로세스의 이름 이외에 프로세스의 아이디인 pid가 있습니다. pid는 프로세스 별로 유니크한 값을 가지게 되어 프로세스를 식별할 수 있는 아이디가 됩니다.
  • 가장 상위 계층인 init 프로세스는 커널이 부팅하는 과정에서 만들어 주는 프로세스로 가장 상위 계층에 있는 프로세스이고 부모 프로세스는 없습니다. 가장 처음 만들어지는 프로세스이므로 pid = 1입니다.
  • 그러면 어떻게 프로세스를 복제 및 생성하는 지 알아보도록 하겠습니다.


Drawing


  • 첫번째로 알아볼 API는 fork입니다.
  • 부모 프로세스에서 fork를 실행하면 자식 프로세스를 하나 만들어 주는데 이 떄, 부모 프로세스의 메모리 상태를 그대로 복사해서 자식 프로세스를 만들게 됩니다.
  • 복제된 2개의 프로세스가 생기므로 구분을 할 필요가 있는데, fork를 성공적으로 호출하였을 때, 반환값으로 pid_t라는 정수 형태의 값을 반환받는데 이 값을 통하여 부모 프로세스와 자식 프로세스를 구분하고 있습니다.
  • 성공적으로 호출하였을 때, 부모 프로세스의 경우 자식 프로세스의 pid를 반환받게 되고 자식 프로세스의 경우에는 0 값을 반환받으므로 부모와 자식 프로세스가 어떤 것인 지 구분할 수 있습니다. (이후에 살펴볼 코드를 보시면 더 자세하게 이해하실 수 있습니다.)
  • 호출을 실패하였을 때, 부모 프로세스는 -1의 값을 가지게 되고 자식 프로세스는 생성되지 않습니다.
  • 즉, 부모 프로세스 기준으로 반환값이 양의 값을 가지면 fork가 성공적으로 호출되어 자식 프로세스가 생성된 것이고 음수 값을 가지면 fork 호출이 실패한 것입니다.


Drawing


  • 현재 프로세스 관련 pid를 알아보기 위해서는 getpidgetppid API를 사용할 수 있습니다.
  • 현재 프로세스의 pid를 알아보려면 getpid를 사용하여 확인할 수 있고 현재 프로세스의 부모 프로세스를 알아보려면 getppid 함수를 이용하면 됩니다.