|
自己写的一个监控用户连接的驱动,用到内核线程,在卸载驱动的时候会死锁宕机,不必现,看了堆栈信息是在内核的default_idle里面
下面是堆栈信息
Dead lock in User:
CPU: 7
EIP: 0010:[<8010904c>] Tainted: GF
EFLAGS: 00000246
eax: 00000000 ebx: 80109020 ecx: 00000007 edx: 87666000
esi: 87666000 edi: 87666000 ebp: ffffe000 esp: 87667fb0
ds: 0018 es: 0018 ss: 0018
Process swapper (pid: 0, stackpage=87667000)
Stack: 801090e2 07040800 00000000 00000000 00000000 0000000d 00000006 8011ffa0
0000000a 00000400 8029e4df 00000000 80352bc0 80352bf9 8029e265 8032950b
8029e4d0 0000000b 00000000 00000006
Call Trace: [<801090e2>] [<8011ffa0>]
Code: c3 8d 76 00 fb eb 0d 90 90 90 90 90 90 90 90 90 90 90 90 90
这是内核的堆栈信息(一小部分)
80109010 T enable_hlt
80109020 T default_idle
80109070 t poll_idle
80109090 T cpu_idle
80109100 T machine_real_restart
所以确定是宕在default_idle,看了default_idle函数用到cpu指针current,下面是内核的代码:
static void default_idle(void)
{
if (!hlt_counter) {
__cli();
if (!current->need_resched)
safe_halt();
else
__sti();
}
}
我在内核线程里也用到了指针current,请各位大侠帮忙看下我是不是哪里操作不对了导致了死锁,下面是我的内核线程和卸载关键代码,(内核是2.4版本)
static DECLARE_WAIT_QUEUE_HEAD (connauth_waitqueue);//等待队列
static DECLARE_COMPLETION(connauth_exit); //完成变量
static int del_thread(void *data)
{
static int timercnt = 0;
DECLARE_WAITQUEUE(wait, current);//初始化等待队列
sprintf(current->comm, "connauth_thd");
daemonize();
//阻塞所有线程
spin_lock_irq(¤t->sigmask_lock);
siginitsetinv(¤t->blocked, 0);
recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
add_wait_queue(&connauth_waitqueue, &wait);
for(;; )
{
//处于睡眠状态:30秒
//放弃cpu 直到被唤醒
set_current_state(TASK_INTERRUPTIBLE);
schedule();
//线程退出
if (stop_connauth_thd)
break;
//下面是线程的工作。。。
}
//从等待队列中删除
set_current_state(TASK_RUNNING);
remove_wait_queue(&connauth_waitqueue, &wait);
complete_and_exit(&connauth_exit, 0);//完成并退去,原子操作
}
//卸载驱动时,删除线程代码
static void __exit driver_cleanup(void)
{
stop_connauth_thd = 1;
//唤醒线程,以防僵死
wake_up_interruptible(&connauth_waitqueue);
wait_for_completion(&connauth_exit);//等待线程退出
//下面是卸载动作
} |
|