task_struct analyze short cut

간단하게 기본적인 task_struct 에 대해 설명한뒤 그 뒤에가 shortcut들임

리눅스에서 실행 단위는 task이고(task_struct로 관리), 유저 프로세스/스레드도 task이며 커널 스레드도 task다. 스케줄러가 각 논리 CPU에 task를 배치해 실행한다.

C
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
        /*
         * For reasons of header soup (see current_thread_info()), this
         * must be the first element of task_struct.
         */
        struct thread_info              thread_info;
#endif
        unsigned int                    __state;
        /* saved state for "spinlock sleepers" */
        unsigned int                    saved_state;
        /*
         * This begins the randomizable portion of task_struct. Only
         * scheduling-critical items should be added above here.
         */
        randomized_struct_fields_start
        void                            *stack;
        refcount_t                      usage;
        /* Per task flags (PF_*), defined further below: */
        unsigned int                    flags;
        unsigned int                    ptrace;
#ifdef CONFIG_SMP
        int                             on_cpu;
        struct __call_single_node       wake_entry;
        unsigned int                    wakee_flips;
        unsigned long                   wakee_flip_decay_ts;
        struct task_struct              *last_wakee;
        ...

드림핵에 있는 kernel 강의를 보면 다음과 같이 정리를 해놓았다.

task_struct는 태스크에 대한 대부분의 정보가 들어있는 거대한 구조체입니다.

  • pid_t pid: 프로세스 ID 입니다. 각 태스크는 고유한 pid를 가지고 있습니다.
  • pid_t tgid: 스레드 그룹 ID 입니다. 부모 프로세스로부터 생성된 스레드들은 서로 같은 tgid를 가지고 있습니다.
  • char comm[TASK_COMM_LEN]: 태스크의 실행 파일명을 저장하는 문자 배열입니다. 태스크를 식별할 때 사용됩니다.
  • struct list_head tasks: 태스크 리스트를 관리하는 리스트 헤드입니다. 이 리스트를 통해 시스템의 모든 태스크를 순회할 수 있습니다.
  • struct task_struct __rcu *parent: 태스크의 부모 태스크를 가리킵니다.
  • struct list_head children: 자식 태스크 목록을 관리하는 리스트 헤드입니다.
  • struct mm_struct *mm: 태스크의 메모리 관리를 위한 구조체 mm_struct의 포인터입니다. 이 mm_struct는 가상 메모리 영역, 페이지 테이블 등 메모리 관련 정보를 포함합니다.
  • struct files_struct *files: 태스크가 open()한 파일들을 관리하는 구조체 files_struct의 포인터입니다. 이 멤버를 통해 태스크가 열고 있는 파일의 목록과 각 파일의 상태를 관리합니다.
  • struct signal_struct *signal: 시그널을 처리하기 위한 정보를 포함하는 구조체 signal_struct의 포인터입니다. 이는 태스크가 받은 시그널과 시그널 처리 방법을 관리합니다.

또한 커널 코드를 보다보면 보이는

current 매크로는 CPU에서 현재 실행 중인 태스크의 task_struct 구조체를 가리키는 포인터이다. 이 매크로를 통해 커널 코드 어디서나 현재 실행 중인 태스크의 정보에 접근할 수 있어 다양한 커널 기능의 구현에 필수적이라고 한다.

그리고 우리가 흔히 아는 프로세스의 메모리는

C
struct mm_struct {
        struct {
                /*
                 * Fields which are often written to are placed in a separate
                 * cache line.
                 */
                ...
                unsigned long start_code, end_code, start_data, end_data;
                unsigned long start_brk, brk, start_stack;
                unsigned long arg_start, arg_end, env_start, env_end;
                ...
        } __randomize_layout;
        /*
         * The mm_cpumask needs to be at the end of mm_struct, because it
         * is dynamically sized based on nr_cpu_ids.
         */
        unsigned long cpu_bitmap[];
};

다음과 같이 task 구조체 안에 있는 mm_struct 구조체에 담겨져 있다.

여기서 start_code와 end_code는 코드 세그먼트의 시작과 끝의 주소를 담고 있고, start_data와 end_data는 데이터 세그먼트의 시작과 끝을, start_brk와 brk는 힙 세그먼트의 시작과 끝의 주소를 담고 있으며 brk는 알다시피 heap이 자라나기에 값이 커질 수 있다. 마지막으로 start_stack는 스택 세그먼트의 시작 주소를 의미함