libuv异步实现分析

我们都知道libuv是异步非阻塞的,那么它究竟是如何实现异步的呢?

Libuv中文编程指南上如是说

libuv提供的文件操作和 socket operations 并不相同. 套接字操作使用了操作系统本身提供了非阻塞操作,而文件操作内部使用了阻塞函数,但是 libuv 是在线程池中调用这些函数, 并在应用程序需要交互时通知在事件循环中注册的监视器.

参考: http://www.infoq.com/cn/articles/nodejs-asynchronous-io

 

也就是说libuv除了借助于操作系统自身的分阻塞操作外,还使用了阻塞 + 多线程的实现方式。

下面通过分析libuv自带的例子来分析libuv异步的实现方式。

 

对于套接字操作,先看看libuv中自带的用例echo-server.c,其中这样的代码:

HELPER_IMPL(udp4_echo_server) {
 loop = uv_default_loop();
 
  if(udp4_echo_start(TEST_PORT))
   return 1;
 
 uv_run(loop, UV_RUN_DEFAULT);
  return 0;
}


这里uv_run里面包含了异步事件polling和处理的循环。

 

再看udp4_echo_start函数

static int udp4_echo_start(int port) {
  intr;
 
 server = (uv_handle_t*)&udpServer;
 serverType = UDP;
 
  r =uv_udp_init(loop, &udpServer);
//这里将loop赋值给了udpServer的loop成员,然后后续会对loop进行成员变量的值进行设定。在uv_run中会根据loop获取其在udpServer中的双链表成员所在的节点,进行处理然后删除。
  if(r) {
   fprintf(stderr, "uv_udp_init: %s\n", uv_strerror(r));
   return 1;
  }
 
  r =uv_udp_recv_start(&udpServer, echo_alloc, on_recv);
  if(r) {
   fprintf(stderr, "uv_udp_recv_start: %s\n", uv_strerror(r));
   return 1;
  }
 
 return 0;
}


 追寻代码有如下的调用过程:

uv_run->uv__run_pending-> uv__udp_io

 uv__udp_io[udp.c]->uv__udp_recvmsg->会调用handle的recv_cb实际上->用户设置的callback

用户的回调是被调用了,那设置套接字非阻塞呢?

 

再详细看看上面的例子,找到如下的代码处理流程:

[echo-server.c]udp4_echo_start->uv_udp_recv_start->[uv-common.c]uv__udp_recv_start->[udp.c] uv__udp_maybe_deferred_bind->uv__udp_bind->uv__socket->[core.c]调用uv__nonblock设置套接字非阻塞。。。

 

 

针对文件操作,虽然使用了阻塞函数,但是将阻塞操作放到了线程池中。

 

看看Test-fs.c中的例子,找到如下的函数调用链:

 

(创建线程池中的各个线程只需初始化一次

Test-fs.c->uv_fs_open->fs.c  INIT->POST ->uv__work_submit ->threadpool.c->uv__work_submit->uv_once->init_once->uv_thread_create)

 

Test-fs.c->uv_fs_open->fs.c  INIT->POST ->uv__work_submit-> post

在post中将work_req也就是uv__work挂到threadpool.c模块的staict双向链表wq中。

后续,线程池中的线程从wq中捞出任务进行处理。这样实际上是多线程进行了处理。处理完成之后会调用uv__fs_done,在uv__fs_done中调用用户设置的回调函数。


本人享有博客文章的版权,转载请标明出处http://blog.csdn.net/baidu20008


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值