How does get_current() work?
Kernel 을 보다 보면, "current"를 사용한 코드들이 보인다. 이에 관련해서 어떻게 현재 수행중인 process의 task struct 를 갖고 올 수 있는지 확인해 보자.
참고 url : http://kernelnewbies.org/FAQ/get_current
http://kernelnewbies.org/FAQ/current
위의 두 가지를 참고하여 재구성 해봤다.
일단 process 마다 virtual address space 를 갖고 있다. 이는 User/Kernel 의 영역이 나뉘어져 있는데(대게 3G(user)/1G(kernel) 을 많이 사용한다), 이중 kernel 영역에 get_current() 를 통해 현재 process 정보를 얻어올 수 있도록 하는 것이 get_current() 이다.
Kernel 영역의 어디에 이와 같은 정보가 저장되느냐면, Kernel 이 갖고 있는 stack 의 가장 아래쪽에 저장되어 있다.(stack 이 높은 주소에서 낮은 주소 방향으로 이동하며 사용되니까 가장 아래쪽이라 하면.. 아래 그림을 보자)
대게 32bit 에서는 8KB stack 을 사용한다고 한다. 위에서 처럼 stack 의 맨 아래의 정보를 얻기 위한 macro가 get_current() 이다.
일단 get_current() 는 thread_info struct 정보를 넘기고 thread_info struct 는(architecture 마다 다른 듯 함.)
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 */
struct exec_domain *exec_domain; /* execution domain */
__u32 cpu; /* cpu */
__u32 cpu_domain; /* cpu domain */
struct cpu_context_save cpu_context; /* cpu context */
__u32 syscall; /* syscall number */
__u8 used_cp[16]; /* thread used copro */
unsigned long tp_value;
struct crunch_state crunchstate;
union fp_state fpstate __attribute__((aligned(8)));
union vfp_state vfpstate;
#ifdef CONFIG_ARM_THUMBEE
unsigned long thumbee_state; /* ThumbEE Handler Base register */
#endif
struct restart_block restart_block;
};
get_current() 로 얻은 thread_info 를 통해 현재 process의 상태 및 task_struct 도 갖고 올 수 있다.
Kernel Stack 은 항상 고정된 주소이고 이 thread info가 저장되는 위치는 항상 같은 곳이다. 그래서 얻어오는 과정의 소스를 분석해보자.
// code 에서 current->flag |= ... 이라고 사용하면
// current macro는
// include/asm-generic/current.h
#define get_current() (current_thread_info()->task)
#define current get_current()
간단하다. 위에서 처럼 current->XXX 로 사용하면 된다.(thread_info 구조체에 있는 녀석으로)
current_thread_info() 의 함수는 architecture 마다 따로 구현이 되어 있다. ARM 것을 보면,
// arch/arm/include/asm/thread_info.h
static inline struct thread_info *current_thread_info(void)
{
register unsigned long sp asm ("sp");
return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}
단지 현재 stack pointer register를 읽어다가, sp & ~(THREAD_SIZE - 1) 했다.
현재 32bit 의 ARM 에서 stack 의 크기는 8KB 이다. 그렇다면 stack 의 12bit 만 0으로 만들어 주면 제일 낮은 주소의 stack 주소가 나오고 거기에는 현재 thread_info 의 address가 있다는 것이다.(현재 stack pointer 가 위의 그림에서 중간쯤에 위치 하더라도 하위 12bit 만 0으로 해주면 맨 아래의 thread_info 를 접근 할 수 있을 것이다.)
이렇게 해서 current macro를 이용해서 thread_info 구조체의 내용을 갖고와 process 의 status 확인 및 control 이 가능 한것이다.
'Linux Kernel Study' 카테고리의 다른 글
[책 소개] 리눅스 커널 패치와 커밋 (1) | 2015.04.17 |
---|---|
Qemu booted kernel debugging with GDB (0) | 2013.11.22 |
[Kernel] define 으로 do { ... } while(0) 많이 쓰는 이유 (2) | 2013.10.22 |
Kernel Likely/Unlikely (2) | 2013.10.21 |
나의 첫 kernel patch 등록!!! (0) | 2013.10.17 |