eventfd以及epoll原理分析
生活随笔
收集整理的這篇文章主要介紹了
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的優勢網絡隨處可見,這就不多說了。
應用程序就已經寫到這了,對于內核里面具體是怎么搞的,將會在以后的博客中盡量解釋清楚。
為了弄明白這兩個東西到底在內核上是怎么實現的,這兩天將內核這兩個部分的相關代碼看了下,也終于明白了這兩個東西的實現機制。
后續幾篇博客我盡量將這兩個東西的工作原理闡述清楚,但是自己的語言表達能力比較差,也只能是盡量了。
今天這篇博客首先是介紹兩者的使用方式,恰巧兩者能夠在一個程序中搞定,我就寫了下面的小程序來展示兩者的功能。
epoll則是linux提供的一種多路復用技術,完成與select,poll等一樣的功能,完成對多個文件描述符進行等待。本文上述代碼僅僅用到了一個文件描述符。
epoll比select的優勢網絡隨處可見,這就不多說了。
應用程序就已經寫到這了,對于內核里面具體是怎么搞的,將會在以后的博客中盡量解釋清楚。
總結
以上是生活随笔為你收集整理的eventfd以及epoll原理分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 24核32线程 Intel 13酷睿新增
- 下一篇: MySQL安装错误: unknown o