日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

eventfd以及epoll原理分析

發布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 eventfd以及epoll原理分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這兩天公司代碼中用到了epoll。然后在跟同事閑扯的過程中發現了Linux中有eventfd。兩者雖然名字看起來差不多,但是相關性倒是不多。
為了弄明白這兩個東西到底在內核上是怎么實現的,這兩天將內核這兩個部分的相關代碼看了下,也終于明白了這兩個東西的實現機制。
后續幾篇博客我盡量將這兩個東西的工作原理闡述清楚,但是自己的語言表達能力比較差,也只能是盡量了。

今天這篇博客首先是介紹兩者的使用方式,恰巧兩者能夠在一個程序中搞定,我就寫了下面的小程序來展示兩者的功能。
  • #include <stdio.h>
  • #include <unistd.h>
  • #include <sys/time.h>
  • #include <stdint.h>
  • #include <pthread.h>
  • #include <sys/eventfd.h>
  • #include <sys/epoll.h>

  • int efd = -1;

  • void *read_thread(void *dummy)
  • {
  • ????int ret = 0;
  • ????uint64_t count = 0;
  • ????int ep_fd = -1;
  • ????struct epoll_event events[10];

  • ????if (efd < 0)
  • ????{
  • ????????printf("efd not inited.\n");
  • ????????goto fail;
  • ????}

  • ????ep_fd = epoll_create(1024);
  • ????if (ep_fd < 0)
  • ????{
  • ????????perror("epoll_create fail: ");
  • ????????goto fail;
  • ????}

  • ????{
  • ????????struct epoll_event read_event;

  • ????????read_event.events = EPOLLHUP | EPOLLERR | EPOLLIN;
  • ????????read_event.data.fd = efd;

  • ????????ret = epoll_ctl(ep_fd, EPOLL_CTL_ADD, efd, &read_event);
  • ????????if (ret < 0)
  • ????????{
  • ????????????perror("epoll ctl failed:");
  • ????????????goto fail;
  • ????????}
  • ????}

  • ????while (1)
  • ????{
  • ????????ret = epoll_wait(ep_fd, &events[0], 10, 5000);
  • ????????if (ret > 0)
  • ????????{
  • ????????????int i = 0;
  • ????????????for (; i < ret; i++)
  • ????????????{
  • ????????????????if (events[i].events & EPOLLHUP)
  • ????????????????{
  • ????????????????????printf("epoll eventfd has epoll hup.\n");
  • ????????????????????goto fail;
  • ????????????????}
  • ????????????????else if (events[i].events & EPOLLERR)
  • ????????????????{
  • ????????????????????printf("epoll eventfd has epoll error.\n");
  • ????????????????????goto fail;
  • ????????????????}
  • ????????????????else if (events[i].events & EPOLLIN)
  • ????????????????{
  • ????????????????????int event_fd = events[i].data.fd;
  • ????????????????????ret = read(event_fd, &count, sizeof(count));
  • ????????????????????if (ret < 0)
  • ????????????????????{
  • ????????????????????????perror("read fail:");
  • ????????????????????????goto fail;
  • ????????????????????}
  • ????????????????????else
  • ????????????????????{
  • ????????????????????????struct timeval tv;

  • ????????????????????????gettimeofday(&tv, NULL);
  • ????????????????????????printf("success read from efd, read %d bytes(%llu) at %lds %ldus\n",
  • ???????????????????????????????ret, count, tv.tv_sec, tv.tv_usec);
  • ????????????????????}
  • ????????????????}
  • ????????????}
  • ????????}
  • ????????else if (ret == 0)
  • ????????{
  • ????????????/* time out */
  • ????????????printf("epoll wait timed out.\n");
  • ????????????break;
  • ????????}
  • ????????else
  • ????????{
  • ????????????perror("epoll wait error:");
  • ????????????goto fail;
  • ????????}
  • ????}

  • fail:
  • ????if (ep_fd >= 0)
  • ????{
  • ????????close(ep_fd);
  • ????????ep_fd = -1;
  • ????}

  • ????return NULL;
  • }

  • int main(int argc, char *argv[])
  • {
  • ????pthread_t pid = 0;
  • ????uint64_t count = 0;
  • ????int ret = 0;
  • ????int i = 0;

  • ????efd = eventfd(0, 0);
  • ????if (efd < 0)
  • ????{
  • ????????perror("eventfd failed.");
  • ????????goto fail;
  • ????}

  • ????ret = pthread_create(&pid, NULL, read_thread, NULL);
  • ????if (ret < 0)
  • ????{
  • ????????perror("pthread create:");
  • ????????goto fail;
  • ????}

  • ????for (i = 0; i < 5; i++)
  • ????{
  • ????????count = 4;
  • ????????ret = write(efd, &count, sizeof(count));
  • ????????if (ret < 0)
  • ????????{
  • ????????????perror("write event fd fail:");
  • ????????????goto fail;
  • ????????}
  • ????????else
  • ????????{
  • ????????????struct timeval tv;

  • ????????????gettimeofday(&tv, NULL);
  • ????????????printf("success write to efd, write %d bytes(%llu) at %lds %ldus\n",
  • ???????????????????ret, count, tv.tv_sec, tv.tv_usec);
  • ????????}

  • ????????sleep(1);
  • ????}

  • fail:
  • ????if (0 != pid)
  • ????{
  • ????????pthread_join(pid, NULL);
  • ????????pid = 0;
  • ????}

  • ????if (efd >= 0)
  • ????{
  • ????????close(efd);
  • ????????efd = -1;
  • ????}
  • ????return ret;
  • }

  • gcc main.c -Werror -Wall -lpthread
  • 最后執行效果為
  • success write to efd, write 8 bytes(4) at 1328805612s 21939us
  • success read from efd, read 8 bytes(4) at 1328805612s 21997us
  • success write to efd, write 8 bytes(4) at 1328805613s 22247us
  • success read from efd, read 8 bytes(4) at 1328805613s 22287us
  • success write to efd, write 8 bytes(4) at 1328805614s 22462us
  • success read from efd, read 8 bytes(4) at 1328805614s 22503us
  • success write to efd, write 8 bytes(4) at 1328805615s 22688us
  • success read from efd, read 8 bytes(4) at 1328805615s 22726us
  • success write to efd, write 8 bytes(4) at 1328805616s 22973us
  • success read from efd, read 8 bytes(4) at 1328805616s 23007us
  • epoll wait timed out.
  • eventfd具體與pipe有點像,用來完成兩個線程之間事件觸發,但是同事說現在已經支持到進程級別,現在我還沒有驗證過。能夠用來作為線程之間簡單通訊,類似于pthread_cond_t。
    epoll則是linux提供的一種多路復用技術,完成與select,poll等一樣的功能,完成對多個文件描述符進行等待。本文上述代碼僅僅用到了一個文件描述符。
    epoll比select的優勢網絡隨處可見,這就不多說了。

    應用程序就已經寫到這了,對于內核里面具體是怎么搞的,將會在以后的博客中盡量解釋清楚。

    總結

    以上是生活随笔為你收集整理的eventfd以及epoll原理分析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。