readv() 和 writev()

Linux IO 高级函数:readv() 和 writev()

在Linux系统中,处理文件读写时,我们通常会用到 read()write() 函数。但是,当我们需要处理的内存分散在多个不同的缓冲区中时,传统的读写函数就显得有些力不从心。这时,我们可以使用 readv()write() 函数,这两个函数提供了更加高效的读写方式,它们可以一次性处理多个分散的内存区域。

readv() 和 writev() 函数详解

原型

#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);

作用

这两个函数允许我们一次性读取或写入多个分散的内存缓冲区,而不需要像传统方法那样多次调用 read()write() 函数。

参数

  • fd: 文件描述符,指定要读取或写入的文件。
  • iov: 指向 iovec 结构体的指针数组,每个 iovec 结构体描述了一个缓冲区。
  • iovcnt: iov 数组中的元素数量,即缓冲区的数量。

结构体 iovec

struct iovec {void *iov_base; /* 指向缓冲区的指针 */size_t iov_len; /* 缓冲区的大小 */
};

示例

想象一下,你有一个非常大的拼图,这个拼图由很多小块组成,每块都分布在不同的地方。传统的 read()write() 函数就像是一块块地搬运这些拼图块,而 readv()writev() 函数则像是用一个篮子一次性把所有拼图块都搬走。

例子

假设我们有一个文本文件input.txt,内容如下:

Hello, World!
This is a test file.

我们要读取这个文件的内容,并将其写入另一个文件中,但是文件内容要分两次读取,分别存放在两个不同的缓冲区中。

#include <stdio.h>
#include <stdlib.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>int main() {// 打开源文件和目标文件int fd_in = open("input.txt", O_RDONLY);if (fd_in == -1) {perror("Error opening input file");return 1;}int fd_out = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd_out == -1) {perror("Error opening output file");close(fd_in);return 1;}// 设置缓冲区char buffer1[10];char buffer2[25];// 创建iovec结构体数组struct iovec iov[2];iov[0].iov_base = buffer1;iov[0].iov_len = sizeof(buffer1);iov[1].iov_base = buffer2;iov[1].iov_len = sizeof(buffer2);// 循环读取并写入直到文件结束while (1) {// 读取文件内容到缓冲区ssize_t bytes_read = readv(fd_in, iov, 2);if (bytes_read == -1) {perror("readv failed");break;}if (bytes_read == 0) { // 文件结束break;}// 将缓冲区内容写入目标文件ssize_t total_written = 0;while (total_written < bytes_read) {ssize_t bytes_written = writev(fd_out, iov, 2);if (bytes_written == -1) {perror("writev failed");break;}total_written += bytes_written;// 更新iovec数组中的缓冲区位置和长度if (iov[0].iov_len <= bytes_written) {// 如果第一个缓冲区的内容已全部写入,调整iovecbytes_written -= iov[0].iov_len; // 已写入的字节数减去第一个缓冲区的大小iov[0].iov_base = NULL; // 将第一个缓冲区设为NULL,表示不再使用iov[0].iov_len = 0;iov[1].iov_base = (char *)iov[1].iov_base + bytes_written; // 移动第二个缓冲区的指针iov[1].iov_len -= bytes_written; // 减少第二个缓冲区的长度} else {// 如果第一个缓冲区还有剩余,调整第一个缓冲区的指针和长度iov[0].iov_base = (char *)iov[0].iov_base + bytes_written;iov[0].iov_len -= bytes_written;}}}// 关闭文件描述符close(fd_in);close(fd_out);return 0;
}

使用了一个循环来读取文件直到到达文件末尾(readv() 返回0)。在每次循环中,我们尽可能多地读取数据,并将这些数据写入到输出文件中。如果 writev() 写入的字节数少于 readv() 读取的字节数,说明数据没有完全写入,我们需要调整 iovec 数组,将未写入的数据再次传递给 writev() 函数,直到所有数据都被写入。

