고급 개발자로 가는 길

Embedded/Linux Kernel

[Linux Kernel] 스레드 자료구조 thread_info 간단 설명

다크엔지니어 2022. 2. 27. 18:48
반응형

thread_info 구조체

task_struct 는 프로세스의 속성을 관리하고, thread_info 구조체는 프로세스 실행 동작을 관리한다.

테스크 디스크립터는 프로세스의 공통 속성 정보를 저장하고 관리하는데, 실제 세부 실행 정보를 저장 또는

로딩하는 자료구조로는 thread_info 가 사용 된다. 구조체의 특징으로는 

  • 선점 스케줄링 실행 여부
  • 시그널 전달 여부
  • 인터럽트 컨텍스트와 soft irq 상태
  • 휴면 상태로 진입하기 직전 레지스터 세트를 로딩 및 백업

thread_info 구조체는 프로세스 스택의 최상단 주소에 있다. 프로세스 마다 자신의 스택영역이 있으니, 

즉, 프로세스 마다 1개의 thread_info 구조체가 있는 것이며, ARM32bit 에서 프로세스 실행되는 스택의 크기는 0x2000바이트로 고정 되어있다.

프로세스 스택은 최하단 주소에서 최상단 주소 방향으로 시퀀스가 진행된다.

 

thread_info 구조체 에는 아래 정보를 저장한다.

  • 컨텍스트 정보
  • 스케줄링 직전 실행된 레지스터 세트 즉 SPSR
  • 프로세스 세부 실행 정보

테스크 디스크립터는 CPU 아키텍처가 상이해도 task_struct 기본 필드는 동일하다. 즉 공통적인 부분을 관리한다는 것이다.

thread_info 는 상세 세부동작을 관리하므로 당연 CPU 별로 상이한 것이다.

현재 실행중인 코드가 인터럽트 컨텍스트인지, 선점 가능 조건인지, 시그널을 받았는지 등을 관리한다.

정확히는 CPU 아키텍처 별로 서로 조금씩 상이하다. ARMv7 의 경우 아래와 같다.

struct thread_info {
        unsigned long           flags;          /* low level flags */
        int                     preempt_count;  /* 0 => preemptable, <0 => bug */
        mm_segment_t            addr_limit;     /* address limit */
        struct task_struct      *task;          /* main task structure */
        __u32                   cpu;            /* cpu */
        __u32                   cpu_domain;     /* cpu domain */
#ifdef CONFIG_STACKPROTECTOR_PER_TASK
        unsigned long           stack_canary;
#endif
        struct cpu_context_save cpu_context;    /* cpu context */
        __u32                   syscall;        /* syscall number */
        __u8                    used_cp[16];    /* thread used copro */
        unsigned long           tp_value[2];    /* TLS registers */
#ifdef CONFIG_CRUNCH
        struct crunch_state     crunchstate;
#endif
        union fp_state          fpstate __attribute__((aligned(8)));
        union vfp_state         vfpstate;
#ifdef CONFIG_ARM_THUMBEE
        unsigned long           thumbee_state;  /* ThumbEE Handler Base register */
#endif
};

 

필드 분석

flags 는 프로세스 동작을 관리하는 필드이다. 

/*
 * thread information flags:
 *  TIF_USEDFPU         - FPU was used by this task this quantum (SMP)
 *  TIF_POLLING_NRFLAG  - true if poll_idle() is polling TIF_NEED_RESCHED
 */
#define TIF_SIGPENDING          0       /* signal pending */
#define TIF_NEED_RESCHED        1       /* rescheduling necessary */
#define TIF_NOTIFY_RESUME       2       /* callback before returning to user */
#define TIF_UPROBE              3       /* breakpointed or singlestepping */
#define TIF_SYSCALL_TRACE       4       /* syscall trace active */
#define TIF_SYSCALL_AUDIT       5       /* syscall auditing active */
#define TIF_SYSCALL_TRACEPOINT  6       /* syscall tracepoint instrumentation */
#define TIF_SECCOMP             7       /* seccomp syscall filtering active */

#define TIF_USING_IWMMXT        17
#define TIF_MEMDIE              18      /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK     20

#define _TIF_SIGPENDING         (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED       (1 << TIF_NEED_RESCHED)
#define _TIF_NOTIFY_RESUME      (1 << TIF_NOTIFY_RESUME)
#define _TIF_UPROBE             (1 << TIF_UPROBE)
#define _TIF_SYSCALL_TRACE      (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT      (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_SECCOMP            (1 << TIF_SECCOMP)
#define _TIF_USING_IWMMXT       (1 << TIF_USING_IWMMXT)

등 플레그 설정 매크로가 있다. 프로세스에 시그널이 전달된 경우, 선점될 조건, 시스템 콜 트레이스 설정 등이 있다.

프로세스는 자신의 thread_info 의 flags 를 수시로 체크하며, 스기널, 선점스케줄링, 시스템 콜 트레이싱 조건인지를 체크 한다.

 

preempt_count 는 프로세스의 컨텍스트 정보를 저장하는 필드이다.

인터럽트 컨텍스트, soft irq 컨텍스트 등 실행 정보와 프로세스가 선점 스케줄링 될 조건을 저장한다.

 

cpu 는 번호를 저장하는 필드로 프로세스가 실행 중인 CPU 번호로 raw_smp_process_id() 호출하여 CPU 번호 확인된다.

 

*task 는 실행 중인 프로세스의 태스크 디스크립터의 주소를 저장한다. thread_info 주소만 알면 task 필드를 통해

프로세스의 태스크 디스크립터 주소를 알 수 있다.

 

cpu_context 필드는 컨텍스트 정보로 스케줄링 되기 전 실행했던 레지스터 세트를 저장한다. SPSR 의 역활이며,

스케줄링 되고 다시 실행될 때 cpu_context 필드에 저장된 레지스터를 프로세스 레지스터 세트로 로딩하게 된다.

struct cpu_context_save {
        __u32   r4;
        __u32   r5;
        __u32   r6;
        __u32   r7;
        __u32   r8;
        __u32   r9;
        __u32   sl;
        __u32   fp;
        __u32   sp;
        __u32   pc;
        __u32   extra[2];               /* Xscale 'acc' register, etc */
};

컨텍스트 스위칭 발생 시 switch_to 함수에서 위 필드에 접근하게 된다.

반응형