我正在为linux实现misc设备驱动程序。
此驱动程序实现file_operations :: poll和
我想这样做,如果描述符被关闭,poll(2)将返回POLLHUP。
随后提供了驱动程序客户端代码(userland代码)。
void ThreadA(int fd){
// initialization codes...
pfd[0].fd = fd;
pfd[0].event = POLLIN;
int r = poll(pfd, 1, -1);
if(r > 0 && pfd[0].revent & POLLHUP){
// Detect fd is closed
return; // Exit thread
}
}
void ThreadB(int fd){
// waiting some events. ex.signals
// I expect close(fd) will cause poll(2) return and ThreadA will exit.
close(fd);
return;
}
但我无法在我的驱动程序代码中实现此行为。
即使描述符已关闭,调用poll(2)也不会返回。所以threadA永远不会退出。
随后是琐碎的测试驱动程序代码。
static wait_queue_head_t q;
static int CLOSED = 0;
int my_open(struct inode *a, struct file *b){
printk(KERN_DEBUG "my_open");
return 0;
}
int my_release(struct inode *a, struct file *b){
printk(KERN_DEBUG "my_release");
CLOSED = 1;
wake_up_interruptible(&q);
// I expect this call will wake up q and recall my_poll.
// but doesn't
return 0;
}
unsigned int my_poll(struct file *a, struct poll_table_struct *b){
printk(KERN_DEBUG "my_poll");
poll_wait(file, &q, a);
if(CLOSED != 0)
return POLLHUP;
return 0;
}
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.open = &my_open,
.release = &my_release,
.poll = &my_poll
};
static struct miscdevice mydevice =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "TESTDEV",
.fops = &my_fops
};
static int __init myinit(void){
init_waitqueue_head(&q);
misc_register(&mydevice);
return 0;
}
static void __exit myexit(void){
misc_deregister(&mydevice);
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL");
我认为调用wake_up_interruptible()不会影响my_release()。
这样my_poll()永远不会被召回,而poll(2)永远不会返回。
我应该如何以正确的方式实现my_poll()?
我的测试环境: 内核是linux-3.10.20
答案 0 :(得分:2)
关闭手册页警告:
It is probably unwise to close file descriptors while they may be in use by
system calls in other threads in the same process. Since a file descriptor
may be reused, there are some obscure race conditions that may cause unintended
side effects.
我怀疑在执行close
函数实际调用之前执行release()
时,内核更高级别的某些内容正在取消轮询操作。我想以不同的方式解决你的问题。