카테고리 없음

epoll

sunshout 2015. 3. 26. 14:22

epoll_create


SYNOPSIS

       #include <sys/epoll.h>

       int epoll_create(int size);

       int epoll_create1(int flags);


DESCRIPTION

       epoll_create()  creates  an  epoll(7)  instance. 


epoll_ctl

SYNOPSIS

       #include <sys/epoll.h>

       int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);


DESCRIPTION
       This system call performs control operations on the epoll(7) instance referred to by the file descriptor epfd.

       EPOLL_CTL_ADD
              Register the target file descriptor fd on the epoll instance
              referred to by the file descriptor epfd and associate the
              event event with the internal file linked to fd.

       EPOLL_CTL_MOD
              Change the event event associated with the target file
              descriptor fd.

       EPOLL_CTL_DEL
              Remove (deregister) the target file descriptor fd from the
              epoll instance referred to by epfd.  The event is ignored and
              can be NULL (but see BUGS below).


epoll_wait

SYNOPSIS

       #include <sys/epoll.h>


       int epoll_wait(int epfd, struct epoll_event *events,

                      int maxevents, int timeout);

       int epoll_pwait(int epfd, struct epoll_event *events,

                      int maxevents, int timeout,

                      const sigset_t *sigmask);



#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/epoll.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>


#define EPOLL_SIZE 1024


int main(int argc, char **argv)

{

    struct sockaddr_in addr, clientaddr;

    int sfd;

    int cfd;

    socklen_t clilen;

    int flags = 1;

    int n,i;

    int readn;


    struct epoll_event ev,*events;


    int efd;

    char buf_in[256];


    events = (struct epoll_event *)malloc(sizeof(*events) * EPOLL_SIZE);


    if ( 0 > (efd = epoll_create(EPOLL_SIZE)) )

    {

        perror("epoll_create error");

        return 1;

    }


    clilen = sizeof(clientaddr);

    sfd = socket(AF_INET, SOCK_STREAM, 0);

    if ( -1 == sfd )

    {

        perror("socket error");

        close(sfd);

        return 1;

    }


    addr.sin_family = AF_INET;

    addr.sin_port = htons(atoi(argv[1]));

    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if ( -1 == bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) )

    {

        close(sfd);

        return 1;

    }


    listen(sfd, 512);


    ev.events = EPOLLIN;

    ev.data.fd = sfd;

    epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &ev);


    while(1)

    {

        n = epoll_wait(efd, events, EPOLL_SIZE, -1);

        if ( n == -1 )

        {

            perror("epoll wait error");

        }


        for ( i = 0; i < n; ++i)

        {

            //acept

            if (events[i].data.fd == sfd)

            {

                printf("Accept\n");

                cfd = accept(sfd, (struct sockaddr *)&clientaddr, &clilen);

                ev.events = EPOLLIN;

                ev.data.fd = cfd;

                epoll_ctl(efd, EPOLL_CTL_ADD, cfd, &ev);

            }


            // worker

            else

            {

                memset(buf_in, 0, 256);

                readn = read(events[i].data.fd, buf_in, 255);

                if (readn <= 0)

                {

                    epoll_ctl(efd, EPOLL_CTL_DEL, events[i].data.fd, events);

                    close(events[i].data.fd);

                    printf("Close fd\n");

                }

                else

                {

                    printf("read data %s\n", buf_in);

                }

            }

        }

    }

}



level trigger vs. edge trigger


일반적으로 level trigger 보다 edge trigger 가 성능이 좋다고 한다. 하지만 edge triggerr 로 동작할 때는 fd를 non-blocking 으로 설정하여야 한다.


참조: http://goldenretriever.tistory.com/entry/linux-epoll%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-echo-server