首页 » 技术分享 » libuv学习笔记(11)

libuv学习笔记(11)

 

libuv学习笔记(11)

uv_stream_t数据结构以及相关函数

uv_stream_t提供一个抽象的双工通信通道。uv_stream_t是抽象类型,libuv提供3种流测实现:uv_tcp_t,uv_pipe_t以及uv_tty_t

数据结构:

typedef struct uv_stream_s uv_stream_t;
struct uv_stream_s {
  UV_HANDLE_FIELDS//uv_handle_t成员,此处不再展开
  //UV_STREAM_FIELDS宏展开如下:
  #define UV_STREAM_FIELDS                                                      
  /* number of bytes queued for writing */                                    
  size_t write_queue_size;//需要写入的数据量                                                   
  uv_alloc_cb alloc_cb;//内存分配回调函数                                    
  uv_read_cb read_cb;//读取数据回调函数                                                         
  /* private */                                                               
  //UV_STREAM_PRIVATE_FIELDS宏展开如下:
  unsigned int reqs_pending;                                                 
  int activecnt;//基于此流的活动请求计数                                                            
  uv_read_t read_req;//读操作请求                                                        
  union {                                                                     
    struct 
    {
     unsigned int write_reqs_pending;                                           
     uv_shutdown_t* shutdown_req;
    } conn;                              
    struct   
    { 
      uv_connection_cb connection_cb; 
    } serv;                             
  } stream;
};

uv_stream_t首先包含uv_handle_t的全部数据,因此uv_stream_t的指针可以转换为uv_handle_t的指针,剩下的数据通过宏UV_STREAM_PRIVATE_FIELDS定义

相关请求类型:

uv_connect_t,连接请求

struct uv_connect_s {
  UV_REQ_FIELDS//uv_req_t的数据,此处不再展开
  uv_connect_cb cb;//连接回调
  uv_stream_t* handle;//
  //UV_CONNECT_PRIVATE_FIELDS宏为空
};

uv_shutdown_t,关闭请求

struct uv_shutdown_s {
  UV_REQ_FIELDS//uv_req_t的数据,此处不再展开
  uv_stream_t* handle;
  uv_shutdown_cb cb;//关闭回调
  //UV_SHUTDOWN_PRIVATE_FIELDS宏为空
};

uv_write_t,写操作请求

struct uv_write_s {
  UV_REQ_FIELDS//uv_req_t的数据,此处不再展开
  uv_write_cb cb;//写回调
  uv_stream_t* send_handle;//发送对象
  uv_stream_t* handle;//
  //UV_WRITE_PRIVATE_FIELDS宏展开:
  int ipc_header;                                                             
  uv_buf_t write_buffer;//写内容                                                     
  HANDLE event_handle;                                                       
  HANDLE wait_handle;
};

以上三种请求都可以说是uv_req_t的子类,内部都有uv_stream_t对象的指针

相关函数

关闭流的写端。导出函数,在uv.h中声明,steam.c中定义

int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) 
{
  uv_loop_t* loop = handle->loop;
  //stream不可写,返回错误
  if (!(handle->flags & UV_HANDLE_WRITABLE)) {
    return UV_EPIPE;
  }
  //初始化请求
  uv_req_init(loop, (uv_req_t*) req);
  req->type = UV_SHUTDOWN;//类型
  req->handle = handle;//与流联系起来
  req->cb = cb;/回调函数

  handle->flags &= ~UV_HANDLE_WRITABLE;//去掉可写的标记
  handle->stream.conn.shutdown_req = req;
  handle->reqs_pending++;
  //REGISTER_HANDLE_REQ(loop, handle, req);宏展开
  do {                                                               
    //INCREASE_ACTIVE_COUNT((loop), (handle));展开
    do {                                                             
      if ((handle)->activecnt++ == 0) {                                
        uv__handle_start((handle));//第一个请求,开始handle                                     
      }                                                                  
      assert((handle)->activecnt > 0);                                  
    }  
    while (0)                     
    //uv__req_register((loop), (req));  展开:
    do {     
      //将请求添加到loop请求列表的尾端                                                                   
      QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue);          
    }                                                                        
    while (0)                             
  } 
  while (0);
  //将流添加到loop的关闭列表
  uv_want_endgame(loop, (uv_handle_t*)handle);
  return 0;
}

uv_run中调用uv_process_endgames对关闭流的处理:

      case UV_TCP:
        uv_tcp_endgame(loop, (uv_tcp_t*) handle);
        break;

      case UV_NAMED_PIPE:
        uv_pipe_endgame(loop, (uv_pipe_t*) handle);
        break;

      case UV_TTY:
        uv_tty_endgame(loop, (uv_tty_t*) handle);
        break;

之后的学习会对于具体对象的分析

uv_run调用uv_process_reqs对于shutdown请求的处理:

case UV_SHUTDOWN:
    //TCP的关闭请求不在此处处理,因为在tcp的关闭处理uv_tcp_endgame中会UNREGISTER_HANDLE_REQ
    assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE);
    uv_process_pipe_shutdown_req(
        loop,
        (uv_pipe_t*) ((uv_shutdown_t*) req)->handle,
        (uv_shutdown_t*) req);
    break;

三种请求,对于不同的流对象,会调用不同的实现,具体细节将在之后对应的流对象中分析

转载自原文链接, 如需删除请联系管理员。

原文链接:libuv学习笔记(11),转载请注明来源!

0