2011-07-20 107 views
5

你好,我在內核開發是新手,恐慌而rmmod的

創建一個簡單的程序:

#include <linux/module.h> 
#include <linux/init.h> 
#include <linux/sched.h> 
#include <linux/kthread.h> 

MODULE_LICENSE("Dual BSD/GPL"); 


int messager(void*); 
struct task_struct* kthrstr; 

static int start_module(void) 
{ 
    printk(KERN_INFO "Loading the messager\n"); 

    kthrstr = kthread_create(messager,NULL,"MESSAGER"); 
    wake_up_process(kthrstr); 
    return 0; 
} 

static void stop_module(void) 
{ 
    printk(KERN_INFO "Unloading the messager\n"); 
    kthread_stop(kthrstr); 
} 

int messager(void* varg) 
{ 
    daemonize("MESSAGER"); 
    allow_signal(SIGKILL); 

    while(1) 
    { 
     printk(KERN_INFO "Timeout: Hello"); 
     set_current_state(TASK_INTERRUPTIBLE); 
     schedule_timeout(10 * HZ); 
     if (signal_pending(current)) 
      break; 
    } 
    return 0; 
} 

module_init(start_module); 
module_exit(stop_module); 

模塊被正確加載和消息也出現在系統日誌預期。但是當使用rmmod卸載模塊時,它會如下所示發生混亂。請幫我鑑別爲自己做錯了什麼正在發生的事情,以及如何糾正:

[ 2207.466086] Timeout: Hello 
[ 2215.756784] Unloading the messager 
[ 2217.461846] BUG: unable to handle kernel paging request at f0ca8054 
[ 2217.462328] IP: [<f0ca8054>] 0xf0ca8054 
[ 2217.462772] *pdpt = 0000000000a76001 *pde = 000000002f8b1067 *pte = 0000000000000000 
[ 2217.463003] Oops: 0010 [#1] PREEMPT SMP 
[ 2217.463065] last sysfs file: /sys/module/ip6_tables/initstate 
[ 2217.463328] Modules linked in: fuse ip6t_LOG xt_tcpudp xt_pkttype ipt_LOG xt_limit vmsync vmblock af_packet mperf snd_pcm_oss snd_mixer_oss snd_seq_midi snd_seq_midi_event snd_seq edd ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_raw xt_NOTRACK ipt_REJECT iptable_raw iptable_filter ip6table_mangle nf_conntrack_netbios_ns nf_conntrack_ipv4 nf_defrag_ipv4 ip_tables xt_conntrack nf_conntrack ip6table_filter ip6_tables x_tables snd_ens1371 gameport snd_rawmidi snd_seq_device snd_ac97_codec ac97_bus snd_pcm sg snd_timer ppdev pcnet32 mptctl snd sr_mod soundcore vmci pcspkr cdrom parport_pc vmxnet shpchp snd_page_alloc parport i2c_piix4 vmw_balloon pci_hotplug floppy button ac container ext4 jbd2 crc16 linear dm_snapshot dm_mod fan processor thermal thermal_sys ata_generic mptspi mptscsih mptbase scsi_transport_spi [last unloaded: printmsg] 
[ 2217.463839] 
[ 2217.463957] Pid: 6684, comm: MESSAGER Not tainted 2.6.37.1-1.2-desktop #1 VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform 
[ 2217.464156] EIP: 0060:[<f0ca8054>] EFLAGS: 00010296 CPU: 0 
[ 2217.464216] EIP is at 0xf0ca8054 
[ 2217.464249] EAX: 00000000 EBX: e8678430 ECX: 00000286 EDX: 00000000 
[ 2217.464275] ESI: 00000000 EDI: f0ca8000 EBP: 00000000 ESP: eccedfb4 
[ 2217.464302] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 
[ 2217.464414] Process MESSAGER (pid: 6684, ti=eccec000 task=e8678430 task.ti=eccec000) 
[ 2217.464450] Stack: 
[ 2217.464580] f0ca80f9 00000000 ec52ff2c c0265dc4 00000000 00000000 00000001 00000101 
[ 2217.464714] eccedfd4 eccedfd4 00000000 c0265d50 ec52ff2c c02034e6 00000000 00000000 
[ 2217.464734] 00000000 00000000 00000000 
[ 2217.464787] Call Trace: 
[ 2217.465094] Inexact backtrace: 
[ 2217.465097] 
[ 2217.476943] [<c0265dc4>] ? kthread+0x74/0x80 
[ 2217.476965] [<c0265d50>] ? kthread+0x0/0x80 
[ 2217.476985] [<c02034e6>] ? kernel_thread_helper+0x6/0x10 
[ 2217.483598] Code: Bad EIP value. 
[ 2217.483786] EIP: [<f0ca8054>] 0xf0ca8054 SS:ESP 0068:eccedfb4 
[ 2217.483849] CR2: 00000000f0ca8054 
[ 2217.484325] ---[ end trace dc9382a06b455776 ]--- 

回答

3

你的模塊崩潰因爲調用daemonize()導致後來kthread_stop()呼叫而不等待返回。

此外,如上所述herekthread_stop()不發送信號給線程,而是讓kthread_should_stop()返回true。簡而言之,將您的代碼更改爲在while (!kthread_should_stop())上循環,並刪除daemonize(此處不需要和危險)和allow_signal調用。

+1

難道這隻會導致無限循環而不是哎呀? – bdonlan

+2

@bdonlan:是的,會的。看來實際的問題是'daemonize'調用,'daemonize'調用'exit_mm',它調用'mm_release',它發信號通知'vfork_done',使'kthread_stop'相信線程已經結束。這使得'kthread_stop'返回而不是等待,導致崩潰。 – Hasturkun

+2

故事的寓意是使用'kernel_thread'和'daemonize',或者使用'kthread_create' /'kthread_run'。同時做兩件事必然會傷害你。 – Hasturkun