2013-12-17 5 views
2

Я реализую драйвер устройства для Linux.Как реализовать опрос в Linux-драйвере, который замечает FD закрыт

Этот драйвер реализует file_operations :: опрос и

я хочу сделать так, чтобы опрос (2) возвратит POLLHUP, если дескриптор закрывается.

Должен быть указан код клиента водителя (код пользователя).

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; 
} 

Но я не мог реализовать это поведение в своем коде драйвера.

Вызов опроса (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() никогда не будет вызван, и опрос (2) никогда не вернется.

Как правильно реализовать my_poll()?

Моя тестовая среда: ядро ​​линукс-3.10.20

ответ

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(). Я бы подумал о том, чтобы решить вашу проблему по-другому.

+0

Спасибо за ваш ответ. Я обнаружил, что close (2) быстро удаляет данный дескриптор из таблицы fd. поэтому заданный дескриптор не является регистратором, действительным, когда close (2) возвращен , и поведение опроса (2), которое никогда не возвращается, может быть правильным. Ваше предположение может быть правильным. Я пытаюсь реализовать эту проблему по-разному. – knj

Смежные вопросы