编辑:我认为我解决了这个问题。明天我上班时会添加我的答案/解决方案。
我正在为Linux内核3.16.x开发一个内核模块。我的模块应该接收和发送以太网帧,因此我创建了两个线程,一个用于接收部分,另一个用于传输部分。它已经工作得很好了。
当我尝试关闭该模块的设备文件并卸载它时,出现了问题。确切地说,当我尝试杀死我的��程时,机器(我在使用Ubuntu 14.04的虚拟机进行测试)就会在没有任何输出之前冻结。然而,当我从代码中删除“线程杀死部分”时,它就不再冻结。这就是为什么我相当确定问题源于我处理kthreads的方式。
下面是我的两个线程:
TX THREAD: tx_sem信号量在代码的另一部分被up'ed。
static int tx_task(void *par)
{
device->tx_task_running = 1;
allow_signal(SIGTERM);
while (!signal_pending(current) && device->tx_task_running) {
/* wait until there is something to send */
down_interruptible(&device->tx_sem);
if (signal_pending(current)) {
PRINTD("device_TX_task(): Received kill signal\n");
break;
}
/* check if device is still initialized before continuing*/
if (!device->init_flag) {
break;
}
}
device->tx_task_running = 0;
return DEVICE_RET_OK;
}
RX THREAD
static int device_rx_task(void *par)
{
device->rx_task_running = 1;
/* task loop */
allow_signal(SIGTERM);
while (!signal_pending(current) && device->rx_task_running) {
rxlen = kernel_recvmsg(device->sock, &msg,
(struct kvec *)&iov, 1, DEVICE_PAY_SIZE, 0);
if (signal_pending(current)) {
PRINTD("device_rx_task(): Received kill signal\n");
break;
}
if(rxlen < 0) {
PRINTD("device_RX_task(): Got error when receiving\n");
break;
}
/* check if device is still initialized before continuing*/
if (!device->init_flag) {
break;
}
}
device->rx_task_running = 0;
return DEVICE_RET_OK;
}
这些线程会一直运行,直到我尝试关闭设备。当关闭内核模块时,会调用此函数并导致崩溃。例如,如果我注释掉“send_sig”函数,它就不会崩溃。当我尝试手动杀死这些线程时,它也会崩溃:
int Device_DevTerm(int dev)
{
device->init_flag = 0;
send_sig(SIGTERM, device->rx_thread, 0);
send_sig(SIGTERM, device->tx_thread, 0);
device->rx_task_running = 0;
device->tx_task_running = 0;
return DEVICE_RET_OK;
}
我在谷歌和搜索引擎中花费了很长时间来寻找问题,但至今仍未成功。由于我已经为此问题投入了大量时间,所以我决定向你们寻求帮助。
我在这里做错了什么?
附言:我不认为我曾在这里发布过任何内容,我只是阅读了很多。我希望我的问题足够清晰简明。但可能并不是。