利用标准库容器封装char,实现自动增长的缓冲区


缓冲区的自动增长的实现原理


web服务器之缓冲区的自动增长的实现原理
socket通信中的分散读和集中写





分散读示例

在Linux下,readv系统调用可以实现分散读(scattered read),即从一个文件描述符中读取数据到多个缓冲区中。下面是一个使用readv的C++示例,演示了如何从文件中分散读取数据:

#include <iostream>  
#include <fcntl.h>  
#include <unistd.h>  
#include <vector>  
#include <sys/uio.h>  
  
int main() {  
    // 打开文件  
    int fd = open("example.txt", O_RDONLY);     // 文件内容:hello,world
    if (fd == -1) {  
        std::cerr << "Failed to open file" << std::endl;  
        return 1;  
    }  
  
    // 定义要读取的缓冲区  
    /* Structure for scatter/gather I/O.  */
    /*
        struct iovec
        {
            void *iov_base;	// Pointer to data.
            size_t iov_len;	// Length of data.
        };
    */
    std::vector<struct iovec> buffers;  
    buffers.emplace_back();  
    buffers.back().iov_base = (char*)malloc(5);  
    buffers.back().iov_len = 5;  
  
    buffers.emplace_back();  
    buffers.back().iov_base = (char*)malloc(1);  
    buffers.back().iov_len = 1;  

    buffers.emplace_back();  
    buffers.back().iov_base = (char*)malloc(5);  
    buffers.back().iov_len = 5;  
  
    // 读取数据  
    ssize_t bytesRead = readv(fd, buffers.data(), buffers.size());  
    if (bytesRead == -1) {  
        std::cerr << "Failed to read data" << std::endl;  
        close(fd);  
        return 1;  
    }

    std::cout << "bytesRead = " << bytesRead << std::endl;

    // 输出读取的数据  
    for (const auto& buffer : buffers) {  
        std::cout.write((char*)buffer.iov_base, buffer.iov_len) << std::endl;  
    }  
  
    // 释放缓冲区并关闭文件  
    for (auto& buffer : buffers) {  
        free((char*)buffer.iov_base);  
    }  
    close(fd);  
  
    return 0;  
}

/*
输出:
bytesRead = 11
hello
,
world
*/

这段代码主要演示了如何使用 readv 函数从文件中进行分散读取,也就是从一个文件中读取数据到多个缓冲区中。下面是对这段代码的详细解释:

  1. 头文件引入

    • <iostream>: 用于C++标准输入输出。
    • <fcntl.h><unistd.h>: 这两个头文件包含了文件操作(如 openclose)和低级I/O操作(如 readv)的函数声明。
    • <vector>: C++标准库中的动态数组。
    • <sys/uio.h>: 包含 iovec 结构的定义,这个结构用于 readvwritev 函数的分散/聚集I/O。
  2. 主函数

    • 打开文件:使用 open 函数打开名为 "example.txt" 的文件,并设置其为只读模式。如果文件打开失败,程序将输出错误消息并返回1。

    • 定义要读取的缓冲区:使用 std::vector 来存储多个 iovec 结构。每个 iovec 结构代表一个缓冲区,其中 iov_base 是指向数据的指针,iov_len 是数据的长度。

      • 第一个缓冲区大小为5,用于存储 "hello" 中的前5个字符。
      • 第二个缓冲区大小为1,用于存储逗号 ","。
      • 第三个缓冲区大小为5,用于存储 "world" 中的5个字符。
    • 读取数据:使用 readv 函数从文件中读取数据。这个函数将从文件描述符 fd 指向的文件中读取数据,并将数据分散到 buffers 向量中的多个缓冲区中。readv 返回实际读取的字节数。如果读取失败,程序将输出错误消息,关闭文件并返回1。

    • 输出读取的数据:遍历 buffers 向量,并使用 std::cout.write 函数将每个缓冲区中的数据输出到标准输出。

    • 释放缓冲区并关闭文件:在输出数据后,使用 free 函数释放每个缓冲区分配的内存,并使用 close 函数关闭文件。

  3. 输出

    • 输出实际读取的字节数,即11。
    • 接着输出从文件中读取的内容,即 "hello\n,\nworld\n"。每个缓冲区的内容后面都有一个换行符,这是因为 std::cout.write 函数不会自动添加换行符,所以在每次写入后都需要手动添加。
posted @   guanyubo  阅读(116)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示