Nodejs事件引擎libuv源码剖析之:请求(request)结构的设计剖析

Posted chenyang_yao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nodejs事件引擎libuv源码剖析之:请求(request)结构的设计剖析相关的知识,希望对你有一定的参考价值。

     声明:本文为原创博文,转载请注明出处。   

     在libuv中,请求(request)代表一个用户向libuv发出的指令,比如uv_connect_s就表示一个tcp的连接请求、uv_work_s代表要递交给libuv线程池执行的任务请求、uv_write_s代表一个写请求。

     类似于上一篇讲句柄(handle)那样,请求也由一个抽象基类和相应的子类组成,这个基类就是uv_req_s,下面来看一下它的定义:

 1 /* Abstract base class of all requests. */
 2 struct uv_req_s {
 3   /* public */                                                                \\
 4   void* data;                                                                 \\
 5   /* read-only */                                                             \\
 6   uv_req_type type;                                                           \\
 7   /* private */                                                               \\
 8   void* active_queue[2];                                                      \\
 9   void* reserved[4];                                                          \\
10 };

     其中,data可以用来携带任何类型的用户数据;type为该请求的类型,其取值可以为:

 1 typedef enum {
 2             UV_UNKNOWN_REQ = 0,
 3             UV_REQ,
 4             UV_CONNECT,
 5             UV_WRITE,
 6             UV_SHUTDOWN,
 7             UV_UDP_SEND,
 8             UV_FS,
 9             UV_WORK,
10             UV_GETADDRINFO,
11             UV_GETNAMEINFO,
12             UV_REQ_TYPE_PRIVATE,
13             UV_REQ_TYPE_MAX,
14  } uv_req_type;

     active_queue是一个队列节点,该请求会通过该节点将自己挂载到所绑定的loop中的active_reqs队列上;该操作(添加、删除)主要通过uv__req_register和uv__req_unregister两个宏定义实现:

 1 #define uv__req_register(loop, req)                                           \\
 2   do {                                                                        \\
 3     QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue);            \\
 4   }                                                                           \\
 5   while (0)
 6 
 7 #define uv__req_unregister(loop, req)                                         \\
 8   do {                                                                        \\
 9     assert(uv__has_active_reqs(loop));                                        \\
10     QUEUE_REMOVE(&(req)->active_queue);                                       \\
11   }                                                                           \\
12   while (0)

     用户并不会直接使用以上两个宏,而是会使用uv__req_init来初始化一个请求,该函数实现如下:

 void uv__req_init(uv_loop_t* loop,
                         uv_req_t* req,
                         uv_req_type type) {
  uv_req_init(loop, req);
  req->type = type;
  uv__req_register(loop, req);//注册这个req
}

    请求并不会单独被处理,一个请求除了会被挂载在loop->active_reqs上,每个req都会被赋值给相应的句柄中的成员。下面画图libuv中各个请求中的关系,其中横线以上的为抽象基类,横线以下都是uv_req_t的直接子类。 

 

以上是关于Nodejs事件引擎libuv源码剖析之:请求(request)结构的设计剖析的主要内容,如果未能解决你的问题,请参考以下文章

nodejs怎么同步查询数据

nodejs运行机制

在nodejs中事件循环分析

浅析libuv源码-node事件轮询解析

Scrapy源码剖析之自定义Scrapy框架

Nodejs的运行原理-libuv篇