- 코드로읽는리눅스디바이스드라이버 - 2011.1.3 강남용 (nykang@ssu.ac.kr)
커널스레드 스레드란? 스레드종류 도우미인터페이스 연결리스트 해시리스트 작업큐 통지연쇄 완료인터페이스 kthread 도우미 오류처리지원 ( 원시코드살펴보기 ) 2
스레드란? - 하나의프로그램내에서실행되는함수를의미 - 일반적인프로세서의경우는한순간에하나의함수만실행되지만, 스레드를사용하면동시에여러함수를실행가능 3
스레드의종류 : 사용자스레드, 커널스레드 사용자스레드 - 사용자스레드는커널영역의상위에서지원되며일반적으로유저레벨의라이브러리를통해구현되며라이브러리는커널의지원없이유저공간에서스레드의생성과, 스케줄링, 관리를지원한다. - 장점 : 생성과관리가빠르다. - 단점 : 여러개의사용자스레드중하나의스레드가시스템호출등으로중단되면나머지모든스레드역시중단되는단점이있다 4
스레드의종류 : 사용자스레드, 커널스레드 커널스레드 - 커널스레드는운영체제가지원하는스레드기능으로구현되며, 커널이스레드의생성및스케줄링등을관리한다 - 장점 : 스레드가시스템호출등으로중단되더라도, 커널은프로세스내의다른스레드를중단시키지않고계속실행시켜준다. - 단점 : 사용자스레드에비해생성및관리하는것이느리다 5
연결리스트 usr/src/kernel/{version}/include/linux/list.h struct list_head { // 이중연결리스트자료구조를만들어내는구조체 }; struct list_head *next, *prev; 6
연결리스트 LIST_HEAD(list_name) : 리스트를새로만듬 list_add(n,p) : p 가가리키는요소다음에 n 을가리키는요소삽입 list_add_tail(n,h) : 첫번째요소의주소인 h 로지정한리스트의맨끝에 n 이가리키는요소삽입 list_del(p) : p 가가리키는요소삭제 list_empty(p) : 첫번째요소의주소로지정한리스트가비어있는지검사 list_entry(p, t, f) : 이름이 f 고주소가 p 인 list_head 필드를포함한 t 타입자료구조의주소반환 list_for_each(p,h) : 첫번째요소의주소 h 로지정한리스트에있는요소를차례로 \ 검색 7
해시리스트 usr/src/kernel/{version}/include/linux/list.h 8
작업큐 workqueue_struct, work_struct 커널내부에서작업을지연시켜주는수단 ( 오류인터럽트에반응한네트워크어댑터재시동 ) struct workqueue_struct *test; create_singlethread_workqueue(const char *name); //workque 를생성 struct work_struct *work; // 작업구성요소를생성한다. INIT_WORK(work, func, data); // 초기화 queue_work(test, work); // 큐에작업을넣는다. 9
작업큐 위치 설명 work_struct include/linux/workqueue.h 커널내부에서작업을지연하는방식인작업큐를 구현하는구조체 DECLARE_WAITQUEUE () include/linux/wait.h 대기큐를선언한다 add_wait_queue() kernel/wait.c 태스크를대기큐에밀어넣는다. 이태스크는다른 스레드나인터럽트처리기가깨울떄까지잔다. remove_wait_queue() kernel/waint.c 대기큐에서잠자고있는태스크를빼낸다. wake_up_interruptible() include/linux/wait.h kernel/sched.c 대기큐내부에서잠자고있는태스크를꺠워스케줄러실행큐로옮긴다 schedule() kenel/sched.c 프로세서를양보해커널의다른부분이실행하게허 용한다. set_current_state() include/linux/sched.h 프로세서실행상태를설정한다. 10
통지연쇄 상태변화메시지들을코드영역에전달할때사용 사망통지 : 커널함수가 oops, 페이지폴트가발생했을때전달된다. 네트워크디바이스통지 : 네트워크인터페이스가올라오고내려갈때생성된다.(ifconfig eth0 up) CPU 주파수통지 : 프로세서주파수에변화가있을떄생성된다. 인터넷주소통지 : 네트워크인터페이스 IP 주소가바뀔때생성된다. 11
통지연쇄 위치 설명 notifier_block include/linux/notifier.h 요청한코드영역에상태변경내용을전달하기위해 쓰이는구조체 register_die_notifier() arch/your-arch/kernel/traps.c 사망통지를등록한다. register_netdevice_notifie r() net/core/dev.c 넷디바이스통지를등록한다. register_inetaddr_notifier( ) net/ipv4/devinet.c inetaddr 통지를등록한다 BLOCKING_NOTIFIER_ HEAD() blocking_notifier_chain_r egister() ATOMIC_NOTIFIER_HE AD() atomic_notifier_chain_reg ister() include/linux/notifier.h 사용자정의차단통지를생성한다. kernel/sys.c 차단통지를등록한다. include/linux/notifier.h 원자적인통지를생성한다. ( 원자적 : 중단됨이없이한번에실행되는것을의미 ) kernel/sys.c 원자적인통지를등록한다. 12
완료인터페이스 커널스레드가수행되고완료가되게끔 도와주는역할 드라이버모듈은커널스레드를사용한다. rmmod 로모듈을제거하면커널영역에서모듈코드를제거하기전에 release() 함수를호출한다. 이방식은스레드에게스스로종료하게요청하고, 스레드가완료될때까지기다린다. kthread 도우미 스레드생성작업과관리를용이하게해준다. daemonize( thread_name ); kernel_thread(my_thread, NULL, CLONE_FS CLONE_FILES CLONE_SIG HAND SIGCHLD); kthread_create(my_thread, NULL, %s, my_thread) 13
완료인터페이스와 kthread 도우미 위치 설명 completion include/linux/completion.h 독자적인스레드로활동을시작하고활동이끝날때 까지기다리기위해사용하는구조체 complete() kernel/sched.c 완료를알린다. wait_for_completion() kernel/sched.c 완료객체가끝날때까지기다린다. complete_and_exit() kernel/exit.c 원자적으로완료와종료시그널을보낸다. kthread_create() kernel/kthread.c 커널스레드를생성한다. kthread_stop() kernel/kthread.c 커널스레드에게멈추도록요청한다. kthread_should_stop() kernel/kthread.c 커널스레드는다른스레드가 kthread_stop() 으로 중단을요청했는지감지하기위해사용한다. 14
오류처리지원 IS_ERR() : 반환값이오류코드인지를점검한다. PTR_ERR() : 오류코드를알려준다. buf = malloc(100, GFP_KERNEL); if(is_err(buf)){ printk( Error returned is %d! \n, PTR_ERR(buf)); } Error returned is -12! (/usr/include/asm/errno.h, #define ENOMEM 12 /* Out of memory */) 15