Programming/OS, Program, Framework Tip

리눅스의 프로세스와 쓰레드

awesometic 2017. 3. 10. 15:32
반응형

 아래 내용에서 잘못된 점은 꼭 알려주세요


 [프로세스와 쓰레드]

 먼저 프로세스와 쓰레드의 의미는 다음과 같습니다.

 프로세스(Process)는 프로그램 하나가 실행될 때 쓰이는 단위입니다. OS로부터 메모리 공간을 할당받고, 스케쥴링 될 수 있습니다.

 쓰레드(Thread)는 프로세스 안의 작은 작업 단위입니다. 따라서 프로세스는 작업을 위해 최소 하나 이상의 쓰레드가 있어야 합니다. 쓰레드는 여러개가 존재할 수 있고, 프로세스의 메모리 자원을 공유할 수 있으며, 때문에 하나의 자원에 여러 쓰레드가 달려들 때 일어날 수 있는 동기화 문제를 신경써야 합니다. 자기 자신만의 스택을 가질 수 있습니다.

 다시 말해 프로세스는 그저 프로그램이 메모리에 로드되어 있고, 실행(스케쥴링)될 수 있다는 그 자체로 봅니다. 여러분이 작성한 소스 코드는 하나 이상의 쓰레드가 훑고 지나가는 겁니다.


 [리눅스 기반 시스템의 프로세스와 쓰레드]

 리눅스는 멀티쓰레드 친화적입니다. 사실 기술적으로 모든 작업 단위를 태스크(Task)로 처리합니다. 태스크는 메모리의 자원 덩어리라고 보시면 됩니다. 그리고 리눅스는 멀티태스킹 운영체제입니다.

 프로그램 내 수많은 태스크들을 프로세스 안의 하나의 쓰레드가 전부 처리하기엔 부하가 커질 수 있기 때문에 다른 쓰레드를 따로 만들어 필요한 일만 하게끔 합니다. 프로세스가 쓰레드를 만드는 과정은, 프로세스가 자식 프로세스를 만드는 과정과 시스템 내에선 크게 다르지 않습니다. 따라서 쓰레드를 세미 프로세스 또는 가벼운 프로세스(Light-weight process)라고도 합니다.


 [리눅스 기반 시스템의 프로세스 생성 과정]

 리눅스는 부팅될 때 부트로더에서 커널(Kernel)을 작동시킵니다. 커널은 프로세스가 아닌 CPU를 위한 디바이스 드라이버라고 생각할 수 있다고 합니다. (http://stackoverflow.com/questions/35629353/is-kernel-a-process) 커널은 init 프로세스를 실행합니다.

 init 프로세스의 설명을 보면, 모든 프로세스의 부모 프로세스라고 합니다. 위키피디아에서 init 프로세스에 대한 설명을 보면,(https://en.wikipedia.org/wiki/Init)

  Init is a daemon process that continues running until the system is shut down. It is the direct or indirect ancestor of all other processes and automatically adopts all orphaned processes.

 라고 되어 있습니다. 바로 이 init 프로세스로부터 모든 시스템/사용자 프로세스가 파생됩니다.

 리눅스 시스템에선 부모 프로세스에서 자식 프로세스를 만들 때 fork()와 exec()를 실행시킵니다. fork()는 부모프로세스와 동일한 정보(PCB)를 갖는 자식 프로세스를 만드는 시스템 콜(System call)이고, exec()는 새로운 정보로 exec()를 호출하는 부모 프로세스를 덮어버리는 시스템 콜입니다.

 따라서, 부모와 다른 일을 하는 자식 프로세스를 생성하길 원하는 부모 프로세스는 다음과 같은 과정을 거칩니다.

 1. fork()로 자신과 동일한 자식 프로세스를 만들고,

 2. 자식 프로세스에서 exec()해 다른 것처럼 보이게 합니다.

 이런 과정을 통해 init 프로세스로부터 모든 프로세스가 파생된 프로세스 트리(Process tree)가 구현될 수 있습니다.


 [리눅스 기반 시스템의 프로세스와 쓰레드 차이]

 같은 프로그램 내에서 조그만 작업을 처리하는데 fork()를 통해 부모와 동일한 자식 프로세스를 만드는 건 너무 오버헤드가 큽니다. 때문에 생긴 개념이 쓰레드입니다.

 쓰레드는 자식프로세스와 비슷한 방식으로 생성됩니다. 부모 프로세스의 PCB 정보를 포함해 모두 갖습니다. 하지만 PCB 내 대부분의 정보가 포인터로 이루어져 있습니다. 몇몇 구조체에서만 자신이 쓰레드임을 알기 위해 다른 정보가 들어 있습니다.

 무슨 말이냐면, 부모 프로세스의 정보를 포인터로만 갖고 있어 같은 정보에 접근할 수 있지만 굉장히 가볍고, 해당 정보로 필요한 작업만을 처리할 수 있다는 겁니다. 따라서 쓰레드를 가벼운 프로세스라고 합니다.

 실제로 리눅스에선 쓰레드를 생성해도 PID는 부모프로세스와 같지만 쓰레드로서 고유 SPID를 갖습니다. (ps -T 옵션 참고)


반응형