这种方法能够确保我们正确地处理分散在多个缓冲区中的数据
在这个例子中,我们首先定义了两个缓冲区 buffer1buffer2,然后创建了一个 iovec 数组,其中包含了这两个缓冲区的信息。我们使用 readv() 函数一次性从源文件读取内容到这两个缓冲区中。然后,我们使用 writev() 函数将这两个缓冲区的内容一次性写入目标文件。

这种方式不仅代码简洁,而且效率高,因为它减少了系统调用的次数,避免了多次在用户空间和内核空间之间切换上下文的开销。

通过使用 readv()writev() 函数,我们可以更加灵活和高效地处理分散在多个缓冲区中的数据,这在网络编程和多线程编程中尤其有用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/32528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产化平替

国产化替代&#xff0c;即国产替代&#xff0c;是指在关键技术和产品领域减少对外依赖&#xff0c;推动国内产业自主创新和升级&#xff0c;以实现关键技术和产品的国产化。在中国&#xff0c;国产化替代是国家战略的重要组成部分&#xff0c;旨在提高国家的自主创新能力和保障…

红队内网攻防渗透:内网渗透之内网对抗:信息收集篇SPN扫描DC定位角色区域定性服务探针安全防护凭据获取

红队内网攻防渗透 1. 内网信息收集1.1 域渗透的信息收集1.2域渗透的思路问题1.3 网络架构1.3.1 基本信息1.3.2 域内定位1.3.3 域内角色1.3.4 其他信息1.3.5 安全防护:1.3.6 凭据口令:1. 内网信息收集 #知识点: 1、基石框架篇-单域架构-权限控制-用户和网络 2、基石框架篇-…

Nginx负载均衡之Memcached缓存模块

Nginx 的 ngx_http_memcached_module 模块本身并没有提供缓存功能&#xff0c;它只是一个将用户请求转发到 Memcached 服务器的代理模块。 在以 Memcached 服务器为缓存应用的方案中&#xff0c;Memcached 作为内容缓存的存储服务器&#xff0c;用户通过 URL 为 Memcac…

古文字识别笔记

前置知识 部件&#xff1a;大部分的汉字是由若干组笔画结构拼合而成的&#xff0c;这些相对独立的笔画结构称为「部件」。 部件是大于基本笔画&#xff08;例如&#xff1a;点、横、撇、捺等&#xff09;而小于或等同于 偏旁 的结构单位。 例如「测」字有三个部件&#xff1a;…

Ubuntu换源

查看发行版本&#xff0c;记下来 cat /etc/issue 根据发行版本找到对应的配置文件copy起来 清华源 ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 阿里源 ubuntu镜像_ubuntu下载地址_ubuntu安装教程-阿里巴巴开源镜像站 (aliyun.com…

视觉新纪元:解码LED显示屏的视角、可视角、最佳视角的最终奥秘

在璀璨夺目的LED显示屏世界里&#xff0c;每一个绚烂画面的背后&#xff0c;都离不开三个关键概念&#xff1a;视角、可视角与最佳视角。这些术语不仅是衡量显示效果的重要标尺&#xff0c;也是连接观众与精彩内容的桥梁。让我们一起走进这场视觉盛宴&#xff0c;探索那些让LED…

基于langchain的开源大模型应用开发1

服务端grpc框架 server-grpc etc yaml配置及 internal 内部代码包 config yaml配置解析代码包 logic 逻辑实现包 server 服务连接处理 svc 上下文配置信息 proto proto文件 go.mod model go.sum main.go 主函数入口 逻辑代码处理 目前该应用的逻辑只有机器人对话功能&#xff…

【C++】——二叉搜索树(详解)

一 二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: ✨若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 ✨若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 …

Go 与 Java 字符编码选择:UTF-8 与 UTF-16 的较量

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

淦!在外包开发的三年给整废了,备战两个月终拿到Android阿里字节哈啰offer总结,阿里P6+这回稳了!

面试时候就感觉不靠谱&#xff0c;因为面试地点是位于近江附近的望江国际里面的温州银行&#xff0c;面试前网上搜了广电运通的信息&#xff0c;说是国企&#xff0c;所以我就硬着头皮接下 offer 了&#xff0c;没想到面试 Android 结果做的 C&#xff0c;而且也是驻场开发。 …

