2017-12-12 1 views
0

를 제기하지 않는다. epoll (7)에 따르면 :는 epoll 이벤트는 선택, 또는 다른 epoll 파일을 폴링하기는 epoll 파일 디스크립터를 추가 할 수 있습니다 및 이벤트를 사용할 수있는 경우는 POLLIN를 반환합니다, 내 연구를 바탕으로 SIGIO

Q3 Is the epoll file descriptor itself poll/epoll/selectable? 

    A3 Yes. If an epoll file descriptor has events waiting, then it will 
     indicate as being readable. 

이것은 내 테스트에서 작동합니다. 나는이 작업을 수행 할 때, 그것은 epoll에 새로운 이벤트에 대한 SIGIO를 발생시키지 않습니다

//Epoll setup code - trySc runs perror on the string and exits if the function returns -1 
int epollFd = epoll_create1(EPOLL_CLOEXEC); 
trySc(epollFd, "epoll_create1"); 
trySc(fcntl(epollFd, F_SETOWN, getpid()), "fcntl F_SETOWN"); 
trySc(fcntl(epollFd, F_SETSIG, SIGIO), "fcntl F_SETSIG"); 
int oldFlags = fcntl(epollFd, F_GETFL, 0); 
trySc(oldFlags, "fcntl F_GETFL"); 
trySc(fcntl(epollFd, F_SETFL, oldFlags | O_ASYNC), "fcntl F_SETFL"); 

//Set up SIGIO and get a socket fd, you don't need to see this 
//All my handler does is exit - it's a definite method of knowing SIGIO was raised 

struct epoll_event event = { 
     .events = EPOLLIN | EPOLLET, 
     .data.fd = socketFd 
}; 
trySc(epoll_ctl(epollFd, EPOLL_CTL_ADD, socketFd, &event), "epoll_ctl"); 
//Then connect 
while(1){ 
     struct pollfd pfd = { 
       .fd = epollFd, 
       .events = POLLIN 
     }; 
     //This blocks until I write something to the socket. Then it enters an infinite loop. 
     printf("Returning to main(), poll = %d\n", poll(&pfd, 1, -1)); 
} 

:하지만, 지금은 이벤트가 준비가되면이 SIGIO를 올릴 수 있도록 내 epoll 파일의 FD에 O_ASYNC을 적용하려합니다. 설문 조사는 epollFd에서 이벤트가 준비되었음을 나타내지 만, 먼저 이벤트가 epollFd에 있는지 확인하고 종료하는 SIGIO를 발생시켜야합니다. 나는 소켓에 O_ASYNC를 적용 할 수 있다는 것을 알고있다. (그리고 나는 이것도 시도했다.)하지만 내 이벤트에 데이터를 포함하고 싶다. Epoll은 내가 이것을 할 수있게 해줍니다.

#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/epoll.h> 
#include <fcntl.h> 
#include <netdb.h> 
#include <poll.h> 
#include <signal.h> 
#include <errno.h> 

void handleSIGIO(int, siginfo_t *, void *); 

const struct sigaction saSIGIO = { 
    .sa_sigaction = handleSIGIO, 
    .sa_flags = SA_SIGINFO 
}; 

const struct addrinfo hints = { 
    .ai_flags = AI_PASSIVE, 
    .ai_family = AF_INET, 
    .ai_socktype = SOCK_STREAM 
}; 

void trySc(int err, const char *msg){ 
    if(err != -1) return; 
    perror(msg); 
    exit(errno); 
} 

int main(){ 
    signal(SIGPIPE, SIG_IGN); 
    trySc(sigaction(SIGIO, &saSIGIO, NULL), "sigaction"); 
    int epollFd = epoll_create1(EPOLL_CLOEXEC); 
    trySc(epollFd, "epoll_create1"); 
    trySc(fcntl(epollFd, F_SETOWN, getpid()), "fcntl F_SETOWN"); 
    trySc(fcntl(epollFd, F_SETSIG, SIGIO), "fcntl F_SETSIG"); 
    int oldFlags = fcntl(epollFd, F_GETFL, 0); 
    trySc(oldFlags, "fcntl F_GETFL"); 
    trySc(fcntl(epollFd, F_SETFL, oldFlags | O_ASYNC), "fcntl F_SETFL"); 
    int socketFd = socket(AF_INET, SOCK_STREAM, 0); 
    trySc(socketFd, "socket"); 
    struct addrinfo *servinfo; 
    trySc(getaddrinfo("127.0.0.1", "5000", &hints, &servinfo), 
     "getaddrinfo"); 
    struct epoll_event event = { 
     .events = EPOLLIN | EPOLLET, 
     .data.fd = socketFd 
    }; 
    trySc(epoll_ctl(epollFd, EPOLL_CTL_ADD, socketFd, &event), "epoll_ctl"); 
    trySc(connect(socketFd, servinfo->ai_addr, servinfo->ai_addrlen), 
     "connect"); 
    printf("Connected\n"); 
    while(1){ 
     struct pollfd pfd = { 
      .fd = epollFd, 
      .events = POLLIN 
     }; 
     printf("Returning to main(), poll = %d\n", poll(&pfd, 1, -1)); 
    } 
} 

void handleSIGIO(int sn, siginfo_t *info, void *ctx){ 
    printf("SIGIO called\n"); 
    struct epoll_event event; 
    if(epoll_wait(info->si_fd, &event, 1, 0) != 1){ 
     printf("Warning: no event available\n"); 
     return; 
    } 
    printf("Event raised for fd %d\n", event.data.fd); 
    exit(0); 
} 

편집 : this website에 따르면, 내가 뭘하려고 오전 작동합니다 : 여기

내 전체 코드입니다

Note that an epoll set descriptor can be used much like a regular file 
descriptor. That is, it can be made to generate SIGIO (or another signal) 
when input (i.e. events) is available on it; likewise it can be used with 
poll() and can even be stored inside another epoll set. 

답변

0

더 많은 연구를하고 후, 나는 그것이 불가능 발견 . O_ASYNC

open(2)

따르면 신호 기반 I/O를 사용 : 신호를 생성한다 (기본적으로 SIGIO, 그러나 이것은 fcntl을 통해 변경 될 수있다 (2))의 입력 또는 출력 이 가능하게 될 때 파일 기술자. 이 기능은 터미널, 의사 터미널, 소켓 및 (Linux 2.6부터) 파이프 및 FIFO에만 사용할 수있는 입니다. 자세한 내용은 fcntl (2)를 참조하십시오. 아래 BUGS를 참고하십시오.

저는 epoll을 SIGIO와 사용할 수 있기를 정말로 바랬습니다. 내가 할 수있는 다른 것을 찾는다.

관련 문제