안녕하세요~~ 이우영 입니다.


참 오랜만에 글을 쓰는 거 같습니다.


오늘의 주제는 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); 를 추가합니다.


커널컴파일을 하고 보드에 올려보면 다음과 같이 문맥교환이 일어날때 마다 화면에 출력을 해줄겁니다.


Screenshot-woo@ubuntu^% ~.png  


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로 추가해주면 다음과 같이 문맥의 변화를 볼 수 있습니다.


스크린샷-woo@ubuntu- ~.png


오늘은 여기까지 입니다.

다음 시간에 만나요~

http://ms-osek.org/ <- 쫌더 빨리 보고 싶으신분은 여기로 오세요~