RocketMQ 和 Kafka 关于消息队列的推拉模式是怎么做的?

引言&#xff1a;在当今的大数据和分布式系统中&#xff0c;消息队列扮演着至关重要的角色&#xff0c;它们作为系统之间通信和数据传输的媒介&#xff0c;为各种场景下的数据流动提供了可靠的基础设施支持。在消息队列的设计中&#xff0c;推拉模式是两种常见的消息传递机制&a…

02 Shell编程之条件语句(补充实验部分)

1、双分支if语句的补充&#xff08;实验部分&#xff09; 例如&#xff0c;要编写一个连通性测试脚本&#xff0c;通过位置参数来提供目标主机地址&#xff0c;然后根据ping检测结果给出相应的提示 &#xff08;能ping通的&#xff0c;回馈一个信息&#xff1a;该服务器是开启…

钓鱼网站开发原理(社会工程学)

钓鱼网站开发原理&#xff08;社会工程学&#xff09; 一、课程简介1、课程大纲2、课程目标3、知识储备 二、钓鱼网站简介1、什么是钓鱼网站2、开发&原理 三、PHP环境搭建1、简介2、自动安装MySQL/apache/PHP3、安装navicat 四、PDO表单入库案例1、语法2、显示登录表单3、入…

浔川AI社宣布正式开创“浔川AI助手”——浔川AI社

这是浔川AI社的标志。 2024.6.22晚8点35分宣布&#xff0c;浔川AI社正式开创“浔川AI助手” 全面发展。 据浔川AI社报道称‘“浔川AI助手”内容包含全部&#xff0c;写作、聊天......都有。’ 让我们敬请期待&#xff01;

【JAVA】精致的五角星

输出的这幅图像中&#xff0c;一颗精致的金色五角星跃然于深红色背景之上&#xff0c;绽放出迷人的光彩。 要绘画这颗五角星&#xff0c;首先要了解五角星的构造和角度问题。我们可以分为内五边形&#xff0c;和外五边形。内五边形从他的中心到每个外点&#xff0c;连接起来&am…

ECharts词云图(案例一)+配置项详解

ECharts词云图&#xff08;案例一&#xff09;配置项详解 ECharts 是一款由百度团队开发的基于 JavaScript 的开源可视化图表库&#xff0c;它提供了丰富的图表类型&#xff0c;包括常见的折线图、柱状图、饼图等&#xff0c;以及一些较为特殊的图表&#xff0c;如词云图。从版…

带百分比的进度条控件(ProgressBar)源码

带百分比的进度条控件&#xff08;ProgressBar&#xff09;&#xff1a; 源码下载地址&#xff1a;https://download.csdn.net/download/wgxds/89472915

打破数据分析壁垒:SPSS复习必备(六)

一、数据的报表呈现 1.报表概述 (1).SPSS中的报表功能 1&#xff09;Base 模块 2&#xff09;Custom Tables 模块 3) Original Tables 模块 (2).报表的基本绘制步骤 步骤一:确定基本结构 步骤二:使用对话框绘制表格的基本结构 步骤三:完善细节 步骤四:添加其余变…

使用golang与智能合约进行交互

文章目录 使用golang与智能合约进行交互一、go-ethereum整体思路二、使用ERC-20实操1. 编译和部署erc-20合约2. 获取合约abi文件 (准备好合约的abi文件 abi.json)使用hardcat生成的json文件中获取3. 准备好solc和abigen工具4. 使用工具生成go代码5. go代码编写连接到区块链网…

Javase.图书管理系统基本框架

图书管理系统基本框架 1.核心类介绍2. book包详解2.1 Book 类2.1.2 代码展示2.1.2 代码解析 2.2 BookList 类2.2.2 代码展示2.2.2 代码解析 2.3Book类和BookList类的联系 3. 用户角色与管理3.1 User 类3.1.1 代码展示3.1.2 代码解析 3.2 adminUser 类3.2.1 代码展示3.2.2代码解…