고급 개발자로 가는 길

Embedded/Linux Kernel

[Linux Kernel] 테스크 디스크립터 매크로 함수

다크엔지니어 2022. 3. 1. 19:11
반응형

매크로 얘기에 앞서,

프로세스 생성 시 copy_process 함수를 통해 최종적으로 task_struct 메모리 영역을 슬럽 캐시를 통해

미리 할당해 놓고, ARMv7 의 경우 mmu에 page 2개로 할당하여 0x2000의 스택 메모리 영역을 할당 받게 된다.

참고로 스택영역은 페이지 사이즈의 2배이다. 실제 소스에서 PAGE_SIZE<< THREAD_SIZE_ORDER 을 통해 할당한다.

또한, task_stcurt <->thread_info 를 통해 서로 주소 값을 연결지어 커널 입장에서 모든 프로세스의 주소와 스택 메모리 주소를 알게된다.

이후, 여러 커널 소스에서 테스크 디스크립터 및 스레드 인포의 필드 상태를 통해 인터럽트, 스케줄링 등 많은 영역에서 관련이 깊다.

그래서 커널은 주소 접근 시 이러한 요구사항을 만족하는 매크로를 제공하기에 이르렀고, 이것이 current 매크로 이다.

 

 

current 매크로

current 매크로를 통해 현재 점유 중인 프로세스의 주소를 알 수 있다.

current 매크로를 통해 테스크 디스크립터의 필드에 접근이 가능하다.

int __get_unused_fd_flags(unsigned flags, unsigned long nofile)
 {
         return __alloc_fd(current->files, 0, nofile, flags);
 }

실제 위 함수는 프로세스의 파일 디스크립터 할당을 위한 함수로 current 매크로를 통해 files 에 접근해 전달 한다.

실제 전역이나 지역변수로 할당은 안되어 있지만, task_struct * 와 같이 동작하게 된다.

이 밖에도 수 많은 함수에서 current 매크로 확인이 가능하다. 즉, 현재 구동 중인 프로세스의 테스크 디스크립터 주소에 접근 하는 것이다.

 

#ifndef __ASM_GENERIC_CURRENT_H
#define __ASM_GENERIC_CURRENT_H

#include <linux/thread_info.h>

#define get_current() (current_thread_info()->task)
#define current get_current()

#endif /* __ASM_GENERIC_CURRENT_H */

실제 current 구현부 이다. 즉 current 는 current_thread_info 함수를 사용하여 task 의 주소값을 치환 한다.

 

 

current_thread_info 매크로 함수

current_thread_info 함수는 이름에서 느낌이 오듯이 thread_info 구조체의 시작 주소 값을 return 한다.

즉, thread_info 의 task 필드를 접근하게 되는 것이다.

static __always_inline int preempt_count(void)
{
        return READ_ONCE(current_thread_info()->preempt_count);
}

실제, current_thread_info 함수로 현재 구동 중인 프로세스의 thread_info 구조체의 선점 스케줄링 관련인 preempt_count에 접근한다.

 

static inline struct thread_info *current_thread_info(void)
{
        return (struct thread_info *)
                (current_stack_pointer & ~(THREAD_SIZE - 1));
}

current_stack_pointer 는 실제 어셈블리 sp 에 접근하여 현재 실행 중인 프로세스의 스택 주소를 가리킨다.

~(THREAD_SIZE-1) 은 ~(0x2000-1) 로 ~(0x1FFF) 인 0xE000 이 된다.

즉, 현재 프로세스의 스택주소에 0xE000 을 AND 연산하여 masking 한다.

이렇게 하는 이유는 sp 의 4byte 중 2byte 만 필터링 하여, 0x2000 만큼 정렬을 맞추어서 최상단 주소값을 가져오기 위함이다.(0x2000 단위 이므로, E 는 1110 이므로 8, 4, 2 인 짝수만 필터링 하게 된다)

반응형