libuv 源码分析 结构体
2015-07-27 16:38
405 查看
libuv 的API是C风格的,很容易读。你可能觉得uv.h中暴露了太多的数据结构了,不够简洁,我想是因为libuv涵盖的内容非常的广泛,从网络,pipe,文件,终端等等,包罗万象。而且uv.h也不是接口的全部,还有两个头文件,uv-unix.h和uv-win.h,里面定义了操作系统specific的数据结构。其实,libuv已经对接口的简化做了一些努力,比如说,通过uv_write一个函数,我们可以写TCP,Pipe和tty。
因为libuv涵盖广泛,我们的目的只是为了了解它如何与nodejs,v8协调工作的,不会面面俱到。有几个重要的数据结构有必要先了解一下:
再来看loop,这是libuv里面最关键的数据结构了,一般会指定一个线程负责一个loop的处理,nodejs只使用了一个loop,由主线程负责对它进行处理。
了解了数据结构以后,程序怎么运行应该就大致有数了。来看一下执行过程。
函数poll()检查completion port,有事件发生的时候,产生一条request,插入到请求队列中。
函数uv_process_reqs()从消息队列中取出请求,处理请求。此函数在处理请求的过程中可能会调用用户传入的callback。
函数uv_process_endgames()清理已经关闭的handle,同时减掉refs。
转载链接:https://cnodejs.org/topic/4f571a16a680d212781ccf9f
因为libuv涵盖广泛,我们的目的只是为了了解它如何与nodejs,v8协调工作的,不会面面俱到。有几个重要的数据结构有必要先了解一下:
#define UV_HANDLE_FIELDS \ uv_loop_t* loop; uv_handle_type type; uv_close_cb close_cb; void* data; UV_HANDLE_PRIVATE_FIELDS /* The abstract base class of all handles. */ struct uv_handle_s { UV_HANDLE_FIELDS };uv_handle_s是其它handle的父类,比如说,uv_tcp_s就是它的子类,在那里你能找到socket。loop字段表明它属于哪个loop,handle里还有一些callback函数,异步调用通常会有两个参数,一个是handle,一个是callback函数,调用完成的时候,libuv会调用callback函数。data字段是留给使用者的,nodejs实现异步机制的时候会用到。
#define UV_REQ_FIELDS \ uv_req_type type; void* data; UV_REQ_PRIVATE_FIELDS /* Abstract base class of all requests. */ struct uv_req_s { UV_REQ_FIELDS };这是所有request的父类。loop维护一个request queue。data字段有时用来存放handle。
再来看loop,这是libuv里面最关键的数据结构了,一般会指定一个线程负责一个loop的处理,nodejs只使用了一个loop,由主线程负责对它进行处理。
struct uv_loop_s { UV_LOOP_PRIVATE_FIELDS uv_ares_task_t* uv_ares_handles_; uv_async_t uv_eio_want_poll_notifier; uv_async_t uv_eio_done_poll_notifier; uv_idle_t uv_eio_poller; uv_counters_t counters; uv_err_t last_err; void* data; };
了解了数据结构以后,程序怎么运行应该就大致有数了。来看一下执行过程。
#define UV_LOOP_ONCE(loop, poll) do { uv_update_time((loop)); uv_process_timers((loop)); /* Call idle callbacks if nothing to do. */ if ((loop)->pending_reqs_tail == NULL && (loop)->endgame_handles == NULL) { uv_idle_invoke((loop)); } uv_process_reqs((loop)); uv_process_endgames((loop)); if ((loop)->refs <= 0) { break; } uv_prepare_invoke((loop)); poll((loop), (loop)->idle_handles == NULL && (loop)->pending_reqs_tail == NULL && (loop)->endgame_handles == NULL && (loop)->refs > 0); uv_check_invoke((loop)); } while (0); #define UV_LOOP(loop, poll) while ((loop)->refs > 0) { UV_LOOP_ONCE(loop, poll) }
函数poll()检查completion port,有事件发生的时候,产生一条request,插入到请求队列中。
函数uv_process_reqs()从消息队列中取出请求,处理请求。此函数在处理请求的过程中可能会调用用户传入的callback。
函数uv_process_endgames()清理已经关闭的handle,同时减掉refs。
转载链接:https://cnodejs.org/topic/4f571a16a680d212781ccf9f
相关文章推荐
- Intents and Intent Filters用法
- 关于android library project里的assets
- 逻辑回归及美团逻辑回归总结
- hdu 5303 Delicious Apples(dp)
- html5中不再支持table的cellspacing和cellpadding属性
- hdoj 5294 Tricks Device 【最短路+ 最小割】
- 网络编程 TCP
- LeetCode Implement Stack using Queues
- 用JavaScript将Canvas内容转化成图片的方法
- error: No resource identifier found for attribute 'showAsAction' in package 'com.example.singlecheck
- Qt Creator 乱码问题
- GTK入门学习:Libglade 和 GtkBuilder 的区别使用
- 【bzoj3990】 SDOI2015排序 dfs搜索+剪枝
- idea 14 Error: Failed to create a child event loop
- HDUOJ 18岁生日 题目1201
- POJ 1007 DNA Sorting (归并排序)
- linux操作链路层的数据
- hdu 1203 I NEED A OFFER! dp
- GDB调试(一)
- hdu4770Lights Against Dudely 暴力搜索