免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 76218 | 回复: 34

[其他] 事件响应方式 [复制链接]

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2016-08-12 11:26 |显示全部楼层
在编程中,常常要让程序等待某些事件,如何及时响应这些事件,有若干方式。
1.        程序轮询,程序不断查询状态,直到期望的状态发生。这将剧烈消耗CPU和相关资源。可以在轮询中插入sleep之类的休眠以减小CPU的消耗,但是牺牲了响应时间。
2.        事件触发,有几种:
1:1    一个线程等待一个事件,同步阻塞方式。等待期间不消耗CPU,事件可以立即响应。如read。
M:1    一个线程等待M个事件。同步阻塞方式。等待期间不消耗CPU,出现任一事件可以立即响应。如select。
M:N    N个线程等待M个事件。同步阻塞方式。等待期间不消耗CPU,出现任一事件都会选出一个线程来响应这个事件。如epoll。

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
发表于 2016-08-12 17:30 |显示全部楼层
只讨论 rpc 的情况?
不考虑跨硬件 rpc 的话,除了socket/pipe,还有信号量,条件量,直接回调(有竞争就加锁)配着队列之类的也方便

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2016-08-12 21:31 |显示全部楼层
本帖最后由 yulihua49 于 2016-08-12 21:33 编辑
cokeboL 发表于 2016-08-12 17:30
只讨论 rpc 的情况?
不考虑跨硬件 rpc 的话,除了socket/pipe,还有信号量,条件量,直接回调(有竞争就加 ...

把你的想法说说,补充一下。

尤其是同步阻塞的事件处理器如何处理异步IO,没想出来怎样简练的描述。
关于eventfd,signalfd,timerfd等等。

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
发表于 2016-08-15 14:32 |显示全部楼层
最近论坛上的少,才看到。

eventfd这个好像没什么可说的吧,epollfd,就是epoll那几个接口
signalfd,这个具体是指信号?比如kill -9?还是指其他?
实现timer的方式也挺多的,timerfd这个也没明白具体指?

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
发表于 2016-08-15 14:42 |显示全部楼层
如果非要用c/c++

异步IO
发包肯定要存队列,同步阻塞的地方处理,也只是把包挂到sock fd对应的结构体的消息队列里然后加个等待可写的事件,但是无法保证同步阻塞的地方返回时包已经发出去了,
想等到结果,就得把同步的地方分两半,发包之后的部分弄个回调来做,如果同步这部分逻辑,发包和等待都是在循环里,又不行,还得改成回调之后再激发下一次循环的结构,
所以你们各位弄的协程那种,可能比这种写法稍好一些
如果同步的地方都用同步发肯定太虐心了,一是发包的sock fd如果有多个,就都应该从epoll列表里dele了先,然后再遍历阻塞发,这种肯定就乱了,不行

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
发表于 2016-08-15 14:50 |显示全部楼层
timer c/c++ epoll这种结构里
我见过的主流大概就两种:
一种是弄个小顶堆或者list、map也凑合用,epoll的循环里每次wait最小时间间隔,nginx好像是这种,redis类似但是好像是没用小顶堆,用的链表,我猜是redis的业务场景,简单的链表实现足够了吧
另一种是wait固定的tick time,然后和timer的结构最小间隔对比看到时间没,就相当于轮询吧


论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
发表于 2016-08-15 14:53 |显示全部楼层
不太清楚你们具体的业务场景,各种ipc机制和锁这些,就像过家家,不同的业务场景和需求,可以有太多中摆法。。

可惜你们不用golang,否则真是简化了太多结构,chan、锁、回调加起来的各种组合,就差不多能搞所有姿势了,省心,省力。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2016-08-15 16:07 |显示全部楼层
本帖最后由 yulihua49 于 2016-08-15 16:16 编辑
cokeboL 发表于 2016-08-15 14:53
不太清楚你们具体的业务场景,各种ipc机制和锁这些,就像过家家,不同的业务场景和需求,可以有太多中摆法。 ...

个人偏爱C是因为癖好,喜欢玩机器,C更像在使用一个机器。其他语言更高级,接近于任务描述,应该是好用些,但是资源控制更间接,有时不知他怎么干的,需要优化也无从下手。

那几个fd,你在网上搜搜,有详细说明。配合epoll完成非IO异步操作的。
这里有一个eventfd配合epoll进行文件异步IO的例子:

  1. /*******************************************
  2. * 需要linux 2.6.22 以上版本
  3. * 和libaio 3.107以上版本
  4. * 如果不具备这个条件,在makefile里用SIO_fd.o
  5. * 取代本模块
  6. *******************************************/

  7. #include <unistd.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <sys/eventfd.h>
  11. #include <libaio.h>

  12. #include <scsrv.h>

  13. static int AIO_oper(int fd,char *buff,size_t iosize,int flg)
  14. {
  15. io_context_t myctx;
  16. int rc,num;
  17. uint64_t finished_aio;
  18. struct iocb _iocb,*io=&_iocb;
  19. struct io_event event;
  20. int     efd = eventfd(0, 0);
  21. T_YIELD yield=get_yield();

  22.         if (efd == -1) {   
  23.                 return flg?write(fd,buff,iosize):read(fd,buff,iosize);
  24.         }   

  25.         memset(&myctx,0,sizeof(myctx));
  26.         io_set_eventfd(io,efd);
  27.         io_queue_init(1, &myctx);
  28.         if(flg) io_prep_pread(io, fd, buff, iosize, 0);
  29.         else    io_prep_pwrite(io, fd, buff, iosize, 0);
  30.         rc = io_submit(myctx, 1, &io);
  31.         if(rc<0) {
  32.                 close(efd);
  33.                 io_destroy(myctx);
  34.                 return flg?write(fd,buff,iosize):read(fd,buff,iosize);
  35.         }
  36.         if(yield) {
  37.                 rc = yield(efd,0,0);//efd提交给epoll,并yield and resume.
  38.                 if(rc==0) eventfd_read(efd, &finished_aio);
  39.         }
  40.         close(efd);
  41.         num = io_getevents(myctx, 1, 1, &event, NULL);
  42.         if(num>0) {
  43.                 if(event.res2==0) num=event.res;
  44.                 else num=-1;
  45.         }
  46.         io_destroy(myctx);
  47.         return num;
  48. }

  49. int AIO_read(int fd,char *buff,size_t iosize)
  50. {
  51.         return AIO_oper(fd,buff,iosize,0);
  52. }

  53. int AIO_write(int fd,char *buff,size_t iosize)
  54. {
  55.         return AIO_oper(fd,buff,iosize,1);
  56. }

复制代码

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2016-08-15 16:21 |显示全部楼层
本帖最后由 yulihua49 于 2016-08-15 16:22 编辑
cokeboL 发表于 2016-08-15 14:53
不太清楚你们具体的业务场景,各种ipc机制和锁这些,就像过家家,不同的业务场景和需求,可以有太多中摆法。 ...

发了个回复怎么丢了?

  1. /*******************************************
  2. * 需要linux 2.6.22 以上版本
  3. * 和libaio 3.107以上版本
  4. * 如果不具备这个条件,在makefile里用SIO_fd.o
  5. * 取代本模块
  6. *******************************************/

  7. #include <unistd.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <sys/eventfd.h>
  11. #include <libaio.h>

  12. #include <scsrv.h>

  13. static int AIO_oper(int fd,char *buff,size_t iosize,int flg)
  14. {
  15. io_context_t myctx;
  16. int rc,num;
  17. uint64_t finished_aio;
  18. struct iocb _iocb,*io=&_iocb;
  19. struct io_event event;
  20. int     efd = eventfd(0, 0);
  21. T_YIELD yield=get_yield();

  22.         if (efd == -1) {   
  23.                 return flg?write(fd,buff,iosize):read(fd,buff,iosize);
  24.         }   

  25.         memset(&myctx,0,sizeof(myctx));
  26.         io_set_eventfd(io,efd);
  27.         io_queue_init(1, &myctx);
  28.         if(flg) io_prep_pread(io, fd, buff, iosize, 0);
  29.         else    io_prep_pwrite(io, fd, buff, iosize, 0);
  30.         rc = io_submit(myctx, 1, &io);
  31.         if(rc<0) {
  32.                 close(efd);
  33.                 io_destroy(myctx);
  34.                 return flg?write(fd,buff,iosize):read(fd,buff,iosize);
  35.         }
  36.         if(yield) {
  37.                 rc = yield(efd,0,0);//efd提交给epoll,并yield and resume.
  38.                 if(rc==0) eventfd_read(efd, &finished_aio);
  39.         }
  40.         close(efd);
  41.         num = io_getevents(myctx, 1, 1, &event, NULL);
  42.         if(num>0) {
  43.                 if(event.res2==0) num=event.res;
  44.                 else num=-1;
  45.         }
  46.         io_destroy(myctx);
  47.         return num;
  48. }

  49. int AIO_read(int fd,char *buff,size_t iosize)
  50. {
  51.         return AIO_oper(fd,buff,iosize,0);
  52. }

  53. int AIO_write(int fd,char *buff,size_t iosize)
  54. {
  55.         return AIO_oper(fd,buff,iosize,1);
  56. }

复制代码

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2016-08-15 16:24 |显示全部楼层
cokeboL 发表于 2016-08-15 14:53
不太清楚你们具体的业务场景,各种ipc机制和锁这些,就像过家家,不同的业务场景和需求,可以有太多中摆法。 ...

  1. /*******************************************
  2. * 需要linux 2.6.22 以上版本
  3. * 和libaio 3.107以上版本
  4. * 如果不具备这个条件,在makefile里用SIO_fd.o
  5. * 取代本模块
  6. *******************************************/

  7. #include <unistd.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <sys/eventfd.h>
  11. #include <libaio.h>

  12. #include <scsrv.h>

  13. static int AIO_oper(int fd,char *buff,size_t iosize,int flg)
  14. {
  15. io_context_t myctx;
  16. int rc,num;
  17. uint64_t finished_aio;
  18. struct iocb _iocb,*io=&_iocb;
  19. struct io_event event;
  20. int     efd = eventfd(0, 0);
  21. T_YIELD yield=get_yield();

  22.         if (efd == -1) {   
  23.                 return flg?write(fd,buff,iosize):read(fd,buff,iosize);
  24.         }   

  25.         memset(&myctx,0,sizeof(myctx));
  26.         io_set_eventfd(io,efd);
  27.         io_queue_init(1, &myctx);
  28.         if(flg) io_prep_pread(io, fd, buff, iosize, 0);
  29.         else    io_prep_pwrite(io, fd, buff, iosize, 0);
  30.         rc = io_submit(myctx, 1, &io);
  31.         if(rc<0) {
  32.                 close(efd);
  33.                 io_destroy(myctx);
  34.                 return flg?write(fd,buff,iosize):read(fd,buff,iosize);
  35.         }
  36.         if(yield) {
  37.                 rc = yield(efd,0,0);//efd提交给epoll,并yield and resume.
  38.                 if(rc==0) eventfd_read(efd, &finished_aio);
  39.         }
  40.         close(efd);
  41.         num = io_getevents(myctx, 1, 1, &event, NULL);
  42.         if(num>0) {
  43.                 if(event.res2==0) num=event.res;
  44.                 else num=-1;
  45.         }
  46.         io_destroy(myctx);
  47.         return num;
  48. }

  49. int AIO_read(int fd,char *buff,size_t iosize)
  50. {
  51.         return AIO_oper(fd,buff,iosize,0);
  52. }

  53. int AIO_write(int fd,char *buff,size_t iosize)
  54. {
  55.         return AIO_oper(fd,buff,iosize,1);
  56. }

复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP