6

我有一个创建/dev/mything条目的 Linux 字符设备驱动程序,然后是一个打开设备并使用它的 C++/Qt 程序。如果该程序正确退出exit(),则设备将关闭并且驱动程序会自行正确重置。但是如果程序异常退出,通过segfault之类SIGINT的,设备没有正确关闭。

我目前的解决方法是在驱动程序卡在“打开”状态时重新加载驱动程序。

驱动程序中的这一行试图防止多个程序同时使用该设备:

int mything_open( struct inode* inode, struct file* filp ) {
    ...
    if ( port->rings[bufcount].virt_addr ) return -EBUSY;
    ...
}

然后清理它:

int mything_release( struct inode* inode, struct file* filp ) {
    ...
    port->rings[bufcount].virt_addr = NULL;
    ...
}

我认为exit()是导致mything_release被调用,但SIGINT不是。如何使驱动程序对这种情况更加稳健?

编辑:

以下是我实施的操作。也许我错过了什么?

static struct file_operations fatpipe_fops = {
    .owner =    THIS_MODULE,
    .open =     mything_open,
    .release =  mything_release,
    .read =     mything_read,
    .write =    mything_write,
    .ioctl =    mything_ioctl
};
4

2 回答 2

2

不需要这个测试;问题不是程序异常终止(从您的驱动程序的角度来看,这close与设备上的正常情况完全一样),而是您设备的状态保持问题。换句话说,如果您插入close(dev_fd)甚至是exit(0)在程序崩溃的确切位置,您也会遇到同样的问题。

您应该找出驱动程序行为的哪一部分导致它保持忙碌状态并修复它。

于 2012-06-25T16:55:12.293 回答
1

问题归结为这一行mything_release,放入等待一些内存写入完成:

if (wait_event_interruptible_timeout(port->inq, false, 10)) return -ERESTARTSYS;

在正常程序退出的情况下,这将旋转 10 个 jiffies 并继续。但是由于 SIGINT 异常退出或其他原因,我认为可中断超时被中断并返回-ERESTARTSYS,导致我的 if 返回相同。

对我有用的是摆脱if并等待:

wait_event_interruptible_timeout(port->inq, false, 10);

多年前的这个补丁让我相信ERESTARTSYS从 close/_release 函数返回不是一个好主意:http ://us.generation-nt.com/answer/patch-fix-wrong-error-code-interrupted-close-系统调用-帮助-181191441.html

于 2012-06-25T18:01:25.930 回答