강좌 & 팁
안녕하세요~~ 이우영 입니다.
참 오랜만에 글을 쓰는 거 같습니다.
오늘의 주제는 context_switch 입니다.
한글로 하면 문맥교환? 쯤 되겠죠?
리눅스의 /kernel/sched.c 에 보시면
context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next)
함수가 존재하고 있습니다. 여기서는 MM과 thread의 정보를 다음 실행될 thread의 정보로 교환해줍니다.
실제 문맥을 바꾸는 함수를 찾아 봅시다.
context_switch 함수는 switch_to 함수를 부르고 switch_to는 __switch_to 함수를 호출합니다.
switch_to, __switch_to 함수는 /arch/arm/include/asm/system.h 에 정의되어 있습니다.
208extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
209
210#define switch_to(prev,next,last) \
211do { \
212 last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
213} while (0)
이번에 공부한 jprobe를 통해서 내부를 확인해 봅시다.
그러나 __switch_to 함수는 어셈블리어로 되어있고, switch_to는 define 되어있습니다.
jprobe도 만능이 아닌지라 그냥 호출하기에는 무리였습니다.
그래서 jprobe로 끼어들 함수를 하나 만들어 주었습니다.
/kernel/sched.c 에 아래 함수를 추가하고
void my_switch_to( struct task_struct *prev,
struct task_struct *next,
struct task_struct *last )
{
printk("my_switch_to\n");
}
context_switch 안에서 switch_to 함수를 호출하기 전에 my_switch_to(prev,next,preb); 를 추가합니다.
커널컴파일을 하고 보드에 올려보면 다음과 같이 문맥교환이 일어날때 마다 화면에 출력을 해줄겁니다.
my_switch_to 함수안에서 확인하고픈 만큼 다 확인해도 좋지만 jprobe를 등록해서 확인해 봅시다.
07_context_switch.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kprobes.h>
#include <linux/sched.h>
static void probe_context_switch( struct task_struct *prev,
struct task_struct *next,
struct task_struct *last )
{
printk("prev task_id = %d next task_id = %d\n",prev->pid, next->pid);
jprobe_return();
}
static struct jprobe my_probe = {
.entry = (kprobe_opcode_t *)probe_context_switch
};
int module_start() {
my_probe.kp.symbol_name ="my_switch_to";
// my_probe.kp.addr = (kprobe_opcode_t *)0xc003e7dc; <- 직접 함수위치를 지정하는 방법
do{
if( register_jprobe(&my_probe) < 0 ) {
printk("oop`s!\n");
}
}while(0);
return 0;
}
void module_end() {
unregister_jprobe(&my_probe);
}
module_init(module_start);
module_exit(module_end);
MODULE_LICENSE("GPL");
insmod로 추가해주면 다음과 같이 문맥의 변화를 볼 수 있습니다.