[ZLG-ARM] 关于内核线程的入门和讨论

[复制链接]
 楼主| qtopia 发表于 2009-7-8 13:25 | 显示全部楼层 |阅读模式
.&nbsp;ps&nbsp;出来的哪些是&nbsp;内核线程?<br /><br />2.&nbsp;内核线程&nbsp;是不是&nbsp;独立存在的,&nbsp;跟某个进程不关的?&nbsp;<br /><br />3.&nbsp;内核线程是怎样增加的?<br />&nbsp;<br /> &nbsp;&nbsp;<br />.&nbsp;ps&nbsp;-elf&nbsp;的结果中最后面一栏,如果CMD是用[&nbsp;]&nbsp;包含起来的就为内核线程,如[ksoftirqd/1]等<br />2.&nbsp;嗯,内核线程只运行在内核态,与普通的进程无关。<br />3.&nbsp;使用函数kernel_thread创建新的内核线程。&nbsp;<br /><br />ULK上面讲到:<br /><br />QUOTE:<br />3.4.2.&nbsp;Kernel&nbsp;Threads<br />Traditional&nbsp;Unix&nbsp;systems&nbsp;delegate&nbsp;some&nbsp;critical&nbsp;tasks&nbsp;to&nbsp;intermittently&nbsp;running&nbsp;processes,&nbsp;including&nbsp;flushing&nbsp;disk&nbsp;caches,&nbsp;swapping&nbsp;out&nbsp;unused&nbsp;pages,&nbsp;servicing&nbsp;network&nbsp;connections,&nbsp;and&nbsp;so&nbsp;on.&nbsp;Indeed,&nbsp;it&nbsp;is&nbsp;not&nbsp;efficient&nbsp;to&nbsp;perform&nbsp;these&nbsp;tasks&nbsp;in&nbsp;strict&nbsp;linear&nbsp;fashion;&nbsp;both&nbsp;their&nbsp;functions&nbsp;and&nbsp;the&nbsp;end&nbsp;user&nbsp;processes&nbsp;get&nbsp;better&nbsp;response&nbsp;if&nbsp;they&nbsp;are&nbsp;scheduled&nbsp;in&nbsp;the&nbsp;background.&nbsp;Because&nbsp;some&nbsp;of&nbsp;the&nbsp;system&nbsp;processes&nbsp;run&nbsp;only&nbsp;in&nbsp;Kernel&nbsp;Mode,&nbsp;modern&nbsp;operating&nbsp;systems&nbsp;delegate&nbsp;their&nbsp;functions&nbsp;to&nbsp;kernel&nbsp;threads&nbsp;,&nbsp;which&nbsp;are&nbsp;not&nbsp;encumbered&nbsp;with&nbsp;the&nbsp;unnecessary&nbsp;User&nbsp;Mode&nbsp;context.&nbsp;In&nbsp;Linux,&nbsp;kernel&nbsp;threads&nbsp;differ&nbsp;from&nbsp;regular&nbsp;processes&nbsp;in&nbsp;the&nbsp;following&nbsp;ways:<br /><br />Kernel&nbsp;threads&nbsp;run&nbsp;only&nbsp;in&nbsp;Kernel&nbsp;Mode,&nbsp;while&nbsp;regular&nbsp;processes&nbsp;run&nbsp;alternatively&nbsp;in&nbsp;Kernel&nbsp;Mode&nbsp;and&nbsp;in&nbsp;User&nbsp;Mode.<br /><br />Because&nbsp;kernel&nbsp;threads&nbsp;run&nbsp;only&nbsp;in&nbsp;Kernel&nbsp;Mode,&nbsp;they&nbsp;use&nbsp;only&nbsp;linear&nbsp;addresses&nbsp;greater&nbsp;than&nbsp;PAGE_OFFSET.&nbsp;Regular&nbsp;processes,&nbsp;on&nbsp;the&nbsp;other&nbsp;hand,&nbsp;use&nbsp;all&nbsp;four&nbsp;gigabytes&nbsp;of&nbsp;linear&nbsp;addresses,&nbsp;in&nbsp;either&nbsp;User&nbsp;Mode&nbsp;or&nbsp;Kernel&nbsp;Mode.<br /><br />3.4.2.1.&nbsp;Creating&nbsp;a&nbsp;kernel&nbsp;thread<br />The&nbsp;kernel_thread(&nbsp;)&nbsp;function&nbsp;creates&nbsp;a&nbsp;new&nbsp;kernel&nbsp;thread.&nbsp;It&nbsp;receives&nbsp;as&nbsp;parameters&nbsp;the&nbsp;address&nbsp;of&nbsp;the&nbsp;kernel&nbsp;function&nbsp;to&nbsp;be&nbsp;executed&nbsp;(fn),&nbsp;the&nbsp;argument&nbsp;to&nbsp;be&nbsp;passed&nbsp;to&nbsp;that&nbsp;function&nbsp;(arg),&nbsp;and&nbsp;a&nbsp;set&nbsp;of&nbsp;clone&nbsp;flags&nbsp;(flags).&nbsp;The&nbsp;function&nbsp;essentially&nbsp;invokes&nbsp;do_fork(&nbsp;)&nbsp;as&nbsp;follows:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;do_fork(flags|CLONE_VM|CLONE_UNTRACED,&nbsp;0,&nbsp;pregs,&nbsp;0,&nbsp;NULL,&nbsp;NULL);<br /><br /><br />The&nbsp;CLONE_VM&nbsp;flag&nbsp;avoids&nbsp;the&nbsp;duplication&nbsp;of&nbsp;the&nbsp;page&nbsp;tables&nbsp;of&nbsp;the&nbsp;calling&nbsp;process:&nbsp;this&nbsp;duplication&nbsp;would&nbsp;be&nbsp;a&nbsp;waste&nbsp;of&nbsp;time&nbsp;and&nbsp;memory,&nbsp;because&nbsp;the&nbsp;new&nbsp;kernel&nbsp;thread&nbsp;will&nbsp;not&nbsp;access&nbsp;the&nbsp;User&nbsp;Mode&nbsp;address&nbsp;space&nbsp;anyway.&nbsp;The&nbsp;CLONE_UNTRACED&nbsp;flag&nbsp;ensures&nbsp;that&nbsp;no&nbsp;process&nbsp;will&nbsp;be&nbsp;able&nbsp;to&nbsp;trace&nbsp;the&nbsp;new&nbsp;kernel&nbsp;thread,&nbsp;even&nbsp;if&nbsp;the&nbsp;calling&nbsp;process&nbsp;is&nbsp;being&nbsp;traced.<br /><br />第三个问题,可能是我一时不知怎样表达,现整理这样:<br /><br />一个进程对应一个内核线程(多线程除外),当进程exit后,这个内核线程会不会也exit?<br />&nbsp;<br /> &nbsp;&nbsp;<br />内核线程是在内核态创建的,&nbsp;和普通的进程没有对应关系.&nbsp;所以谈不上进程exit后,&nbsp;内核线程也exit.<br />这样的话,进程通过什么手段和一个内核线程联系在一起的?能否大概地表述一下<br />Linux&nbsp;Kernel&nbsp;Threads&nbsp;in&nbsp;Device&nbsp;Drivers<br />Purpose<br />This&nbsp;examples&nbsp;shows&nbsp;how&nbsp;to&nbsp;create&nbsp;and&nbsp;stop&nbsp;a&nbsp;kernel&nbsp;thread.<br />The&nbsp;driver&nbsp;is&nbsp;implemented&nbsp;as&nbsp;a&nbsp;loadable&nbsp;module.&nbsp;In&nbsp;the&nbsp;init_module()&nbsp;routine&nbsp;five&nbsp;kernel&nbsp;threads&nbsp;are&nbsp;created.&nbsp;This&nbsp;kernel&nbsp;threads&nbsp;sleep&nbsp;one&nbsp;second,&nbsp;wake&nbsp;up,&nbsp;print&nbsp;a&nbsp;message&nbsp;and&nbsp;fall&nbsp;asleep&nbsp;again.&nbsp;On&nbsp;unload&nbsp;of&nbsp;the&nbsp;module&nbsp;(cleanup_module),&nbsp;the&nbsp;kernel&nbsp;threads&nbsp;are&nbsp;killed.<br />The&nbsp;example&nbsp;has&nbsp;been&nbsp;tested&nbsp;with&nbsp;Linux&nbsp;kernel&nbsp;2.4.2&nbsp;on&nbsp;Intel&nbsp;(uni&nbsp;processor&nbsp;only)&nbsp;and&nbsp;Alpha&nbsp;platform&nbsp;(COMPAQ&nbsp;Personal&nbsp;Workstation&nbsp;500au&nbsp;(uni&nbsp;processor),&nbsp;DS20&nbsp;and&nbsp;ES40&nbsp;(SMP).<br />A&nbsp;version&nbsp;for&nbsp;the&nbsp;2.2&nbsp;kernel&nbsp;can&nbsp;be&nbsp;found&nbsp;here.&nbsp;Note:&nbsp;depending&nbsp;on&nbsp;the&nbsp;context&nbsp;of&nbsp;the&nbsp;creator&nbsp;of&nbsp;the&nbsp;threads&nbsp;the&nbsp;new&nbsp;threads&nbsp;may&nbsp;inherit&nbsp;properties&nbsp;from&nbsp;the&nbsp;parent&nbsp;you&nbsp;do&nbsp;not&nbsp;want&nbsp;to&nbsp;have.&nbsp;The&nbsp;new&nbsp;version&nbsp;avoids&nbsp;this&nbsp;by&nbsp;having&nbsp;keventd&nbsp;create&nbsp;the&nbsp;threads.&nbsp;The&nbsp;2.2.&nbsp;kernel&nbsp;do&nbsp;not&nbsp;have&nbsp;a&nbsp;keventd,&nbsp;so&nbsp;this&nbsp;approach&nbsp;is&nbsp;not&nbsp;implementable&nbsp;there.&nbsp;<br /><br />Functions&nbsp;in&nbsp;example<br />start_kthread:&nbsp;creates&nbsp;a&nbsp;new&nbsp;kernel&nbsp;thread.&nbsp;Can&nbsp;be&nbsp;called&nbsp;from&nbsp;any&nbsp;process&nbsp;context&nbsp;but&nbsp;not&nbsp;from&nbsp;interrupt.&nbsp;The&nbsp;functions&nbsp;blocks&nbsp;until&nbsp;the&nbsp;thread&nbsp;started.&nbsp;<br />stop_kthread:&nbsp;stop&nbsp;the&nbsp;thread.&nbsp;Can&nbsp;be&nbsp;called&nbsp;from&nbsp;any&nbsp;process&nbsp;context&nbsp;but&nbsp;the&nbsp;thread&nbsp;to&nbsp;be&nbsp;terminated.&nbsp;Cannot&nbsp;be&nbsp;called&nbsp;from&nbsp;interrupt&nbsp;context.&nbsp;The&nbsp;function&nbsp;blocks&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminated.&nbsp;<br />init_kthread:&nbsp;sets&nbsp;the&nbsp;environment&nbsp;of&nbsp;the&nbsp;new&nbsp;threads.&nbsp;Is&nbsp;to&nbsp;be&nbsp;called&nbsp;out&nbsp;of&nbsp;the&nbsp;created&nbsp;thread.&nbsp;<br />exit_kthread:&nbsp;needs&nbsp;to&nbsp;be&nbsp;called&nbsp;by&nbsp;the&nbsp;thread&nbsp;to&nbsp;be&nbsp;terminated&nbsp;on&nbsp;exit&nbsp;<br />Creation&nbsp;of&nbsp;new&nbsp;Thread<br />A&nbsp;new&nbsp;thread&nbsp;is&nbsp;created&nbsp;with&nbsp;kernel_thread().&nbsp;The&nbsp;thread&nbsp;inherits&nbsp;properties&nbsp;from&nbsp;its&nbsp;parents.&nbsp;To&nbsp;make&nbsp;sure&nbsp;that&nbsp;we&nbsp;do&nbsp;not&nbsp;get&nbsp;any&nbsp;weired&nbsp;properties,&nbsp;we&nbsp;let&nbsp;keventd&nbsp;create&nbsp;the&nbsp;new&nbsp;thread.<br />The&nbsp;new&nbsp;thread&nbsp;is&nbsp;created&nbsp;with&nbsp;start_kthread().&nbsp;It&nbsp;uses&nbsp;a&nbsp;semaphore&nbsp;to&nbsp;block&nbsp;until&nbsp;the&nbsp;new&nbsp;thread&nbsp;is&nbsp;running.&nbsp;A&nbsp;down()&nbsp;blocks&nbsp;the&nbsp;start_kthread()&nbsp;routine&nbsp;until&nbsp;the&nbsp;corresponding&nbsp;up()&nbsp;call&nbsp;in&nbsp;init_kthread()&nbsp;is&nbsp;executed.&nbsp;<br />The&nbsp;new&nbsp;thread&nbsp;must&nbsp;call&nbsp;init_kthread()&nbsp;in&nbsp;order&nbsp;to&nbsp;let&nbsp;the&nbsp;creator&nbsp;continue.&nbsp;<br />Stop&nbsp;of&nbsp;new&nbsp;Thread<br />stop_kthread()&nbsp;sets&nbsp;a&nbsp;flag&nbsp;that&nbsp;the&nbsp;thread&nbsp;uses&nbsp;to&nbsp;determine&nbsp;whether&nbsp;do&nbsp;die&nbsp;or&nbsp;not&nbsp;and&nbsp;sends&nbsp;a&nbsp;SIGKILL&nbsp;to&nbsp;the&nbsp;thread.&nbsp;This&nbsp;signal&nbsp;causes&nbsp;the&nbsp;thread&nbsp;to&nbsp;be&nbsp;woken&nbsp;up.&nbsp;On&nbsp;wakeup&nbsp;it&nbsp;will&nbsp;check&nbsp;for&nbsp;the&nbsp;flag&nbsp;and&nbsp;then&nbsp;terminate&nbsp;itself&nbsp;by&nbsp;calling&nbsp;exit_kthread&nbsp;and&nbsp;returning&nbsp;from&nbsp;the&nbsp;thread&nbsp;function.&nbsp;With&nbsp;a&nbsp;semaphore&nbsp;the&nbsp;stop_kthread()&nbsp;function&nbsp;blocks&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminated.&nbsp;<br />Initialization&nbsp;of&nbsp;new&nbsp;Thread<br />Within&nbsp;the&nbsp;new&nbsp;created&nbsp;thread,&nbsp;init_kthread()&nbsp;needs&nbsp;to&nbsp;be&nbsp;called.&nbsp;This&nbsp;function&nbsp;sets&nbsp;a&nbsp;signal&nbsp;mask,&nbsp;initialises&nbsp;a&nbsp;wait&nbsp;queue,&nbsp;the&nbsp;termination&nbsp;flag&nbsp;and&nbsp;sets&nbsp;a&nbsp;new&nbsp;name&nbsp;for&nbsp;the&nbsp;thread.&nbsp;With&nbsp;a&nbsp;up()&nbsp;call&nbsp;it&nbsp;notifies&nbsp;the&nbsp;creator&nbsp;that&nbsp;the&nbsp;setup&nbsp;is&nbsp;done.&nbsp;<br />Exit&nbsp;of&nbsp;new&nbsp;Thread<br />When&nbsp;the&nbsp;thread&nbsp;receives&nbsp;the&nbsp;notification&nbsp;to&nbsp;terminate&nbsp;itself,&nbsp;is&nbsp;calls&nbsp;the&nbsp;exit_kthread()&nbsp;function.&nbsp;It&nbsp;notifies&nbsp;the&nbsp;stop_kthread()&nbsp;function&nbsp;that&nbsp;it&nbsp;terminated&nbsp;with&nbsp;an&nbsp;up()&nbsp;call.&nbsp;<br />The&nbsp;new&nbsp;Thread&nbsp;itself<br />The&nbsp;new&nbsp;thread&nbsp;is&nbsp;implemented&nbsp;in&nbsp;the&nbsp;example_thread()&nbsp;function.&nbsp;It&nbsp;runs&nbsp;an&nbsp;endless&nbsp;loop&nbsp;(for(;;)).&nbsp;In&nbsp;the&nbsp;loop&nbsp;it&nbsp;falls&nbsp;asleep&nbsp;with&nbsp;the&nbsp;interruptible_sleep_on_timeout()&nbsp;function.&nbsp;It&nbsp;comes&nbsp;out&nbsp;of&nbsp;this&nbsp;function&nbsp;either&nbsp;when&nbsp;the&nbsp;timeout&nbsp;expires&nbsp;or&nbsp;when&nbsp;a&nbsp;signal&nbsp;got&nbsp;caught.<br />The&nbsp;'work'&nbsp;in&nbsp;the&nbsp;thread&nbsp;is&nbsp;to&nbsp;print&nbsp;out&nbsp;a&nbsp;message&nbsp;with&nbsp;printk.&nbsp;<br />Kernel&nbsp;Versions<br />The&nbsp;example&nbsp;has&nbsp;been&nbsp;tested&nbsp;on&nbsp;2.4.2.&nbsp;<br />Example&nbsp;Device&nbsp;Driver&nbsp;Code<br />The&nbsp;example&nbsp;consists&nbsp;of&nbsp;four&nbsp;files:&nbsp;kthread.h,&nbsp;kthread.c,&nbsp;thread_drv.c&nbsp;and&nbsp;a&nbsp;Makefile&nbsp;<br />kthread.h<br />#ifndef&nbsp;_KTHREAD_H<br />#define&nbsp;_KTHREAD_H<br />#include&nbsp;<br />#include&nbsp;<br /><br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br /><br />#include&nbsp;<br />#include&nbsp;<br /><br />/*&nbsp;a&nbsp;structure&nbsp;to&nbsp;store&nbsp;all&nbsp;information&nbsp;we&nbsp;need<br />&nbsp;&nbsp;&nbsp;for&nbsp;our&nbsp;thread&nbsp;*/<br />typedef&nbsp;struct&nbsp;kthread_struct<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;private&nbsp;data&nbsp;*/<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Linux&nbsp;task&nbsp;structure&nbsp;of&nbsp;thread&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;task_struct&nbsp;*thread;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Task&nbsp;queue&nbsp;need&nbsp;to&nbsp;launch&nbsp;thread&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;tq_struct&nbsp;tq;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;function&nbsp;to&nbsp;be&nbsp;started&nbsp;as&nbsp;thread&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;(*function)&nbsp;(struct&nbsp;kthread_struct&nbsp;*kthread);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;semaphore&nbsp;needed&nbsp;on&nbsp;start&nbsp;and&nbsp;creation&nbsp;of&nbsp;thread.&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;semaphore&nbsp;startstop_sem;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;public&nbsp;data&nbsp;*/<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;queue&nbsp;thread&nbsp;is&nbsp;waiting&nbsp;on.&nbsp;Gets&nbsp;initialized&nbsp;by<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init_kthread,&nbsp;can&nbsp;be&nbsp;used&nbsp;by&nbsp;thread&nbsp;itself.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait_queue_head_t&nbsp;queue;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;flag&nbsp;to&nbsp;tell&nbsp;thread&nbsp;whether&nbsp;to&nbsp;die&nbsp;or&nbsp;not.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;When&nbsp;the&nbsp;thread&nbsp;receives&nbsp;a&nbsp;signal,&nbsp;it&nbsp;must&nbsp;check<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;value&nbsp;of&nbsp;terminate&nbsp;and&nbsp;call&nbsp;exit_kthread&nbsp;and&nbsp;terminate<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;set.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;terminate;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;additional&nbsp;data&nbsp;to&nbsp;pass&nbsp;to&nbsp;kernel&nbsp;thread&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;*arg;<br />}&nbsp;kthread_t;<br /><br />/*&nbsp;prototypes&nbsp;*/<br /><br />/*&nbsp;start&nbsp;new&nbsp;kthread&nbsp;(called&nbsp;by&nbsp;creator)&nbsp;*/<br />void&nbsp;start_kthread(void&nbsp;(*func)(kthread_t&nbsp;*),&nbsp;kthread_t&nbsp;*kthread);<br /><br />/*&nbsp;stop&nbsp;a&nbsp;running&nbsp;thread&nbsp;(called&nbsp;by&nbsp;'killer')&nbsp;*/<br />void&nbsp;stop_kthread(kthread_t&nbsp;*kthread);<br /><br />/*&nbsp;setup&nbsp;thread&nbsp;environment&nbsp;(called&nbsp;by&nbsp;new&nbsp;thread)&nbsp;*/<br />void&nbsp;init_kthread(kthread_t&nbsp;*kthread,&nbsp;char&nbsp;*name);<br /><br />/*&nbsp;cleanup&nbsp;thread&nbsp;environment&nbsp;(called&nbsp;by&nbsp;thread&nbsp;upon&nbsp;receiving&nbsp;termination&nbsp;signal)&nbsp;*/<br />void&nbsp;exit_kthread(kthread_t&nbsp;*kthread);<br /><br />#endif<br /><br />kthread.c<br />#include&nbsp;<br />#include&nbsp;<br /><br />#if&nbsp;defined(MODVERSIONS)<br />#include&nbsp;<br />#endif<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br /><br />#include&nbsp;<br />#include&nbsp;<br /><br />#include&nbsp;'kthread.h'<br /><br />/*&nbsp;private&nbsp;functions&nbsp;*/<br />static&nbsp;void&nbsp;kthread_launcher(void&nbsp;*data)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread_t&nbsp;*kthread&nbsp;=&nbsp;data;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kernel_thread((int&nbsp;(*)(void&nbsp;*))kthread-&gtfunction,&nbsp;(void&nbsp;*)kthread,&nbsp;0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />}<br /><br />/*&nbsp;public&nbsp;functions&nbsp;*/<br /><br />/*&nbsp;create&nbsp;a&nbsp;new&nbsp;kernel&nbsp;thread.&nbsp;Called&nbsp;by&nbsp;the&nbsp;creator.&nbsp;*/<br />void&nbsp;start_kthread(void&nbsp;(*func)(kthread_t&nbsp;*),&nbsp;kthread_t&nbsp;*kthread)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;initialize&nbsp;the&nbsp;semaphore:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;we&nbsp;start&nbsp;with&nbsp;the&nbsp;semaphore&nbsp;locked.&nbsp;The&nbsp;new&nbsp;kernel<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;will&nbsp;setup&nbsp;its&nbsp;stuff&nbsp;and&nbsp;unlock&nbsp;it.&nbsp;This<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;control&nbsp;flow&nbsp;(the&nbsp;one&nbsp;that&nbsp;creates&nbsp;the&nbsp;thread)&nbsp;blocks<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in&nbsp;the&nbsp;down&nbsp;operation&nbsp;below&nbsp;until&nbsp;the&nbsp;thread&nbsp;has&nbsp;reached<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;up()&nbsp;operation.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init_MUTEX_LOCKED(&kthread-&gtstartstop_sem);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;store&nbsp;the&nbsp;function&nbsp;to&nbsp;be&nbsp;executed&nbsp;in&nbsp;the&nbsp;data&nbsp;passed&nbsp;to<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;launcher&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread-&gtfunction=func;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;create&nbsp;the&nbsp;new&nbsp;thread&nbsp;my&nbsp;running&nbsp;a&nbsp;task&nbsp;through&nbsp;keventd&nbsp;*/<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;initialize&nbsp;the&nbsp;task&nbsp;queue&nbsp;structure&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread-&gttq.sync&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INIT_LIST_HEAD(&kthread-&gttq.list);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread-&gttq.routine&nbsp;=&nbsp;&nbsp;kthread_launcher;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread-&gttq.data&nbsp;=&nbsp;kthread;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;and&nbsp;schedule&nbsp;it&nbsp;for&nbsp;execution&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;schedule_task(&kthread-&gttq);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;wait&nbsp;till&nbsp;it&nbsp;has&nbsp;reached&nbsp;the&nbsp;setup_thread&nbsp;routine&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;down(&kthread-&gtstartstop_sem);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />}<br /><br />/*&nbsp;stop&nbsp;a&nbsp;kernel&nbsp;thread.&nbsp;Called&nbsp;by&nbsp;the&nbsp;removing&nbsp;instance&nbsp;*/<br />void&nbsp;stop_kthread(kthread_t&nbsp;*kthread)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(kthread-&gtthread&nbsp;==&nbsp;NULL)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk('stop_kthread:&nbsp;killing&nbsp;non&nbsp;existing&nbsp;thread!\n');<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;this&nbsp;function&nbsp;needs&nbsp;to&nbsp;be&nbsp;protected&nbsp;with&nbsp;the&nbsp;big<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kernel&nbsp;lock&nbsp;(lock_kernel()).&nbsp;The&nbsp;lock&nbsp;must&nbsp;be<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;grabbed&nbsp;before&nbsp;changing&nbsp;the&nbsp;terminate<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flag&nbsp;and&nbsp;released&nbsp;after&nbsp;the&nbsp;down()&nbsp;call.&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock_kernel();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;initialize&nbsp;the&nbsp;semaphore.&nbsp;We&nbsp;lock&nbsp;it&nbsp;here,&nbsp;the<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leave_thread&nbsp;call&nbsp;of&nbsp;the&nbsp;thread&nbsp;to&nbsp;be&nbsp;terminated<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;will&nbsp;unlock&nbsp;it.&nbsp;As&nbsp;soon&nbsp;as&nbsp;we&nbsp;see&nbsp;the&nbsp;semaphore<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlocked,&nbsp;we&nbsp;know&nbsp;that&nbsp;the&nbsp;thread&nbsp;has&nbsp;exited.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init_MUTEX_LOCKED(&kthread-&gtstartstop_sem);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;We&nbsp;need&nbsp;to&nbsp;do&nbsp;a&nbsp;memory&nbsp;barrier&nbsp;here&nbsp;to&nbsp;be&nbsp;sure&nbsp;that<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;flags&nbsp;are&nbsp;visible&nbsp;on&nbsp;all&nbsp;CPUs.&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mb();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;set&nbsp;flag&nbsp;to&nbsp;request&nbsp;thread&nbsp;termination&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread-&gtterminate&nbsp;=&nbsp;1;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;We&nbsp;need&nbsp;to&nbsp;do&nbsp;a&nbsp;memory&nbsp;barrier&nbsp;here&nbsp;to&nbsp;be&nbsp;sure&nbsp;that<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;flags&nbsp;are&nbsp;visible&nbsp;on&nbsp;all&nbsp;CPUs.&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mb();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kill_proc(kthread-&gtthread-&gtpid,&nbsp;SIGKILL,&nbsp;1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;block&nbsp;till&nbsp;thread&nbsp;terminated&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;down(&kthread-&gtstartstop_sem);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;release&nbsp;the&nbsp;big&nbsp;kernel&nbsp;lock&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlock_kernel();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;now&nbsp;we&nbsp;are&nbsp;sure&nbsp;the&nbsp;thread&nbsp;is&nbsp;in&nbsp;zombie&nbsp;state.&nbsp;We<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;notify&nbsp;keventd&nbsp;to&nbsp;clean&nbsp;the&nbsp;process&nbsp;up.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kill_proc(2,&nbsp;SIGCHLD,&nbsp;1);<br /><br />}<br /><br />/*&nbsp;initialize&nbsp;new&nbsp;created&nbsp;thread.&nbsp;Called&nbsp;by&nbsp;the&nbsp;new&nbsp;thread.&nbsp;*/<br />void&nbsp;init_kthread(kthread_t&nbsp;*kthread,&nbsp;char&nbsp;*name)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;lock&nbsp;the&nbsp;kernel.&nbsp;A&nbsp;new&nbsp;kernel&nbsp;thread&nbsp;starts&nbsp;without<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;big&nbsp;kernel&nbsp;lock,&nbsp;regardless&nbsp;of&nbsp;the&nbsp;lock&nbsp;state<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;the&nbsp;creator&nbsp;(the&nbsp;lock&nbsp;level&nbsp;is&nbsp;*not*&nbsp;inheritated)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock_kernel();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;fill&nbsp;in&nbsp;thread&nbsp;structure&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread-&gtthread&nbsp;=&nbsp;current;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;set&nbsp;signal&nbsp;mask&nbsp;to&nbsp;what&nbsp;we&nbsp;want&nbsp;to&nbsp;respond&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;siginitsetinv(¤t-&gtblocked,&nbsp;sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;initialise&nbsp;wait&nbsp;queue&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init_waitqueue_head(&kthread-&gtqueue);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;initialise&nbsp;termination&nbsp;flag&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread-&gtterminate&nbsp;=&nbsp;0;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;set&nbsp;name&nbsp;of&nbsp;this&nbsp;process&nbsp;(max&nbsp;15&nbsp;chars&nbsp;+&nbsp;0&nbsp;!)&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sprintf(current-&gtcomm,&nbsp;name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;let&nbsp;others&nbsp;run&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlock_kernel();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;tell&nbsp;the&nbsp;creator&nbsp;that&nbsp;we&nbsp;are&nbsp;ready&nbsp;and&nbsp;let&nbsp;him&nbsp;continue&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;up(&kthread-&gtstartstop_sem);<br /><br />}<br /><br />/*&nbsp;cleanup&nbsp;of&nbsp;thread.&nbsp;Called&nbsp;by&nbsp;the&nbsp;exiting&nbsp;thread.&nbsp;*/<br />void&nbsp;exit_kthread(kthread_t&nbsp;*kthread)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;we&nbsp;are&nbsp;terminating&nbsp;*/<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;lock&nbsp;the&nbsp;kernel,&nbsp;the&nbsp;exit&nbsp;will&nbsp;unlock&nbsp;it&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock_kernel();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread-&gtthread&nbsp;=&nbsp;NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mb();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;notify&nbsp;the&nbsp;stop_kthread()&nbsp;routine&nbsp;that&nbsp;we&nbsp;are&nbsp;terminating.&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;up(&kthread-&gtstartstop_sem);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;the&nbsp;kernel_thread&nbsp;that&nbsp;called&nbsp;clone()&nbsp;does&nbsp;a&nbsp;do_exit&nbsp;here.&nbsp;*/<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;there&nbsp;is&nbsp;no&nbsp;race&nbsp;here&nbsp;between&nbsp;execution&nbsp;of&nbsp;the&nbsp;'killer'&nbsp;and&nbsp;real&nbsp;termination<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;the&nbsp;thread&nbsp;(race&nbsp;window&nbsp;between&nbsp;up&nbsp;and&nbsp;do_exit),&nbsp;since&nbsp;both&nbsp;the<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;and&nbsp;the&nbsp;'killer'&nbsp;function&nbsp;are&nbsp;running&nbsp;with&nbsp;the&nbsp;kernel&nbsp;lock&nbsp;held.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;kernel&nbsp;lock&nbsp;will&nbsp;be&nbsp;freed&nbsp;after&nbsp;the&nbsp;thread&nbsp;exited,&nbsp;so&nbsp;the&nbsp;code<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is&nbsp;really&nbsp;not&nbsp;executed&nbsp;anymore&nbsp;as&nbsp;soon&nbsp;as&nbsp;the&nbsp;unload&nbsp;functions&nbsp;gets<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;kernel&nbsp;lock&nbsp;back.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;init&nbsp;process&nbsp;may&nbsp;not&nbsp;have&nbsp;made&nbsp;the&nbsp;cleanup&nbsp;of&nbsp;the&nbsp;process&nbsp;here,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;but&nbsp;the&nbsp;cleanup&nbsp;can&nbsp;be&nbsp;done&nbsp;safely&nbsp;with&nbsp;the&nbsp;module&nbsp;unloaded.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br /><br />}<br /><br />thread_drv.c<br />#include&nbsp;<br />#include&nbsp;<br /><br />#include&nbsp;<br />#if&nbsp;defined(MODVERSIONS)<br />#include&nbsp;<br />#endif<br /><br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br /><br />#include&nbsp;'kthread.h'<br /><br />#define&nbsp;NTHREADS&nbsp;5<br /><br />/*&nbsp;the&nbsp;variable&nbsp;that&nbsp;contains&nbsp;the&nbsp;thread&nbsp;data&nbsp;*/<br />kthread_t&nbsp;example[NTHREADS];<br /><br />/*&nbsp;prototype&nbsp;for&nbsp;the&nbsp;example&nbsp;thread&nbsp;*/<br />static&nbsp;void&nbsp;example_thread(kthread_t&nbsp;*kthread);<br /><br />/*&nbsp;load&nbsp;the&nbsp;module&nbsp;*/<br />int&nbsp;init_module(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;create&nbsp;new&nbsp;kernel&nbsp;threads&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i=0;&nbsp;i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start_kthread(example_thread,&nbsp;&example);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(0);<br />}<br /><br />/*&nbsp;remove&nbsp;the&nbsp;module&nbsp;*/<br />void&nbsp;cleanup_module(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;terminate&nbsp;the&nbsp;kernel&nbsp;threads&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i=0;&nbsp;i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stop_kthread(&example);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />}<br /><br />/*&nbsp;this&nbsp;is&nbsp;the&nbsp;thread&nbsp;function&nbsp;that&nbsp;we&nbsp;are&nbsp;executing&nbsp;*/<br />static&nbsp;void&nbsp;example_thread(kthread_t&nbsp;*kthread)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;setup&nbsp;the&nbsp;thread&nbsp;environment&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init_kthread(kthread,&nbsp;'example&nbsp;thread');<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk('hi,&nbsp;here&nbsp;is&nbsp;the&nbsp;kernel&nbsp;thread\n');<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;an&nbsp;endless&nbsp;loop&nbsp;in&nbsp;which&nbsp;we&nbsp;are&nbsp;doing&nbsp;our&nbsp;work&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(;;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;fall&nbsp;asleep&nbsp;for&nbsp;one&nbsp;second&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interruptible_sleep_on_timeout(&kthread-&gtqueue,&nbsp;HZ);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;We&nbsp;need&nbsp;to&nbsp;do&nbsp;a&nbsp;memory&nbsp;barrier&nbsp;here&nbsp;to&nbsp;be&nbsp;sure&nbsp;that<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;flags&nbsp;are&nbsp;visible&nbsp;on&nbsp;all&nbsp;CPUs.&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mb();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;here&nbsp;we&nbsp;are&nbsp;back&nbsp;from&nbsp;sleep,&nbsp;either&nbsp;due&nbsp;to&nbsp;the&nbsp;timeout<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(one&nbsp;second),&nbsp;or&nbsp;because&nbsp;we&nbsp;caught&nbsp;a&nbsp;signal.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(kthread-&gtterminate)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;we&nbsp;received&nbsp;a&nbsp;request&nbsp;to&nbsp;terminate&nbsp;ourself&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;this&nbsp;is&nbsp;normal&nbsp;work&nbsp;to&nbsp;do&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk('example&nbsp;thread:&nbsp;thread&nbsp;woke&nbsp;up\n');<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;here&nbsp;we&nbsp;go&nbsp;only&nbsp;in&nbsp;case&nbsp;of&nbsp;termination&nbsp;of&nbsp;the&nbsp;thread&nbsp;*/<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;cleanup&nbsp;the&nbsp;thread,&nbsp;leave&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit_kthread(kthread);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;returning&nbsp;from&nbsp;the&nbsp;thread&nbsp;here&nbsp;calls&nbsp;the&nbsp;exit&nbsp;functions&nbsp;*/<br />}<br /><br />Makefile<br />#&nbsp;set&nbsp;to&nbsp;your&nbsp;kernel&nbsp;tree<br />KERNEL&nbsp;&nbsp;=&nbsp;/usr/src/linux<br /><br />#&nbsp;get&nbsp;the&nbsp;Linux&nbsp;architecture.&nbsp;Needed&nbsp;to&nbsp;find&nbsp;proper&nbsp;include&nbsp;file&nbsp;for&nbsp;CFLAGS<br />ARCH=$(shell&nbsp;uname&nbsp;-m&nbsp;|&nbsp;sed&nbsp;-e&nbsp;s/i.86/i386/&nbsp;-e&nbsp;s/sun4u/sparc64/&nbsp;-e&nbsp;s/arm.*/arm/&nbsp;-e&nbsp;s/sa110/arm/)<br />#&nbsp;set&nbsp;default&nbsp;flags&nbsp;to&nbsp;compile&nbsp;module<br />CFLAGS&nbsp;=&nbsp;-D__KERNEL__&nbsp;-DMODULE&nbsp;-I$(KERNEL)/include<br />CFLAGS+=&nbsp;-Wall&nbsp;-Wstrict-prototypes&nbsp;-O2&nbsp;-fomit-frame-pointer&nbsp;-fno-strict-aliasing<br /><br />all:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread_mod.o<br /><br />#&nbsp;get&nbsp;configuration&nbsp;of&nbsp;kernel<br />include&nbsp;$(KERNEL)/.config<br />#&nbsp;modify&nbsp;CFLAGS&nbsp;with&nbsp;architecture&nbsp;specific&nbsp;flags<br />include&nbsp;$(KERNEL)/arch/${ARCH}/Makefile<br /><br />#&nbsp;enable&nbsp;the&nbsp;module&nbsp;versions,&nbsp;if&nbsp;configured&nbsp;in&nbsp;kernel&nbsp;source&nbsp;tree<br />ifdef&nbsp;CONFIG_MODVERSIONS<br />CFLAGS+=&nbsp;-DMODVERSIONS&nbsp;-include&nbsp;$(KERNEL)/include/linux/modversions.h<br />endif<br />#&nbsp;enable&nbsp;SMP,&nbsp;if&nbsp;configured&nbsp;in&nbsp;kernel&nbsp;source&nbsp;tree<br />ifdef&nbsp;CONFIG_SMP<br />CFLAGS+=&nbsp;-D__SMP__<br />endif<br /><br />#&nbsp;note:&nbsp;we&nbsp;are&nbsp;compiling&nbsp;the&nbsp;driver&nbsp;object&nbsp;file&nbsp;and&nbsp;then&nbsp;linking<br />#&nbsp;we&nbsp;link&nbsp;it&nbsp;into&nbsp;the&nbsp;module.&nbsp;With&nbsp;just&nbsp;one&nbsp;object&nbsp;file&nbsp;as&nbsp;in<br />#&nbsp;this&nbsp;example&nbsp;this&nbsp;is&nbsp;not&nbsp;needed.&nbsp;We&nbsp;can&nbsp;just&nbsp;load&nbsp;the&nbsp;object<br />#&nbsp;file&nbsp;produced&nbsp;by&nbsp;gcc&nbsp;<br />#&nbsp;link&nbsp;the&nbsp;thread&nbsp;driver&nbsp;module<br />thread_mod.o:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread_drv.o&nbsp;kthread.o<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ld&nbsp;-r&nbsp;-o&nbsp;thread_mod.o&nbsp;thread_drv.o&nbsp;kthread.o<br />#&nbsp;compile&nbsp;the&nbsp;kthread&nbsp;object&nbsp;file<br />kthread.o:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kthread.c&nbsp;kthread.h<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gcc&nbsp;$(CFLAGS)&nbsp;-c&nbsp;kthread.c<br />#&nbsp;compile&nbsp;the&nbsp;thread&nbsp;driver<br />thread_drv.o:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread_drv.c&nbsp;kthread.h<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gcc&nbsp;$(CFLAGS)&nbsp;-c&nbsp;thread_drv.c<br /><br />clean:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;-f&nbsp;*.o<br /><br />Bugs<br />The&nbsp;code&nbsp;assumes&nbsp;that&nbsp;keventd&nbsp;is&nbsp;running&nbsp;with&nbsp;PID&nbsp;2.&nbsp;<br />Comments,&nbsp;Corrections<br />Please&nbsp;send&nbsp;comments,&nbsp;corrections&nbsp;etc.&nbsp;to&nbsp;the&nbsp;address&nbsp;below.<br />
postcode 发表于 2009-7-8 13:28 | 显示全部楼层

好帖

  
tmake 发表于 2009-7-9 13:01 | 显示全部楼层

线程和 进程,能搞明白吗?

  
chun1chun 发表于 2009-7-18 13:30 | 显示全部楼层

很详细的介绍

  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

125

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

25

主题

125

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部