pwritev2系统调用及示例

pwritev2 函数

1. 函数介绍

pwritev2 是 pwritev 的增强版本,支持额外的标志参数,提供更多的控制选项。与 preadv2 配对使用。

pwritev2系统调用及示例-CSDN博客

2. 函数原型

#define _GNU_SOURCE
#include <sys/uio.h>
ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);

3. 功能

将多个缓冲区中的数据写入到文件的指定位置,并支持额外的控制标志。

4. 参数

  • int fd: 文件描述符
  • *const struct iovec iov: iovec结构体数组
  • int iovcnt: iov数组元素个数
  • off_t offset: 文件偏移量
  • int flags: 控制标志

5. 返回值

  • 成功: 返回实际写入的总字节数
  • 失败: 返回-1,并设置errno

6. 相似函数,或关联函数

  • pwritev: 基本版本
  • preadv2: 对应的读取函数
  • write: 基本写入函数

7. 示例代码

#define _GNU_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

/**
 * 演示pwritev2的基本使用
 */
int demo_pwritev2_basic() {
    int fd;
    struct iovec iov[3];
    ssize_t bytes_written;
    
    printf("=== pwritev2 基本使用示例 ===\n");
    
    // 准备要写入的数据
    char part1[] = "Part one of the data\n";
    char part2[] = "Part two of the data ";
    char part3[] = "and part three.\n";
    
    // 创建测试文件
    fd = open("test_pwritev2.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("创建测试文件失败");
        return -1;
    }
    
    // 设置iovec数组
    iov[0].iov_base = part1;
    iov[0].iov_len = strlen(part1);
    iov[1].iov_base = part2;
    iov[1].iov_len = strlen(part2);
    iov[2].iov_base = part3;
    iov[2].iov_len = strlen(part3);
    
    // 使用pwritev2写入数据(flags设为0表示默认行为)
    bytes_written = pwritev2(fd, iov, 3, 0, 0);
    if (bytes_written == -1) {
        if (errno == ENOSYS) {
            printf("系统不支持 pwritev2 函数\n");
            close(fd);
            unlink("test_pwritev2.txt");
            return 0;
        }
        perror("pwritev2 失败");
        close(fd);
        unlink("test_pwritev2.txt");
        return -1;
    }
    
    printf("pwritev2 成功写入 %zd 字节\n", bytes_written);
    
    // 读取并验证写入的数据
    char buffer[256];
    lseek(fd, 0, SEEK_SET);
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
    if (bytes_read > 0) {
        buffer[bytes_read] = '\0';
        printf("\n写入的文件内容:\n%s", buffer);
    }
    
    close(fd);
    unlink("test_pwritev2.txt");
    return 0;
}

/**
 * 演示pwritev2的追加写入特性
 */
int demo_pwritev2_append() {
    int fd;
    struct iovec iov[2];
    ssize_t bytes_written;
    
    printf("\n=== pwritev2 追加写入示例 ===\n");
    
    // 创建初始文件
    fd = open("append_test.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("创建测试文件失败");
        return -1;
    }
    
    const char *initial_data = "Initial data in the file\n";
    write(fd, initial_data, strlen(initial_data));
    close(fd);
    
    // 使用pwritev2进行追加写入
    fd = open("append_test.txt", O_WRONLY);
    if (fd == -1) {
        perror("打开文件失败");
        return -1;
    }
    
    char new_data1[] = "Appended data ";
    char new_data2[] = "using pwritev2\n";
    
    iov[0].iov_base = new_data1;
    iov[0].iov_len = strlen(new_data1);
    iov[1].iov_base = new_data2;
    iov[1].iov_len = strlen(new_data2);
    
    // 注意:RWF_APPEND 标志需要内核支持
    bytes_written = pwritev2(fd, iov, 2, 0, RWF_APPEND);
    if (bytes_written == -1) {
        if (errno == ENOSYS || errno == EINVAL) {
            printf("系统不支持 RWF_APPEND 标志,使用普通写入\n");
            bytes_written = pwritev2(fd, iov, 2, 0, 0);
        } else {
            perror("pwritev2 追加写入失败");
            close(fd);
            unlink("append_test.txt");
            return -1;
        }
    }
    
    if (bytes_written > 0) {
        printf("追加写入成功,写入 %zd 字节\n", bytes_written);
    }
    
    // 显示最终文件内容
    char buffer[256];
    lseek(fd, 0, SEEK_SET);
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
    if (bytes_read > 0) {
        buffer[bytes_read] = '\0';
        printf("\n最终文件内容:\n%s", buffer);
    }
    
    close(fd);
    unlink("append_test.txt");
    return 0;
}

int main() {
    printf("pwritev2 需要 Linux 4.6+ 内核支持\n");
    
    if (demo_pwritev2_basic() == 0) {
        demo_pwritev2_append();
        printf("\n=== pwritev2 使用总结 ===\n");
        printf("优点:支持额外控制标志,功能更强大\n");
        printf("注意:需要较新内核版本支持\n");
    }
    return 0;
}
此条目发表在linux文章分类目录。将固定链接加入收藏夹。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注