网络套接字iovec API有什么用

结论先行

  • 对于面向连接的工作模式,可以节省系统调用API的次数
  • 可以让报文缓冲区分配和管理更具弹性
    • 适合的场景将节省一次用户空间内、不必要的拷贝

前言

很久以前就知道网络Socket套接字API存在iovec接口,曾以为它能够实现零拷贝,但是,简单分析后,发现iovec指向的也是用户空间的地址,所以,认为它没什么太大价值,不能够实现用户空间到内核空间的零拷贝,就没有继续深入学习研究下去。

直到最近研究recvmmsg接口,以及伴随一直思考的的性能优化任务,突然对iovec产生了理解的电火花,用网络套接字iovec类接口,可以对适用的场景节省一次不必要的数据拷贝工作!

下面列举一个比较容易理解的例子

不知道IOVEC接口前

简而言之,例子就是组件API对上层提供发送网络报文接口,但对于接口参数传递的报文数据,又必须在入参数据前加上扩展头后,才能发送出去,而且不得不做!

  • 不使用iovec
    • 组件API实现将不得不通过构造一个完整的报文数据区,构造新包头,拷贝入参报文数据后,将此新报文数据区发送出去
    • 与上层API存在工作协议,在入参报文数据区前能够提供前缀的工作空间,以便于组件API实现可以在不拷贝入参报文缓冲区的情况下,添加了新包头后进行发送

但是,在知道了iovec类接口后,就不需要这么复杂了!!!

scatter/gather操作

  • 流模式,按iovec次序分散和收集
  • 报文模式,将一次收发dgram,按iovec次序分散和收集

以前笔记积累过网络操作报文缓冲区预留前后缀空间的最佳实践

具体例子

反例

extern struct T_GTPUHeader;

int sendMessageToPeer(..., const char* data, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen)
{
  unsigned char abEncodeBuf[MAX_PKG];
  
  struct T_GTPUHeader*  ptGTPUHeader = (T_GTPUHeader*)abEncodeBuf;
  // Use the input paras or some global info
  fillGTPUHeader(ptGTPUHeader, ...);
  
  // 多一次用户空间内的拷贝
  memcpy(abEncodeBuf + sizeof(struct T_GTPUHeader), data, len);
  
  // get sockfd by some mean
  return sendto(sockfd, abEncodeBuf, sizeof(struct T_GTPUHeader) + len, flags, dest_addr, addrlen);
}

正例

extern struct T_GTPUHeader;

int sendMessageToPeer_iovec(..., const char* data, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen)
{
  
  struct T_GTPUHeader  tGTPUHeader = {};
  // Use the input paras or some global info
  fillGTPUHeader(&tGTPUHeader, ...);

  // Use iovec api
  struct iovec vec[2];
  vec[0].iov_base = &tGTPUHeader;
  vec[0].iov_len  = sizeof(tGTPUHeader);
  vec[1].iov_base = data;
  vec[1].iov_len  = len;
  
  struct msghdr  msghdr = {};
  msghdr.msg_name    = dest_addr;
  msghdr.msg_namelen = addrlen;
  msghdr.msg_iov     = &vec;        /* scatter/gather array */
  msghdr.msg_iovlen  = sizeof(vec)/sizeof(vec[0]);  /* # elements in msg_iov */

  // get sockfd by some mean
  return sendmsg(sockfd, &msghdr, flags);
}

图解

发送

网络套接字iovec API有什么用_第1张图片

接收

网络套接字iovec API有什么用_第2张图片

iovec可支持更自由的内存管理

参考

  • gnu scatter-gather operations
  • man socket sendmsg

你可能感兴趣的:(ACE,网络,iovec,网络套接字,Socket,节省拷贝)