acl-dev / acl

C/C++ server and network library, including coroutine,redis client,http/https/websocket,mqtt, mysql/postgresql/sqlite client with C/C++ for Linux, Android, iOS, MacOS, Windows, etc..
https://acl-dev.cn
GNU Lesser General Public License v3.0
2.84k stars 937 forks source link

socket与fiber是如何结合的? #265

Open alongL opened 2 years ago

alongL commented 2 years ago

大神新好!

看了acl的源码,对协程的流程基本了解,不太明白的是socket与fiber是如何联接起来的。

像下面的示例代码,fiberecho这个类是继承了acl::fiber因此可以在fiber->start()的时候运行run()虚函数,但是当conn->read() 的时候,涉及到socket的读写,如何导致与此fiber暂停,然后在read成功后再继续运行,底层是如何实现的? 有没有相关的文档介绍?

    acl::fiber* fb = new fiber_echo(conn);
    fb->start();
// 客户端协程处理类,用来回显客户发送的内容,每一个客户端连接绑定一个独立的协程
class fiber_echo : public acl::fiber
{
public:
    fiber_echo(acl::socket_stream* conn) : conn_(conn) {}
private:
    acl::socket_stream* conn_;
    ~fiber_echo(void) { delete conn_; }
    // @override
    void run(void) {
        char buf[8192];
        while (true) {
            int ret = conn_->read(buf, sizeof(buf), false);
            if (ret == -1) {
                break;
            }
            if (conn_->write(buf, ret) != ret) {
                break;
            }
        }
        delete this; // 自销毁动态创建的协程对象
    }
};
zhengshuxin commented 2 years ago

acl 协程hook了底层的I/O API,所以可以将 socket 的 I/O 过程协程,我曾在 https://mp.weixin.qq.com/s/XAEzZAUYuOhuqMOszNFe2A 文章中介绍过 acl 协程的原理,但还未曾讲过 acl 协程是如何 hook 系统 I/O API 的,将来有时间可以讲讲这块。

alongL commented 2 years ago

大概是这张图所描述的内容吧。doc/articles/aclfiber.pptx中的图。 协程运行到conn->read()的时候,通过hookapi,实现注册读事件,挂接到epoll引擎上, 读事件到来后,此协程再转为运行态。

image

zhengshuxin commented 2 years ago

对,原理是这样的。