eventfd

来源:互联网 发布:什么是软件集成测试 编辑:程序博客网 时间:2024/04/28 04:46

PS:有点明白这个eventfd了,类似于管道。


int eventfd(unsigned int initval, int flags);

eventfd函数会创建一个 事件对象 (eventfd object), 用来实现,进程(线程)  等待/通知(wait/notify) 机制内核会为这个对象维护一个64位的计数器(uint64_t)。并且使用第一个参数(initval)初始化这个计数器。调用这个函数就会返回一个新的文件描述符(event object)eventfd 可以完美取代 pipe去通知(唤醒)其他的进程(线程)

 

#define handle_error(msg) \

            do { perror(msg); exit(EXIT_FAILURE); } while (0)

 

int main(int argc, char *argv[])

{

    int evfd, epfd, j, ret;

    uint64_t u;

    ssize_t s;

    pid_t pid;

    if (argc < 2)

    {

        fprintf(stderr, "Usage: %s <num>...\n", argv[0]);

        exit(EXIT_FAILURE);

    }

    evfd = eventfd(0, EFD_NONBLOCK);/*EFD_SEMAPHORE semaphore way*/

    if (evfd == -1)

            handle_error("eventfd");         

    epfd = epoll_create(10);

    if (epfd == -1)

handle_error("epoll");

    struct epoll_event ev;

    ev.events = EPOLLIN;

    ev.data.fd = evfd;

    ret = epoll_ctl(epfd, EPOLL_CTL_ADD, evfd, &ev);

    if (ret < 0)

                handle_error("epoll_ctl");        

    pid = fork();

    if(pid == 0)

    {

        sleep(3);

        for (j = 1; j < argc; j++)

        {

            printf("Child writing %s to efd\n", argv[j]);

            u = strtoull(argv[j], NULL, 0);

            /* strtoull() allows various bases */

            s = write(evfd, &u, sizeof(uint64_t)); //append to the value

            if (s != sizeof(uint64_t))

            handle_error("write");

            sleep(1);

        }

        printf("Child completed write loop\n");

        exit(EXIT_SUCCESS);

    }

    else if(pid == -1)

   {

        handle_error("fork");

    }     

    struct epoll_event events[10];    

    int fd, i;

    printf("Parent about to read\n");

    for (j = 1; j < argc; j++)

    {

        ret = epoll_wait(epfd, events, 10, -1);

        printf("get %d events\n", ret);

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

        {

                fd = events[i].data.fd;

    if((events[i].events & EPOLLIN) && (fd == evfd))

                {

                        s = read(evfd, &u, sizeof(uint64_t)); // read it then empty the value

                        if (s != sizeof(uint64_t))

                                    handle_error("read");

                        printf("Parent read %llu (0x%llx) from efd\n", (unsigned long long) u, (unsigned long long) u);

                 }

         }

     }

    ret = epoll_ctl(epfd, EPOLL_CTL_DEL, evfd, NULL);

    if (ret < 0)

        handle_error("epoll_ctl");         

    wait();

    exit(EXIT_SUCCESS);          

}

 

每次把收到的所有的值都读走。

$ ./eventfd 5 2 3

Parent about to read

Child writing 5 to efd

get 1 events

Parent read 5 (0x5) from efd

Child writing 2 to efd

get 1 events

Parent read 2 (0x2) from efd

Child writing 3 to efd

get 1 events

Parent read 3 (0x3) from efd

Child completed write loop

 

如果flags带着一个EFD_SEMAPHORE,就以semaphore的方式 一次读1.

./eventfd——semaphore 1 2

Parent about to read 3

Child writing 1 to efd

get 1 events

Parent read 1 (0x1) from efd

Child writing 2 to efd

get 1 events

Parent read 1 (0x1) from efd

get 1 events

Parent read 1 (0x1) from efd

Child completed write loop

 

参考

http://blog.chinaunix.net/uid-23146151-id-3069427.html

0 0
原创粉丝点击