본문 바로가기

나름컴공이라공/Linux Kernel

Linux Kernal Internal > Ch3 태스크 관리(1)

☆★☆2016.01.07 작성☆★☆

☆★☆참고책 _리눅스 커널 내부구조(저자_백승재, 최종무)☆★☆

 

1. 프로세스와 쓰레드 그리고 태스크

* 태스크(task) : 자원소유권의 단위

* 쓰레드(thread) : 수행의 단위

* 프로세스(process) : running or runnable program 동작중인 프로그램으로 정의. 동적인 객체가 프로세스가 됨.

* 프로그램(program) : 디스크에 저장되어있는 수동적인 파일 형태 ≒ 실행파일.

* 프로그램이 수행되기 위해서 자원을 할당 받은 것이 프로세스.

 

2. 사용자 입장에서 프로세스 구조

* 프로세스가 수행되기 위해서 여어 자원들(가상 주소 공간)을 커널로부터 할당 받아야 함

* 32bit CPU, 각 프로세스 4GB 가상공간(실제 물리주소x) 할당

- 0~3GB 사용자 공간

- 3~4GB 커널 공간

(그림참조) http://mintnlatte.tistory.com/396

 

 

* text 영역 : CPU에서 직접 수행되는 명령어, 함수 등으로 구성(가장 하위 공간 차지)

* data 영역 : 전역 변수 등으로 구성(text영역 다음 부분)

* heap 영역 : 동적 메모리 할당(data영역 다음 부분)

- melloc()/free() 함수 사용하여 동적으로 메모리 공간을 할당 가능. 아래에서 위쪽 방향으로 크기가 커짐

* stack 영역 : 지역 변수, 인자, 함수 리턴 주소 등으로 구성(사용자 공간과 커널 공간의 경계위치 공간 차지)

- 함수를 호출할 때나 지역 변수를 저장하기 위해서 아래 방향으로 크기가 커지고, 함수에서 리턴되면 다시 스캑의 크기는 줄어듦(동적)

* text, data, heap, stack 영역 = segment(세그먼트), vm area struct(가상 메모리 객체)

 

3. 프로세스와 쓰레드의 생성과 수행

* 프로세스 생성 : fork(), vfork(), + create_process()

- 독립적인 pid

- 새 프로세스에 모든 자원을 새로 할당(주소 공간 등)

- 자식 프로세스에 발생한 결함이 부모 프로세스에 영향이 없음

-> 결함 고립에 적합한 프로그래밍 모델

 

* 쓰레드 생성 : pthread(), clone()

- 자식을 생성한 태스크와 동일한 pid

- 새 프로세스 x, 새 쓰레드 생성 o

- 부모 쓰레드와 같은 주소 공간 공유

- 자식 쓰레드에 발생함 결함이 부모 쓰레드에 영향이 있음

-> 자원 공유에 적합한 프로그래밍 모델

 

* 프로세스(태스크)의 수행 : execl()

- execl() 호출 순간, 앞에 수행되고 있던 프로세스 대신 새로운 프로세스를 덮어 씌움

 

* fork() 와 vfork() 의 차이점

- fork() : 부모 프로세스 주소 공간을 복사해서 자식 프로세스의 주소 공간을 따로 생성

- vfork() : 부모와 자식 프로세스가 같은 주소 공간을 가리키고 있다가 execl()함수를 통해 요청된 바이너리 기반으로 새로운 주소 공간 생성(호출시 새 주소 생성)

-> fork() 이후 execl() 되면 결국 fork() 때 수행했던 부모 프로세스 주소 공간을 복사하여 자식 프로세스의 주소 공간을 따로 만들어 주었던 작업이 불필요

이를 해결하기 위해 vfork()가 만들어짐(fork()에 COW 기법 적용)

- COW(Copy of Write) : 데이터의 복제를 지연, 방지

프로세스 주소 공간을 복제 하는 대신 부모와 자식이 주고 공간을 공유

데이터를 수정할 경우, 그 때의 주소 공간을 복제

 

4. 리눅스의 태스크 모델

* 리눅스 환경에서의 태스크 관리 구조

- 프로세스는 사용 자원과 수행되는 수행 흐름으로 구성

- 각 프로세스마다 task_struct이라는 자료 구조 생성

- 리눅스에서 프로세스가 생성되든, 쓰레드가 생성되든 동일한 자료 구조(task_struct)를 생성하여 관리

~ : thread / ㅁ : process

 

* 태스크 모델은 1대1 모델 기발 : 사용자 수준의 쓰레드 생성시 쓰레드의 존재를 커널도 앎

* 태스크

- 프로세스, 쓰레드 모두 커널 내부의 태스크라는 객체로 관리

- 태스크가 관리하는 자원을 어떻게 공유하고, 접근 제어하는지에 따라 프로세스인지 쓰레드인지 해석

* 태스크 흐름과 관계된 함수의 흐름

(그림 참조) http://hahaha333.egloos.com/3835505

 

 

- 사용자의 프로세스/쓰레드 생성 요청은 라이브러리(Library)를 거쳐 시스템 호출(System Call)을 통해 리눅스 커널에 전달

- fork(), clone(), pthread_create()는 커널에 구현되어 있는 sys_clone() 시스템 호출을 사용하고,

vfork()는 sys_vfork()를 사용하는데, sys_clone()과 sys_vfork()는 모두 커널 내부 함수 do_fork()를 호출

- fork()는 프로세스를 생성하는 함수이고, clone()은 쓰레드를 생성하는 함수인데, 커널 내부에서 동일한 함수 do_fork()를 호출하는 이유?

리눅스 입장에서는 모두 태스크를 생성하기 때문

 

* 존재하는 모든 태스크는 유일하게 구분이 가능해야하기 때문에, task_struct 구조체의 pid 필드에 해당 정보를 저장

- 한 프로세스 내의 쓰레드는 동일한 pid 공유 -> tgid 개념 (tgid는 동일, pid는 다름)

- tgid : thread group id

- 프로세스 생성하는 경우, tgid는 새 pid와 동일

- 쓰레드 생성하는 경우, 부모 태스크와 자식 태스크의 tgid는 동일(동일한 프로세스이기 때문)