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 함수에서 위 필드에 접근하게 된다.
'Embedded > Linux Kernel' 카테고리의 다른 글
[Linux Kernel] 테스크 디스크립터 매크로 함수 (0) | 2022.03.01 |
---|---|
[Linux Kernel] 테스크 디스크립터 자료구조 (0) | 2022.02.22 |
[Linux Kernel] gcc 컴파일 옵션 (0) | 2022.02.16 |
[Linux Kernel] ftrace 를 통한 유저 레벨 프로세스 분석(POSIX exit 종료 방식) (0) | 2022.02.16 |
[Linux Kernel] 프로세스 소멸 과정 소스 분석 (0) | 2022.02.16 |