readv和writev函数

参考:《UNIX 网络编程 · 卷1 : 套接字联网API》
这两个函数类似于 read 和 write 函数,但是其允许单个系统调用读入或写出多个缓冲区。这些操作分别称为分散读和集中写,因为来自读操作的输入数据被分散到多个应用缓冲区中,而来自多个应用缓冲区的输出数据集则被几种提供给单个写操作。其函数签名如下:

#include <sys/uio.h>
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

返回值:成功为读入或写出的字节数,出错为 -1 并设置相应的 errno。

这两个函数的第二个参数都是指向某个 iovec 结构的一个指针,其中 iovec 结构在头文件 <sys/uio.h> 中定义:

struct iovec
{
    void  *iov_base;    /* Starting address */
    size_t iov_len;     /* Number of bytes to transfer */
};

其中iov_base为缓冲区首地址,iov_len为缓冲区长度,参数 iovcnt 指定了 iovec 的个数。

iovec 结构数组中元素的数目存在某个限制,具体取决于实现,通常头文件 <sys/uio.h> 中定义 IOV_MAX 常值为 1024 个。

iovec结构图

readv 函数则将读入的数据按上述同样顺序散布到缓冲区中。readv 总是先填满一个缓冲区,然后再填写下一个。

readv 和 writev 这两个函数可以用于任何描述符,而不仅限于套接字。另外 writev 是一个原子操作,意味着对于类似 UDP 协议,一次 writev 调用只产生单个 UDP 数据报。

之前我们说过 TCP_NODELAY 套接字选项,一个 4 字节的 write 和一个 396 字节的 write 可能触发 Nagle 算法,首选方法之一是针对这两个缓冲区调用 writev。

我们应当用尽量少的系统调用次数来完成任务。如果我们只写少量的数据,将会发现自己复制数据然后使用一次 write 会比用 writev 更合算。但也可能发现,我们管理自己的分段缓冲区会增加程序额外的复杂性成本,所以从性能成本的角度来看不合算。

实例如下:

int main(void)
{
    char buf1[5], buf2[10];
    struct iovec iov[2];
    iov[0].iov_base = buf1;
    iov[0].iov_len = 5;
    iov[1].iov_base = buf2;
    iov[1].iov_len = 10;

    int fd = open("a.txt", O_RDWR);
    if (fd < 0)
    {
        perror("open");
        return -1;
    }
    int rsize = readv(fd, iov, 2);
    printf("rsize = %d\n", rsize);

    close(fd);

    fd = open("b.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    if (fd < 0)
    {
        perror("open");
        return -1;
    }

    int wsize = writev(fd, iov, 2);
    printf("wsize = %d\n", wsize);

    close(fd);
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值