免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: yulihua49
打印 上一主题 下一主题

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

论坛徽章:
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
11 [报告]
发表于 2016-08-15 16:24 |只看该作者
本帖最后由 yulihua49 于 2016-08-15 16:25 编辑

不能发代码,发了就没了。
/*******************************************
* 需要linux 2.6.22 以上版本
* 和libaio 3.107以上版本
* 如果不具备这个条件,在makefile里用SIO_fd.o
* 取代本模块
*******************************************/

#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/eventfd.h>
#include <libaio.h>

#include <scsrv.h>

static int AIO_oper(int fd,char *buff,size_t iosize,int flg)
{
io_context_t myctx;
int rc,num;
uint64_t finished_aio;
struct iocb _iocb,*io=&_iocb;
struct io_event event;
int     efd = eventfd(0, 0);
T_YIELD yield=get_yield();

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

        memset(&myctx,0,sizeof(myctx));
        io_set_eventfd(io,efd);
        io_queue_init(1, &myctx);
        if(flg) io_prep_pread(io, fd, buff, iosize, 0);
        else    io_prep_pwrite(io, fd, buff, iosize, 0);
        rc = io_submit(myctx, 1, &io);
        if(rc<0) {
                close(efd);
                io_destroy(myctx);
                return flg?write(fd,buff,iosize):read(fd,buff,iosize);
        }
        if(yield) {
                rc = yield(efd,0,0);//efd提交给epoll,并yield and resume.
                if(rc==0) eventfd_read(efd, &finished_aio);
        }
        close(efd);
        num = io_getevents(myctx, 1, 1, &event, NULL);
        if(num>0) {
                if(event.res2==0) num=event.res;
                else num=-1;
        }
        io_destroy(myctx);
        return num;
}

int AIO_read(int fd,char *buff,size_t iosize)
{
        return AIO_oper(fd,buff,iosize,0);
}

int AIO_write(int fd,char *buff,size_t iosize)
{
        return AIO_oper(fd,buff,iosize,1);
}

论坛徽章:
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
12 [报告]
发表于 2016-08-16 14:45 |只看该作者
eventfd看了下,类似pipe

论坛徽章:
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
13 [报告]
发表于 2016-08-16 14:50 |只看该作者
原来这几个是新API,我*nix c 还停留在apue unp范围。

c/c++实现的协程我是无爱的。。。

论坛徽章:
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
14 [报告]
发表于 2016-08-16 17:57 |只看该作者
发个代码还等一天审核,还不告知,以为丢了呢,没兴趣了。

论坛徽章:
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
15 [报告]
发表于 2016-08-18 10:18 |只看该作者
本帖最后由 yulihua49 于 2016-08-18 10:21 编辑
cokeboL 发表于 2016-08-16 14:50
原来这几个是新API,我*nix c 还停留在apue unp范围。

c/c++实现的协程我是无爱的。。。

c的协程,实现机制和resume条件都是明确的。epoll有响应了就resume。别的语言,晕。就一个yield,啥时候能resume不知道。一般是轮到你了就resume。这不符合要求。
一般协程是配合AIO/NIO的,如果干的好好的为什么要yield呢?一定是等什么事件,干不下去了才需要yield。这个需求,其他语言是怎么实现的?

论坛徽章:
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
16 [报告]
发表于 2016-08-18 10:38 |只看该作者
回复 15# yulihua49


我最初看lua的协程就不喜欢,因为要手动yield resume,而且lua又难利用多核,所以连深入研究的兴趣都没有
我不喜欢c的协程,也是因为手动档,这种跟golang erlang比,写法太麻烦太弱鸡了,erlang golang的可以看
成是线程那样,调度是应用层实现也不需要自己操心,清爽干净得多。。。

