2012-08-06 12 views

Odpowiedz

14

Nic - połączenie z rejestracją fd (przynajmniej dla typowych systemów plików Linux) zakończy się niepowodzeniem z EPERM.

Testowałem to przy użyciu następujący program Demo:

#include <sys/epoll.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 

int main(void) { 
    int ep = epoll_create1(0); 
    int fd = open("/tmp", O_RDONLY|O_DIRECTORY); 
    struct epoll_event evt = { 
     .events = EPOLLIN 
    }; 

    if (ep < 0 || fd < 0) { 
     printf("Error opening fds.\n"); 
     return -1; 
    } 

    if (epoll_ctl(ep, EPOLL_CTL_ADD, fd, &evt) < 0) { 
     perror("epoll_ctl"); 
     return -1; 
    } 
    return 0; 
} 

z następującym wynikiem:

[[email protected]:/tmp]$ make epoll 
cc  epoll.c -o epoll 
[[email protected]:/tmp]$ ./epoll 
epoll_ctl: Operation not permitted 

Aby dowiedzieć się, co się tu dzieje, poszedłem do źródła. I happen to know, że większość zachowania epoll jest określona przez funkcję ->poll na struct file_operations odpowiadającą plikowi docelowemu, która zależy od systemu plików, o którym mowa. I zbierane ext4 jako typowy przykład i wyglądał na fs/ext4/dir.c, które definesext4_dir_operations następująco:

const struct file_operations ext4_dir_operations = { 
    .llseek  = ext4_dir_llseek, 
    .read  = generic_read_dir, 
    .readdir = ext4_readdir, 
    .unlocked_ioctl = ext4_ioctl, 
#ifdef CONFIG_COMPAT 
    .compat_ioctl = ext4_compat_ioctl, 
#endif 
    .fsync  = ext4_sync_file, 
    .release = ext4_release_dir, 
}; 

Uwaga braku .poll definicja będzie inicjowane NULL. Tak, kołysanie z powrotem do epoll, który jest zdefiniowany w fs/eventpoll.c szukamy kontroli dla poll będącego NULL, a my znaleźć early on w definicji epoll_ctl syscall:

/* The target file descriptor must support poll */ 
error = -EPERM; 
if (!tfile->f_op || !tfile->f_op->poll) 
    goto error_tgt_fput; 

Jak wskazano nasz test, jeśli plik docelowy nie robi 't obsługa poll, próba wstawienia zakończy się niepowodzeniem z EPERM.

Jest możliwe, że inne systemy plików definiują metody na obiektach plików katalogowych, ale wątpię, żeby tak wiele robili.

+0

Czy 'dirfd (opendir ("/tmp ")) jest preferowany zamiast' open (ścieżka, O_RDONLY | O_DIRECTORY); '? Tylko pytanie o styl. Użycie 'opendir' nie magicznie sprawia, że ​​fs obsługuje ankietę. – schmichael

+0

'dirfd (opendir (" ... "))' jest bardziej przenośny, więc prawdopodobnie jest ogólnie preferowany. Jestem hackerem jądra Linuksa, więc osobiście domyślnie używam interfejsu wywołań systemowych, nawet jeśli nie jest to najbardziej odpowiednie, ponieważ wiem o tym lepiej. Oczywiście tutaj to nie ma znaczenia, ponieważ 'epoll' jest również specyficzny dla Linuksa. – nelhage