如何在通知FD关闭的linux驱动程序中实现轮询

时间:2013-12-17 22:41:49

标签: linux linux-kernel linux-device-driver polling

我正在为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

1 个答案:

答案 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()时,内核更高级别的某些内容正在取消轮询操作。我想以不同的方式解决你的问题。