论坛徽章:
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
17 [报告]
发表于 2016-08-18 10:45 |只看该作者
golang一个简单的转发网关

  1. import (
  2.         "fmt"
  3.         "net"
  4. )

  5. func newAgentConn(clientConn *net.TCPConn, serverAddr string) {
  6.         serverConn, dailErr := net.Dial("tcp", serverAddr)

  7.         if dailErr == nil {
  8.                 c2sCor := func() {
  9.                         defer func() {
  10.                                 _ = recover()
  11.                         }()

  12.                         var nread int
  13.                         var nwrite int
  14.                         var err error
  15.                         var buf = make([]byte, 1024)
  16.                         for {
  17.                                 nread, err = clientConn.Read(buf)
  18.                                 if err != nil {
  19.                                         clientConn.Close()
  20.                                         serverConn.Close()
  21.                                         break
  22.                                 }

  23.                                 nwrite, err = serverConn.Write(buf[:nread])
  24.                                 if nwrite != nread || err != nil {
  25.                                         clientConn.Close()
  26.                                         serverConn.Close()
  27.                                         break
  28.                                 }
  29.                         }
  30.                 }

  31.                 s2cCor := func() {
  32.                         defer func() {
  33.                                 _ = recover()
  34.                         }()

  35.                         var nread int
  36.                         var nwrite int
  37.                         var err error
  38.                         var buf = make([]byte, 1024)
  39.                         for {
  40.                                 nread, err = serverConn.Read(buf)
  41.                                 if err != nil {
  42.                                         clientConn.Close()
  43.                                         serverConn.Close()
  44.                                         break
  45.                                 }

  46.                                 nwrite, err = clientConn.Write(buf[:nread])
  47.                                 if nwrite != nread || err != nil {
  48.                                         clientConn.Close()
  49.                                         serverConn.Close()
  50.                                         break
  51.                                 }
  52.                         }
  53.                 }

  54.                 go c2sCor()
  55.                 go s2cCor()
  56.         } else {
  57.                 clientConn.Close()
  58.         }
  59. }

  60. func RunAgent(agentAddr string, serverAddr string) {
  61.         tcpAddr, err := net.ResolveTCPAddr("tcp4", agentAddr)
  62.         if err != nil {
  63.                 fmt.Println("ResolveTCPAddr Error: ", err)
  64.                 return
  65.         }

  66.         listener, err2 := net.ListenTCP("tcp", tcpAddr)
  67.         if err2 != nil {
  68.                 fmt.Println("ListenTCP Error: ", err2)
  69.                 return
  70.         }

  71.         defer listener.Close()

  72.         fmt.Println(fmt.Sprintf("Agent Start Running on: Agent(%s) -> Server(%s)!", agentAddr, serverAddr))
  73.         for {
  74.                 conn, err := listener.AcceptTCP()

  75.                 if err != nil {
  76.                         fmt.Println("AcceptTCP Error: ", err2)
  77.                 } else {
  78.                         go newAgentConn(conn, serverAddr)
  79.                 }
  80.         }
  81. }

  82. func TestAgent() {
  83.         Run("127.0.0.1:8888", "127.0.0.1:9999")
  84. }
复制代码

论坛徽章:
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
18 [报告]
发表于 2016-08-18 11:01 |只看该作者
本帖最后由 yulihua49 于 2016-08-18 11:03 编辑
cokeboL 发表于 2016-08-18 10:45
golang一个简单的转发网关

不懂golang。
没看见多线程。
err = clientConn.Read(buf)--------这个需要yield,怎样实现的?没有yield就成了1:1的事件等待。

论坛徽章:
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
19 [报告]
发表于 2016-08-18 11:38 |只看该作者
go c2sCor()
go s2cCor()
这两句就是启动两个协程,然后
err = clientConn.Read(buf)
nwrite, err = serverConn.Write(buf[:nread])
这两句就都是阻塞了,不需要异步
神清气爽的赶脚

论坛徽章:
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
20 [报告]
发表于 2016-08-18 12:09 |只看该作者
本帖最后由 yulihua49 于 2016-08-18 12:29 编辑
cokeboL 发表于 2016-08-18 11:38
go c2sCor()
go s2cCor()
这两句就是启动两个协程,然后

启动两个协程,而不是线程?那么没有并行功能,无法充分利用多核。
我希望看到多线程协程,能够并行,也能把任务在多个线程间切换。要看看你是怎么管理协程与线程的关系。

少线程服务器  --- 其实还是多线程服务器,就是线程数不多,大约=核数。要充分利用所有的线程,一旦发生等待就yield,放弃这个任务赶紧接别的任务。

我那个例子只是应用侧代码,很简单,而且是同步异步自适应的。就是:同步框架可以调用它,异步框架也可以调用它,只是需要事先提供yield函数即可。

多线程与多协程的关系在于yield函数内的代码,作为C,当然是非常的庞杂,但是完全可以实现上述需求。

你是每个连接产生3个协程?如果10000个连接来了,就是30000个协程?30000个棧?每个棧就算1M,所需内存?
在C里也是这个问题,我用棧池来解决,就是栈数=线程数,激活的协程才拥有棧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP