- 0~3GB : user address space
0 ~ : text, data, heap의 순으로.
3GB ~ 아래로 : stack
- 3~4GB : kernel address space
* linux child process
- parent process와 다른 주소공간, 다른 pid을 가짐.
- parent process에서 fork(or vfork)를 호출시 child process는 return value(pid)는 0 임.
=> 그렇다고 실제 child process의 pid가 0이라는 것은 아님. return value가 0일뿐.
* linux thread.
- 같은 process내의 모든 thread와 주소공간을 공유.
- clone api 또는 pthread(POXIS thread)를 모두 지원.
* child process / thread
- 자원 공유 모델의 다중 작업은 thread로.
=> thread는 다른 thread에 영향을 미치고, parent process에게까지 영향을 미침.
- 결함 고립 모델의 다중 자업은 child process로.
=> child process는 parent process와 독립적임.(주소공간의 독립)
* execve system call
- linux task 수행 system call
- execve system call을 호출한 후에는 호출한 process의 실행 Image는 더 이상 동작하지 않는다.
ex)
printf("hi");
execve("./fork", "fork", "-I", (char*)0);
printf("bye");
=> "bye"는 출력되지 않고, fork 실행 binary로 process의 image가 모두 바뀐다.
* fork와 vfork
- vfork는 parent process와 같은 주소공간을 가진다.
- fork는 parent process와 다른 주소공간을 가지고 있다.
- 현재 linux system은 COW(copy on write) 기법의 도입으로 fork 시 야기되는 주소공간 복사 비용이 많이 줄어든 상태임.
* linux는 1:1 모델
- process를 생성하던 thread를 생성하던 task_struct 라는 자료구조를 생성함.
- kernel은 process와 thread를 따로 구분하지 않음.
- 물론, thread가 어느 그룹에 속해 있느냐에 따라서 thread가 process 종속임을 나타냄.
* linux task
- process이든 thread이든 모두 task라는 객체로 관리.
- task가 관리하는 자원을 어떻게 공유하고 접근하느냐에 따라 process로 해석될수도 있고, thread로 해석될 수 있음.
- fork()[user app] -> fork()[library] -> clone()[system call] -> sys_clone() -> do_fork()
- clone()[user app] -> clone()[library] -> clone()[system call] -> sys_clone() -> do_fork()
- pthread_create[user app] -> pthread_create()[library] -> clone()[system call] -> sys_clone() -> do_fork()
- vfork[user app] -> vfork()[library] -> vfork()[system call] -> sys_vfork() -> do_fork()
- fork, clone, pthread_create 모두 kernel에 구현되어 있는 sys_clone함수를 호출하게 됨.
- sys_clone과 sys_vfork 역시 kernel 내부 함수인 do_fork를 호출함.
* do_fork
- do_fork는 fork와 clone에서 모두 호출됨.
- parent와 많은 공유를 하는 task의 경우는 clone.
- 비교적 부모와 많은 공유를 하지 않는 task는 fork.
- do_fork시 부모와의 공유 여부를 인자로 정해줌으로써 fork, clone을 모두 지원.
* pid, tgid
- pid는 process id
- POSIX 표준에 의하면 "Process 내의 모든 Thread는 동일한 PID를 공유해야 한다"고 명시되어 있음. 이를 위해 linux에서는 tgid(Thread Group ID)라는 개념을 도입.
- 새로운 task가 생성되면 pid가 할당되고, process라면 tgid는 pid와 같은 값이 된다. 만약 thread라면, tgid는 parent thread의 pid(= tgid)가 된다.
- 부모 task와 자식 task는 동일한 tgid를 가짐으로써, 동일한 process 내에 있다는 것을 알 수 있게 된다.
* context of task
- task의 context는 크게 3부분으로 구분한다.
- 첫 번째, System context로 task의 정보를 유지하기 위한 kernel이 할당한 자료구조들이다. 대표적인 자료구조로는 task_struct, file descriptor, file table, segment table, page table등이 잇다.
- 두 번째, Memory context로 text, data, stack, heap area, swap area등이 있다.
- 세 번째, Hardware context로 context switching시에 task의 현재 실행 위치에 대한 정보를 유지하고, thread 구조 또는 HW register context라고 불린다. 이 부분은 실행중이던 task가 대기상태나 준비상태로 전이할 때 이 task가 어디까지 실행했는지 기억해 두는 공간으로, 이후 이 task가 다시 실행할 때 필요한 정보들이다.
* task_struct
- task identification
- pid : process id
- tgid : thread group id
- pid를 통해 task의 task_struct를 빠르게 찾기 위한 hash관련 field등의 변수.
- uid : 사용자 id
- euid : 유효 사용자 id (binary의 유효한 user id, 실행가능 binary format에만 영향을 미치는 effective user id로써, binary가 실행될 때 binary의 보안은 euid의 권한을 가질 수 있다.)
- suid : set user id, user가 소유자의 user id로 실행되도록 하는 것.
- fsuid : file system user id
- gid, egid, sgid, fsgid등의 변수들
- state
- Task의 생성과 소멸까지의 많은 상태를 표현하는 state 변수가 존재.
- TASK_RUNNING(0), TASK_INTERRUPTIBLE(1), TASK_UNINTERRUPTIBLE(2), __TASK_STOPPED(4)... EXIT_ZOMBIE(32)등 여러 state가 있음.
- Sched.h 파일을 참조하면 보다 많은 state를 알수 있음.
- task relationship
- task는 생성되면 가족 관계를 가짐.
- 현재 task를 생성한 parent task의 task_struct를 가르키는 real_parent 필드와 현재 parent task의 task_struct를 가르키는 parent 필드를 가짐.
- 자식과 형제들 list로 연결한 뒤 그 list의 header를 각각 children, sibling 필드에 저장.
- linunx kernel에 존재하는 모든 task는 이중 linked list로 연결되어 있음.
- liked list의 시작은 init_task로 부터 시작되며, task_struct 구조체의 tasks(struct list_head tasks;)라는 list header를 통해서 연결된다.
- running 상태(TASK_RUNNING)의 task들은 따로, run_list 필드를 통해서 이중 연결 리스트로 연결됨.
- run_list 필드는 struct sched_rt_entity 내에 존재, task_struct 내에 struct sched_rt_entity rt;가 존재.
- scheduling information
- task_struct에서 스케줄링과 관련된 변수는 prio, array, policy, cpus_allowed, time_slice, rt_priority등이 있다.
- signal information
- signal은 task에서 비동기적인 사건의 발생을 알리는 매커니즘이다.
- task_struc에서 시그널 관련 변수는 signal, sighand, blocked, pending등이 있다.
- Memory information
- Task는 자신의 명령어와 테이터를 text, data, stack, heap area등 공간에 저장한다.
- task_struct에는 이 공간에 대한 위치, 크기, 접근 제어 정보등을 관리하는 변수들이 존재.
- 가상 주소를 물리 주소로 변환하기 위한 page directory와 page table등의 주소변환 정보들도 task_struct에 존재.
- 이러한 정보들은 task_struct에서 mm_struct라는 이름의 변수로 접근.
- file information
- task가 오픈한 파일들은 task_struct에서 files_struct 구조체 형태인 files라는 이름의 변수로 접근.
- root directory의 inode와 current directory의 indoe는 fs_struct 구조체 형태인 fs라는 변수로 접근할 수 있음.
- thread structure
- thread 구조(thread_struct : TSS)는 문맥교환을 수행할 때 task가 현재 어디까지 실행되었는지 기억해 놓는 공간.
- time information
- task의 시간 정보를 위한 변수로 task의 시작 시간을 가리키는 start_time, real_start_time등이 있으며, 사용한 CPU 시간을 나타내는 cpu_time, 대기시간을 나타내는 run_delay등이 있다.
- format
- binary format을 지원하기 위한 binfmt 변수, a.out, elf, java, shell script format등이 있다.
- resource limits
- 태스크가 사용할 수 있는 자원의 한계를 의미, rlim_max는 최대 허용 자원의 수, 그리고, rlim_cur은 현재 설정된 허용자원의 수를 의미한다.
- 다양한 종류의 Resource limit가 존재함.
- RLIMIT_CPU(프로세스가 사용 가능한 초 단위의 CPU 시간), RLIMIT_FSIZE(최대 사용 가능한 파일 크기), RLIMIT_DATA(최대 Heap 크기), RLIMIT_STACK(최대 스택 크기), RLIMIT_CORE(Core Dump File의 최대 크기), RLIMIT_RSS(Process가 소유할 수 있는 최대 Page Frame 수), RLIMIT_NPROC(사용자가 소유할 수 있는 최대 프로세스 수), RLIMIT_NOFILE(열기 가능한 최대 파일 디스크립터 개수), RLIMIT_MEMLOCK(스왑 불가능한 메모리 최대 크기), RLIMIT_AS(프로세스 주소 공간의 최대 크기)
- Resource.h 파일에 참조.
* Task state transition과 실행 수준 변화
댓글 없음:
댓글 쓰기