2017-02-16 2 views
0

커널에서 인터럽트 번호를 받으려면 netlink을 사용합니다. 사용자 공간의 응용 프로그램은 libevent을 사용하여 TCP/IP 요청을 처리하고 netlink 메시지를 처리합니다. libevent 리눅스를 지원 netlink 소켓을 지원합니까? 간단한 예를 들어 주시면 감사하겠습니다.libevent가 netlink 소켓을 지원합니까

답변

1

예, libevent는 netlink 소켓을 지원합니다.

https://github.com/libevent/libevent/blob/master/sample/hello-world.c이 있으며, netlink 소켓을 청취하기 위해 아래에서 수정되었습니다.

기본 예제는 Linux 네트워크 인터페이스 생성/삭제를 수신하며 sudo를 사용하여 필요한 권한을 얻습니다. 그것은 ip monitor link과 같은 사건을 경청합니다.

libevent를 사용하여 RAW 소켓을 수신하는 또 다른 예는 https://github.com/bodgit/libevent-natpmp/blob/master/natpmp.c입니다.

static void link_recvmsg(int fd, short event, void *arg) 
{ 
    char   buf[NLMSG_SPACE(BUF_SIZE)] = {0}; 
    socklen_t  socklen; 
    struct iovec iov = {.iov_base = buf, .iov_len = sizeof(buf)}; 
    struct sockaddr addr; 
    memset(&addr, 0, sizeof(struct sockaddr)); 

    if (!fd || -1 == fd) 
     return; 

    int status = getsockname(fd, &addr, &socklen); 
    if(-1 == status) 
     return; 

    struct msghdr mh = {.msg_name = NULL, .msg_namelen = 0, .msg_iov = &iov, .msg_iovlen = 1, 
     .msg_flags = 0, .msg_name = &addr, .msg_namelen = sizeof(struct sockaddr)}; 

    status = recvmsg(fd, &mh, 0); 
    if ((-1 == status) && ((EINTR == errno) || (EAGAIN == errno))) 
     return; 
    if(-1 == status) 
     return; 
    if ((mh.msg_flags & MSG_TRUNC) == MSG_TRUNC) 
     return; 
    if ((mh.msg_flags & MSG_CTRUNC) == MSG_CTRUNC) 
     return; 

    for (const struct nlmsghdr *h = (struct nlmsghdr *)buf; NLMSG_OK(h, status); h = NLMSG_NEXT(h, status)) { 
     switch (h->nlmsg_type) { 
      case RTM_NEWLINK: 
       fprintf(stderr, "got RTM_NEWLINK\n"); 
       break; 
      case RTM_DELLINK: 
       fprintf(stderr, "got RTM_DELLINK\n"); 
       break; 
      default: 
       fprintf(stderr, "unexpected case in swtch statement\n"); 
       break; 
     } 
    } 
} 
int main(int argc, char **argv) 
{ 
    /* some init code here */ 
    /* NETLINK socket */ 
    int status; 
    int buf_size = BUF_SIZE; 
    struct sockaddr_nl src_addr; 

    int socket_nl = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE); 
    if(-1 == socket_nl) return -1; 

    memset(&src_addr, 0, sizeof(struct sockaddr_nl)); 
    src_addr.nl_family = AF_NETLINK; 
    src_addr.nl_pid = getpid(); 
    src_addr.nl_groups |= RTNLGRP_LINK; 

    status = setsockopt(socket_nl, SOL_SOCKET, SO_RCVBUF, 
      &buf_size, sizeof(buf_size)); 
    if(-1 == status) return -1; 

    status = bind(socket_nl, (struct sockaddr *)&src_addr, sizeof(struct sockaddr_nl)); 
    if(status < 0) return -1; 

    static struct event nl_ev; 
    event_set(&nl_ev, socket_nl, EV_READ|EV_PERSIST, link_recvmsg, 
      NULL); 
    if (base) { 
     event_base_set(base, &nl_ev); 
    } 
    event_add(&nl_ev, NULL); 
    /* some other code, dispatch event and deinit */ 
} 
관련 문제