新版本的glib支持使用外部的事件循环代替内部的poll,这篇文章使用的glib版本是V2.72.0, 理解还很粗浅,但是demo能跑起来,还需要再详细研究一下参考的两个链接,多线程下使用及效率是怎样的都还不清楚。

1、新API

通过新的API g_main_context_new_with_flags 及新变量G_MAIN_CONTEXT_FLAGS_OWNERLESS_POLLING可以创建一个无主的poll,然后通过glib的一套API可以实现自己的事件循环。ubuntu18下的demo:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <glib.h>
#include <sys/epoll.h>static GMainContext *watchdog_context = NULL;int num = 0;
static gboolean cb_check(gpointer user_data)
{printf("In cb_check %d \n", num);
}char* name = "ori";
static gpointer cb_watchdog(gpointer user_data)
{num = 1;GMainLoop *loop = (GMainLoop *) user_data;GMainContext *watchdog_context = g_main_loop_get_context(loop);GSource *timeout_source;timeout_source = g_timeout_source_new_seconds(2);g_source_set_callback(timeout_source, cb_check, watchdog_context, (gpointer)name);g_source_attach(timeout_source, watchdog_context);g_source_unref(timeout_source);printf("Sessions watchdog started\n");g_main_loop_run(loop);printf("Sessions watchdog stopped\n");return NULL;
}void test_ori_glib_event_loop()
{/* Start the sessions timeout watchdog */watchdog_context = g_main_context_new();GError *error = NULL;GMainLoop *watchdog_loop = g_main_loop_new(watchdog_context, FALSE);GThread *watchdog = g_thread_try_new("timeout watchdog", &cb_watchdog, watchdog_loop, &error);if(error != NULL) {printf("Got error %d (%s) trying to start sessions timeout watchdog...\n",error->code, error->message ? error->message : "??");g_error_free(error);exit(1);}
}unsigned short glib_event_2_epoll(unsigned short  glib_event)
{unsigned short ret = 0;if (glib_event & G_IO_IN)ret |= EPOLLIN;if (glib_event & G_IO_OUT)ret |= EPOLLOUT;if (glib_event & G_IO_PRI)ret |= EPOLLPRI;if (glib_event & G_IO_HUP)ret |= EPOLLHUP;if (glib_event & G_IO_NVAL)ret |= EPOLLERR;return ret;
}unsigned short epoll_event_2_glib(unsigned short  epoll_event)
{unsigned short ret = 0;if (epoll_event & EPOLLIN) ret |= G_IO_IN;if (epoll_event & EPOLLOUT)ret |= G_IO_OUT ;if (epoll_event & EPOLLPRI)ret |= G_IO_PRI;if (epoll_event & EPOLLHUP)ret |= G_IO_HUP;if (epoll_event & EPOLLERR)ret |= G_IO_NVAL;return ret;
}#define MAX_EVENTS (4096)
int ev_poll(GPollFD *fds,guint    nfds,gint     timeout)
{GPollFD *f = NULL;int epollfd = -1;struct epoll_event  ev;int ret = 0;int max_events = nfds;struct epoll_event epoll_events[MAX_EVENTS];for (f = fds; f < &fds[nfds]; ++f){if (f->fd >= 0){if(epollfd == -1){epollfd = epoll_create1(EPOLL_CLOEXEC);if ( epollfd == -1 ){perror( "epoll_create1" );continue;}}ev.events  = f->events;//glib_event_2_epoll(f->events);ev.data.fd = f->fd;if( epoll_ctl(epollfd, EPOLL_CTL_ADD, f->fd, &ev) == -1 ){perror( "epoll_ctl: listen_sock" );continue;}}}nfds = epoll_wait( epollfd, epoll_events, MAX_EVENTS, 10 );if(nfds > 0){//unsigned short events = event[i].events;struct epoll_event  *ev = NULL;for (ev = epoll_events; ev < &epoll_events[nfds]; ++ev){f->revents = 0;if (f->fd >= 0){f->revents = ev->events;//epoll_event_2_glib(ev->events);}}}else{perror( "epoll_wait" );return 0;}if(epollfd != -1){close(epollfd);}return nfds;
}char* evname = "ev_ori";
/* epoll实现的事件侦听及处理 */
void test_ev_glib_event_loop()
{num = 2;/* Start the sessions timeout watchdog */GMainContext *ctx = g_main_context_new_with_flags (G_MAIN_CONTEXT_FLAGS_OWNERLESS_POLLING);g_main_context_push_thread_default (ctx);GPollFD fds[20];gint fds_size;gint max_priority;GSource *source = NULL;GSource *timeout_source;timeout_source = g_timeout_source_new_seconds(2);g_source_set_callback(timeout_source, cb_check, ctx, (gpointer)evname);g_source_attach(timeout_source, ctx);g_source_unref(timeout_source);for(;;){gboolean ready_to_dispatch = g_main_context_prepare (ctx, &max_priority);gint timeout, nready;fds_size = g_main_context_query (ctx, max_priority, &timeout, fds, G_N_ELEMENTS (fds));//nready = g_poll (fds, fds_size, /*timeout=*/0);nready = ev_poll (fds, fds_size, /*timeout=*/0);if (!ready_to_dispatch && nready == 0){if (timeout == -1)break;elseg_usleep (timeout * 1000);}if(fds_size == 1)printf("events %d \n", fds[0].events);printf("events G_IO_IN[%d] G_IO_OUT[%d] G_IO_PRI[%d]\n", G_IO_IN, G_IO_OUT, G_IO_PRI);ready_to_dispatch = g_main_context_check (ctx, max_priority, fds, fds_size);if (ready_to_dispatch)g_main_context_dispatch (ctx);}g_assert_cmpint (g_poll (fds, fds_size, 0), >, 0);g_main_context_unref (ctx);
}int main()
{//test_ori_glib_event_loop();test_ev_glib_event_loop();while(1){sleep(1);}return 0;
}

编译

gcc -o demo_glib main.c -lpthread `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0`

2、参考

《1》、Pluggable event loop backends (epoll support)
《2》、Add g_main_context_new_with_flags() and ownerless polling option

新版本glib使用epoll代替poll相关推荐

  1. epoll和poll的C++11多线程练习

    一个epoll和poll的多线程练习 https://github.com/StudentErick/EpollServerTask

  2. Linux下多路复用IO接口epoll/select/poll的区别

    select比epoll效率差的原因:select是轮询,epoll是触发式的,所以效率高. Select: 1.Socket数量限制:该模式可操作的Socket数由FD_SETSIZE决定,内核默认 ...

  3. Java网络编程与NIO详解13:epoll、poll、select面试题汇总

    文章目录 一.文件描述符与IO模型 二.端口和地址复用 三.select 四.poll 五.epoll 六.相关面试题 1.epoll读到一半又有新事件来了怎么办? 一.文件描述符与IO模型   文件 ...

  4. linux下poll和epoll内核源代码剖析

    作者:董昊 博客链接http://donghao.org/uii/ poll和epoll的使用应该不用再多说了.当fd很多时,使用epoll比poll效率更高. 我们通过内核源码分析来看看到底是为什么 ...

  5. 朴素、Select、Poll和Epoll网络编程模型实现和分析——模型比较

    经过之前四篇博文的介绍,可以大致清楚各种模型的编程步骤.现在我们来回顾下各种模型(转载请指明出于breaksoftware的csdn博客) 模型编程步骤对比 <朴素.Select.Poll和Ep ...

  6. Select、Poll、Epoll IO复用技术

    我们之前采用的多进程方式实现的服务器端,一次创建多个工作子进程来给客户端提供服务.其实这种方式是存在问题的. 可以打个比方:如果我们先前创建的几个进程承载不了目前快速发展的业务的话,是不是还得增加进程 ...

  7. select,poll,epoll区别

    2019独角兽企业重金招聘Python工程师标准>>> select的本质是采用32个整数的32位,即32*32= 1024来标识,fd值为1-1024.当fd的值超过1024限制时 ...

  8. linux下代码写错了怎么更改_linux系统下poll和epoll内核源代码剖析

    poll和epoll的使用应该不用再多说了.当fd很多时,使用epoll比poll效率更高.我们通过内核源码分析来看看到底是为什么. poll剖析poll系统调用: int poll(struct p ...

  9. 【网络通信】select、poll、epoll

    [网络通信]select.poll.epoll 目录 [网络通信]select.poll.epoll 前言 0. 网络编程基础原理 1 网络编程(Socket)概念 一.BIO (Blocking I ...

最新文章

  1. 不投降就是成功 --- 我看《新喜剧之王》
  2. matlab共轭梯度法_优化算法之牛顿法
  3. js moment时间戳与时间格式相互转换
  4. hdu-3790-最短路径问题(dijkstra算法)
  5. Linux设备开机卡主
  6. 河南省旅馆业信息化管理实现“人证核验、无证入住”系统全覆盖
  7. 静态VLAN及配置实例详解
  8. 硬盘检测神器-HD Tune Pro/Hard Disk Sentinel
  9. arduino 有源 蜂鸣器_Arduino控制蜂鸣器发声
  10. 西安省某小学能耗监测及电力监控系统的研究与应用
  11. 奇迹网站可视化排行榜]_外观可视化奇迹
  12. X509数字证书格式
  13. 真正厉害的人,早戒掉了情绪
  14. 宽带显示不能建立到远程计算机,宽带连接错误820:不能建立到远程计算机的连接 正确处理办法...
  15. 解决Aero Peek 灰色状态无法点击问题
  16. 马洛斯需求层次模型在用户体验中的理解
  17. Flex和Flash的区别和联系
  18. 空间与运动——模拟太阳系、牧师与魔鬼游戏实现详解
  19. 医用纤维和树脂的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  20. C++课程教学改革问卷调查报告

热门文章

  1. Win10资源管理器闪退解决办法
  2. 小哈智能机器人的功能_小哈智能教育机器人H2产品外观参数说明
  3. 开发中的各种时间格式转换(一)
  4. ue4当中材质自定义uv和多套uv
  5. @RunWith(SpringRunner.class)和@RunWith(SpringJUnit4ClassRunner.class)的区别
  6. 武大计算机导师蔡贤涛,程媛(武汉大学计算中心教师)_百度百科
  7. 富士相机设置传原图_富士X-S10相机传图必看!原创完美解决PC互传图片问题
  8. 抓住那头牛(BFS广搜)
  9. ble mac地址 协议_让BLE设备的名称包含MAC地址
  10. 跳转系统设置token