libeio的个人理解

来源:互联网 发布:从unix到linux 乱码 编辑:程序博客网 时间:2024/05/21 14:52
libeio是异步I/O库,提供了比较齐全的异步文件操作,能够让使用者写出非阻塞程序。今天看了一下libeio的源码,先将自己的一些理解讲述一下。
libeio处理请求的详细过程:
    这个libeio就是一个异步的io库,这里面使用的时候要先调用eio_init函数去初始化这个库,这个初始化函数里面主要是做了初始化锁和激活线程的条件,初始化request队列和response队列等。
    在初始化了这个库以后呢就可以调用这个库里面的函数了,在调用这写函数的时候呢并不是立即就执行了,这个库会先将这些调用封装成为一个eio_req结构体,然后通过 eio_submit函数将这个结构体按照优先级push到req_queue队列里面,并且在eio_submit函数里面会调用etp_maybe_start_thread函数尝试创建新的worker线程(如果worker线程数目没有超过线线程池的上限而且空闲线程不足的时候会创建),这个worker线程创建之后呢就会调用 etp_proc函数来处理请求,这个etp_proc函数启动后就会一直等待req_wait条件的出现,当等待的线程数目超过设定的上限的时候呢就会为这个线程设置一个超时,当超时后还没有接收到req_wait信号时就会杀死这个线程。当worker线程收到这个req_wait信号的时候就会尝试从req_queue中获取一个请求并调用eio_execute来执行io操作,在执行完io操作后会将结果push到res_queue中,这时候如果这个返回队列是空的那么就会调用want_poll_cb,表示有请求已经处理完毕可以返回数据了。这时候就会在want_poll_cb里面向pipe[1]写一个数据,表示可以调用eio_poll了,然后主线程就会去判断pipe[0]是否可读,可读时就会调用eio_poll从res_queue中获取response然后调用这个请求的回调函数,当没有请求结果的时候,eio_poll里面就会调用 done_poll_cb,这个done_poll_cb应该读取pipe[0]里面是数据以结束整个io过程。

下面是libeio的具体实现步骤。

1. 主线程调用eio_init函数,主要是初始化req_queue,res_queue以及对应的mutex和cond;

2-3. 所有的IO操作其实都是对eio_sumbit的调用,而eio_sumbit的职能是将IO操作封装为request并插入到req_queue;并调用cond_signal向worker线程发出reqwait已经OK的信号;

4. worker线程被创建后执行的函数为etp_proc,etp_proc启动后会一直等待reqwait条件的出现;

5-6. 当reqwait条件变量满足时,etp_proc从req_queue中取得一个待处理的request;并调用eio_execute来同步执行该IO操作;

7-8. eio_execute完成后,将response插入到res_queue队列中;同时调用want_poll来通知主线程request已经处理完毕;

9. 这里worker线程通知主线程的机制是通过向pipe[1]写一个byte数据;

10. 当主线程发现pipe[0]可读时,就调用eio_poll;

11. eio_poll从res_queue里取response,并调用该IO操作在init时设置的callback函数完成后续处理;

12. 在res_queue中没有待处理response时,调用done_poll;

13-14. done_poll从pipe[0]读出一个byte数据,该IO操作完成。

0 0
原创粉丝点击