Linux I/O 系统调用完整对比分析

1. 概述

Linux 提供了丰富的 I/O 系统调用,每种都有其特定的用途和优势。本文将详细分析这些系统调用的特点、使用场景和性能特征。

2. 系统调用详细对比

2.1 基本读写函数

pread/pwrite

#include <unistd.h>

// 位置指定读取/写入
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int int fd, const void *buf, size_t count, off_t offset);

特点

  • 原子操作(读取/写入 + 位置指定)
  • 不改变文件描述符的当前位置
  • 线程安全

read/write

#include <unistd.h>

// 基本读取/写入
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

特点

  • 最基本的 I/O 操作
  • 会改变文件描述符的当前位置
  • 相对简单但功能有限

2.2 分散/聚集 I/O 函数

preadv/pwritev

#include <sys/uio.h>

// 位置指定的分散读取/聚集写入
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);

preadv2/pwritev2

#define _GNU_SOURCE
#include <sys/uio.h>

// 带标志的增强版分散/聚集 I/O
ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt, 
                off_t offset, int flags);
ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, 
                 off_t offset, int flags);

2.3 资源限制函数

prlimit64

#include <sys/resource.h>

// 获取/设置进程资源限制
int prlimit64(pid_t pid, int resource, 
              const struct rlimit64 *new_limit, 
              struct rlimit64 *old_limit);

3. 功能对比表

函数位置指定分散/聚集标志控制原子性跨平台
read/write⚠️
pread/pwrite
readv/writev⚠️
preadv/pwritev
preadv2/pwritev2
prlimit64

4. 实际示例代码

4.1 基础读写对比

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

// 创建测试文件
void create_test_file(const char *filename) {
    int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("创建文件失败");
        return;
    }
    
    const char *content = 
        "Line 1: This is the first line of test data.\n"
        "Line 2: This is the second line of test data.\n"
        "Line 3: This is the third line of test data.\n"
        "Line 4: This is the fourth line of test data.\n"
        "Line 5: This is the fifth and final line.\n";
    
    write(fd, content, strlen(content));
    close(fd);
    printf("创建测试文件: %s\n", filename);
}

// read/pread 性能对比
void compare_basic_io(const char *filename) {
    int fd = open(filename, O_RDONLY);
    if (fd == -1) {
        perror("打开文件失败");
        return;
    }
    
    char buffer[100];
    ssize_t bytes_read;
    struct timespec start, end;
    
    printf("\n=== 基础 I/O 对比 ===\n");
    
    // 使用 read (会改变文件位置)
    printf("1. read 测试:\n");
    clock_gettime(CLOCK_MONOTONIC, &start);
    bytes_read = read(fd, buffer, 50);
    clock_gettime(CLOCK_MONOTONIC, &end);
    buffer[bytes_read] = '\0';
    printf("   读取 %zd 字节: %.30s...\n", bytes_read, buffer);
    printf("   当前文件位置: %ld\n", (long)lseek(fd, 0, SEEK_CUR));
    
    // 使用 pread (不改变文件位置)
    printf("2. pread 测试:\n");
    clock_gettime(CLOCK_MONOTONIC, &start);
    bytes_read = pread(fd, buffer, 50, 0);  // 从开头读取
    clock_gettime(CLOCK_MONOTONIC, &end);
    buffer[bytes_read] = '\0';
    printf("   读取 %zd 字节: %.30s...\n", bytes_read, buffer);
    printf("   文件位置仍为: %ld\n", (long)lseek(fd, 0, SEEK_CUR));
    
    close(fd);
}

// 分散/聚集 I/O 示例
void demonstrate_vector_io(const char *filename) {
    int fd = open(filename, O_RDONLY);
    if (fd == -1) {
        perror("打开文件失败");
        return;
    }
    
    printf("\n=== 分散/聚集 I/O 示例 ===\n");
    
    // 设置分散读取缓冲区
    char buffer1[20], buffer2[30], buffer3[25];
    struct iovec iov[3];
    
    iov[0].iov_base = buffer1;
    iov[0].iov_len = sizeof(buffer1) - 1;
    
    iov[1].iov_base = buffer2;
    iov[1].iov_len = sizeof(buffer2) - 1;
    
    iov[2].iov_base = buffer3;
    iov[2].iov_len = sizeof(buffer3) - 1;
    
    printf("分散读取设置:\n");
    printf("  缓冲区1: %zu 字节\n", iov[0].iov_len);
    printf("  缓冲区2: %zu 字节\n", iov[1].iov_len);
    printf("  缓冲区3: %zu 字节\n", iov[2].iov_len);
    
    // 使用 preadv 一次性读取到多个缓冲区
    ssize_t total_bytes = preadv(fd, iov, 3, 0);  // 从文件开头开始读取
    printf("总共读取: %zd 字节\n", total_bytes);
    
    if (total_bytes > 0) {
        buffer1[iov[0].iov_len] = '\0';
        buffer2[iov[1].iov_len] = '\0';
        buffer3[iov[2].iov_len] = '\0';
        
        printf("读取结果:\n");
        printf("  缓冲区1: %s\n", buffer1);
        printf("  缓冲区2: %s\n", buffer2);
        printf("  缓冲区3: %s\n", buffer3);
    }
    
    close(fd);
}

// 资源限制示例
void demonstrate_resource_limits() {
    printf("\n=== 资源限制示例 ===\n");
    
    struct rlimit64 limit;
    
    // 获取当前进程的文件大小限制
    if (prlimit64(0, RLIMIT_FSIZE, NULL, &limit) == 0) {
        printf("文件大小限制:\n");
        printf("  软限制: %lld\n", (long long)limit.rlim_cur);
        printf("  硬限制: %lld\n", (long long)limit.rlim_max);
    }
    
    // 获取内存限制
    if (prlimit64(0, RLIMIT_AS, NULL, &limit) == 0) {
        printf("虚拟内存限制:\n");
        if (limit.rlim_cur == RLIM64_INFINITY) {
            printf("  软限制: 无限制\n");
        } else {
            printf("  软限制: %lld 字节 (%.2f MB)\n", 
                   (long long)limit.rlim_cur,
                   (double)limit.rlim_cur / (1024 * 1024));
        }
        if (limit.rlim_max == RLIM64_INFINITY) {
            printf("  硬限制: 无限制\n");
        } else {
            printf("  硬限制: %lld 字节 (%.2f MB)\n", 
                   (long long)limit.rlim_max,
                   (double)limit.rlim_max / (1024 * 1024));
        }
    }
    
    // 获取打开文件数限制
    if (prlimit64(0, RLIMIT_NOFILE, NULL, &limit) == 0) {
        printf("文件描述符限制:\n");
        printf("  软限制: %lld\n", (long long)limit.rlim_cur);
        printf("  硬限制: %lld\n", (long long)limit.rlim_max);
    }
}

int main() {
    const char *test_file = "io_test_file.txt";
    
    printf("=== Linux I/O 系统调用对比分析 ===\n");
    
    // 创建测试文件
    create_test_file(test_file);
    
    // 基础 I/O 对比
    compare_basic_io(test_file);
    
    // 分散/聚集 I/O 示例
    demonstrate_vector_io(test_file);
    
    // 资源限制示例
    demonstrate_resource_limits();
    
    // 清理
    unlink(test_file);
    
    printf("\n=== 使用建议 ===\n");
    printf("选择指南:\n");
    printf("1. 简单读写: 使用 read/write\n");
    printf("2. 需要指定位置: 使用 pread/pwrite\n");
    printf("3. 多缓冲区操作: 使用 preadv/pwritev\n");
    printf("4. 需要高级控制: 使用 preadv2/pwritev2\n");
    printf("5. 资源限制管理: 使用 prlimit64\n");
    
    return 0;
}

4.2 性能基准测试

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <time.h>
#include <string.h>

#define ITERATIONS 10000
#define BUFFER_SIZE 1024

// 性能测试结构体
struct performance_test {
    const char *name;
    double (*test_func)(int fd, const char *filename);
};

// read 性能测试
double test_read_performance(int fd, const char *filename) {
    char buffer[BUFFER_SIZE];
    struct timespec start, end;
    
    clock_gettime(CLOCK_MONOTONIC, &start);
    
    for (int i = 0; i < ITERATIONS; i++) {
        lseek(fd, 0, SEEK_SET);  // 重置到文件开头
        read(fd, buffer, sizeof(buffer));
    }
    
    clock_gettime(CLOCK_MONOTONIC, &end);
    
    return (end.tv_sec - start.tv_sec) * 1000000.0 + 
           (end.tv_nsec - start.tv_nsec) / 1000.0;  // 微秒
}

// pread 性能测试
double test_pread_performance(int fd, const char *filename) {
    char buffer[BUFFER_SIZE];
    struct timespec start, end;
    
    clock_gettime(CLOCK_MONOTONIC, &start);
    
    for (int i = 0; i < ITERATIONS; i++) {
        pread(fd, buffer, sizeof(buffer), 0);  // 始终从位置0读取
    }
    
    clock_gettime(CLOCK_MONOTONIC, &end);
    
    return (end.tv_sec - start.tv_sec) * 1000000.0 + 
           (end.tv_nsec - start.tv_nsec) / 1000.0;  // 微秒
}

// readv 性能测试
double test_readv_performance(int fd, const char *filename) {
    char buffer1[256], buffer2[256], buffer3[256], buffer4[256];
    struct iovec iov[4];
    struct timespec start, end;
    
    // 设置分散读取
    iov[0].iov_base = buffer1;
    iov[0].iov_len = sizeof(buffer1);
    iov[1].iov_base = buffer2;
    iov[1].iov_len = sizeof(buffer2);
    iov[2].iov_base = buffer3;
    iov[2].iov_len = sizeof(buffer3);
    iov[3].iov_base = buffer4;
    iov[3].iov_len = sizeof(buffer4);
    
    clock_gettime(CLOCK_MONOTONIC, &start);
    
    for (int i = 0; i < ITERATIONS; i++) {
        lseek(fd, 0, SEEK_SET);
        readv(fd, iov, 4);
    }
    
    clock_gettime(CLOCK_MONOTONIC, &end);
    
    return (end.tv_sec - start.tv_sec) * 1000000.0 + 
           (end.tv_nsec - start.tv_nsec) / 1000.0;  // 微秒
}

// preadv 性能测试
double test_preadv_performance(int fd, const char *filename) {
    char buffer1[256], buffer2[256], buffer3[256], buffer4[256];
    struct iovec iov[4];
    struct timespec start, end;
    
    // 设置分散读取
    iov[0].iov_base = buffer1;
    iov[0].iov_len = sizeof(buffer1);
    iov[1].iov_base = buffer2;
    iov[1].iov_len = sizeof(buffer2);
    iov[2].iov_base = buffer3;
    iov[2].iov_len = sizeof(buffer3);
    iov[3].iov_base = buffer4;
    iov[3].iov_len = sizeof(buffer4);
    
    clock_gettime(CLOCK_MONOTONIC, &start);
    
    for (int i = 0; i < ITERATIONS; i++) {
        preadv(fd, iov, 4, 0);  // 始终从位置0读取
    }
    
    clock_gettime(CLOCK_MONOTONIC, &end);
    
    return (end.tv_sec - start.tv_sec) * 1000000.0 + 
           (end.tv_nsec - start.tv_nsec) / 1000.0;  // 微秒
}

void run_performance_benchmark() {
    const char *test_file = "benchmark_test.dat";
    int fd;
    
    printf("=== I/O 性能基准测试 ===\n");
    
    // 创建大测试文件
    fd = open(test_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd != -1) {
        char *buffer = malloc(1024 * 1024);  // 1MB 缓冲区
        if (buffer) {
            for (int i = 0; i < 10; i++) {  // 创建 10MB 文件
                write(fd, buffer, 1024 * 1024);
            }
            free(buffer);
        }
        close(fd);
    }
    
    // 打开文件进行读取测试
    fd = open(test_file, O_RDONLY);
    if (fd == -1) {
        perror("打开测试文件失败");
        return;
    }
    
    struct performance_test tests[] = {
        {"read", test_read_performance},
        {"pread", test_pread_performance},
        {"readv", test_readv_performance},
        {"preadv", test_preadv_performance},
        {NULL, NULL}
    };
    
    printf("%-10s %-15s %-15s\n", "函数", "耗时(微秒)", "平均耗时(纳秒)");
    printf("%-10s %-15s %-15s\n", "----", "----------", "--------------");
    
    for (int i = 0; tests[i].name; i++) {
        double total_time = tests[i].test_func(fd, test_file);
        double avg_time = total_time * 1000.0 / ITERATIONS;
        
        printf("%-10s %-15.2f %-15.2f\n", 
               tests[i].name, total_time, avg_time);
    }
    
    close(fd);
    unlink(test_file);
    
    printf("\n性能分析:\n");
    printf("1. pread 比 read 略慢 (位置指定开销)\n");
    printf("2. readv/preadv 在多缓冲区场景下更高效\n");
    printf("3. preadv2/pwritev2 提供更多控制选项\n");
    printf("4. 选择应基于具体使用场景\n");
}

int main() {
    printf("=== Linux I/O 系统调用完整对比分析 ===\n\n");
    
    // 运行性能基准测试
    run_performance_benchmark();
    
    printf("\n=== 详细功能对比 ===\n");
    printf("pread vs read:\n");
    printf("  • pread: 指定位置读取,不改变文件位置\n");
    printf("  • read: 顺序读取,会改变文件位置\n");
    printf("\n");
    
    printf("preadv vs pread:\n");
    printf("  • preadv: 分散读取到多个缓冲区\n");
    printf("  • pread: 读取到单个缓冲区\n");
    printf("\n");
    
    printf("preadv2 vs preadv:\n");
    printf("  • preadv2: 支持额外标志控制\n");
    printf("  • preadv: 基本的分散读取功能\n");
    printf("\n");
    
    printf("prlimit64:\n");
    printf("  • 用于获取和设置进程资源限制\n");
    printf("  • 支持 64 位资源限制值\n");
    printf("  • 可以操作其他进程的资源限制\n");
    
    printf("\n=== 实际应用建议 ===\n");
    printf("1. 日志文件读写: 使用 pread/pwrite\n");
    printf("2. 数据库存储引擎: 使用 preadv/pwritev\n");
    printf("3. 高性能网络服务: 使用 preadv2/pwritev2\n");
    printf("4. 系统资源管理: 使用 prlimit64\n");
    printf("5. 简单文件操作: 使用 read/write\n");
    
    return 0;
}

4.3 实际应用场景演示

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

// 日志文件读取示例
void log_file_reader_example() {
    printf("=== 日志文件读取场景 ===\n");
    
    // 创建模拟日志文件
    const char *log_file = "application.log";
    int fd = open(log_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    
    if (fd != -1) {
        const char *log_entries[] = {
            "2023-01-01 10:00:00 INFO Application started\n",
            "2023-01-01 10:00:01 DEBUG Loading configuration\n",
            "2023-01-01 10:00:02 WARN Low memory warning\n",
            "2023-01-01 10:00:03 ERROR Database connection failed\n",
            "2023-01-01 10:00:04 INFO Recovery attempt started\n"
        };
        
        for (int i = 0; i < 5; i++) {
            write(fd, log_entries[i], strlen(log_entries[i]));
        }
        close(fd);
    }
    
    // 使用 pread 读取特定时间段的日志
    fd = open(log_file, O_RDONLY);
    if (fd != -1) {
        char buffer[256];
        
        printf("读取最后一条日志记录:\n");
        // 从文件末尾附近读取
        ssize_t bytes_read = pread(fd, buffer, sizeof(buffer) - 1, 150);
        if (bytes_read > 0) {
            buffer[bytes_read] = '\0';
            printf("  %s", buffer);
        }
        
        close(fd);
    }
    
    unlink(log_file);
}

// 数据库页读取示例
void database_page_reader_example() {
    printf("\n=== 数据库页读取场景 ===\n");
    
    const char *db_file = "database_pages.dat";
    int fd = open(db_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    
    if (fd != -1) {
        // 创建模拟的数据库页
        char page_data[4096];
        for (int page = 0; page < 10; page++) {
            snprintf(page_data, sizeof(page_data), 
                    "Page %d: Database page content with ID=%d and timestamp=%ld\n",
                    page, page * 1000, time(NULL));
            write(fd, page_data, strlen(page_data));
        }
        close(fd);
    }
    
    // 使用 preadv 读取多个数据库页
    fd = open(db_file, O_RDONLY);
    if (fd != -1) {
        char page1[1024], page2[1024], page3[1024];
        struct iovec iov[3];
        
        // 设置分散读取
        iov[0].iov_base = page1;
        iov[0].iov_len = sizeof(page1) - 1;
        
        iov[1].iov_base = page2;
        iov[1].iov_len = sizeof(page2) - 1;
        
        iov[2].iov_base = page3;
        iov[2].iov_len = sizeof(page3) - 1;
        
        printf("使用 preadv 读取多个数据库页:\n");
        ssize_t total_bytes = preadv(fd, iov, 3, 0);  // 从开头读取
        printf("  总共读取: %zd 字节\n", total_bytes);
        
        if (total_bytes > 0) {
            page1[iov[0].iov_len] = '\0';
            page2[iov[1].iov_len] = '\0';
            page3[iov[2].iov_len] = '\0';
            
            printf("  页1: %.50s...\n", page1);
            printf("  页2: %.50s...\n", page2);
            printf("  页3: %.50s...\n", page3);
        }
        
        close(fd);
    }
    
    unlink(db_file);
}

// 网络数据包处理示例
void network_packet_processor_example() {
    printf("\n=== 网络数据包处理场景 ===\n");
    
    // 模拟网络数据包结构
    struct packet_header {
        uint32_t magic;
        uint16_t version;
        uint16_t type;
        uint32_t length;
        uint32_t checksum;
    } __attribute__((packed));
    
    struct packet_payload {
        char data[1024];
    };
    
    // 创建测试数据包文件
    const char *packet_file = "network_packets.dat";
    int fd = open(packet_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    
    if (fd != -1) {
        // 写入多个数据包
        for (int i = 0; i < 3; i++) {
            struct packet_header header = {
                .magic = 0x12345678,
                .version = 1,
                .type = i,
                .length = 100,
                .checksum = 0xABCDEF00 + i
            };
            
            char payload[1024];
            snprintf(payload, sizeof(payload), 
                    "Packet %d payload data with timestamp %ld", 
                    i, time(NULL));
            
            write(fd, &header, sizeof(header));
            write(fd, payload, strlen(payload) + 1);
        }
        close(fd);
    }
    
    // 使用 preadv2 读取数据包(如果支持)
    fd = open(packet_file, O_RDONLY);
    if (fd != -1) {
        struct packet_header headers[3];
        char payloads[3][256];
        struct iovec iov[6];  // 3个头部 + 3个载荷
        
        // 设置分散读取结构
        for (int i = 0; i < 3; i++) {
            iov[i*2].iov_base = &headers[i];
            iov[i*2].iov_len = sizeof(struct packet_header);
            
            iov[i*2+1].iov_base = payloads[i];
            iov[i*2+1].iov_len = sizeof(payloads[i]) - 1;
        }
        
        printf("使用分散读取处理网络数据包:\n");
        ssize_t bytes_read = preadv(fd, iov, 6, 0);
        printf("  读取字节数: %zd\n", bytes_read);
        
        if (bytes_read > 0) {
            for (int i = 0; i < 3; i++) {
                printf("  数据包 %d:\n", i);
                printf("    魔数: 0x%08X\n", headers[i].magic);
                printf("    版本: %d\n", headers[i].version);
                printf("    类型: %d\n", headers[i].type);
                printf("    长度: %d\n", headers[i].length);
                printf("    校验: 0x%08X\n", headers[i].checksum);
                payloads[i][iov[i*2+1].iov_len] = '\0';
                printf("    载荷: %.50s...\n", payloads[i]);
                printf("\n");
            }
        }
        
        close(fd);
    }
    
    unlink(packet_file);
}

// 资源限制管理示例
void resource_limit_management_example() {
    printf("\n=== 资源限制管理场景 ===\n");
    
    struct rlimit64 old_limit, new_limit;
    
    // 获取当前文件大小限制
    if (prlimit64(0, RLIMIT_FSIZE, NULL, &old_limit) == 0) {
        printf("当前文件大小限制:\n");
        if (old_limit.rlim_cur == RLIM64_INFINITY) {
            printf("  软限制: 无限制\n");
        } else {
            printf("  软限制: %lld 字节 (%.2f GB)\n", 
                   (long long)old_limit.rlim_cur,
                   (double)old_limit.rlim_cur / (1024 * 1024 * 1024));
        }
    }
    
    // 获取打开文件数限制
    if (prlimit64(0, RLIMIT_NOFILE, NULL, &old_limit) == 0) {
        printf("当前文件描述符限制:\n");
        printf("  软限制: %lld\n", (long long)old_limit.rlim_cur);
        printf("  硬限制: %lld\n", (long long)old_limit.rlim_max);
    }
    
    // 获取内存限制
    if (prlimit64(0, RLIMIT_AS, NULL, &old_limit) == 0) {
        printf("当前虚拟内存限制:\n");
        if (old_limit.rlim_cur == RLIM64_INFINITY) {
            printf("  软限制: 无限制\n");
        } else {
            printf("  软限制: %lld 字节 (%.2f GB)\n", 
                   (long long)old_limit.rlim_cur,
                   (double)old_limit.rlim_cur / (1024 * 1024 * 1024));
        }
    }
    
    printf("\n资源限制管理最佳实践:\n");
    printf("1. 合理设置文件大小限制防止磁盘填满\n");
    printf("2. 适当增加文件描述符限制支持高并发\n");
    printf("3. 监控内存使用防止内存泄漏\n");
    printf("4. 使用 prlimit64 动态调整资源限制\n");
}

int main() {
    printf("=== Linux I/O 系统调用应用场景演示 ===\n\n");
    
    // 日志文件读取场景
    log_file_reader_example();
    
    // 数据库页读取场景
    database_page_reader_example();
    
    // 网络数据包处理场景
    network_packet_processor_example();
    
    // 资源限制管理场景
    resource_limit_management_example();
    
    printf("\n=== 总结 ===\n");
    printf("I/O 系统调用选择指南:\n");
    printf("\n");
    printf("┌─────────────┬────────────────────────────────────┐\n");
    printf("│ 场景        │ 推荐函数                              │\n");
    printf("├─────────────┼────────────────────────────────────┤\n");
    printf("│ 简单读写    │ read/write                            │\n");
    printf("│ 位置指定    │ pread/pwrite                          │\n");
    printf("│ 多缓冲区    │ readv/writev                          │\n");
    printf("│ 位置+多缓冲 │ preadv/pwritev                        │\n");
    printf("│ 高级控制    │ preadv2/pwritev2                      │\n");
    printf("│ 资源限制    │ prlimit64                             │\n");
    printf("└─────────────┴────────────────────────────────────┘\n");
    printf("\n");
    printf("性能优化建议:\n");
    printf("1. 批量操作减少系统调用次数\n");
    printf("2. 合理选择缓冲区大小\n");
    printf("3. 使用位置指定避免文件位置移动\n");
    printf("4. 分散/聚集 I/O 减少内存拷贝\n");
    printf("5. 合理设置资源限制防止系统过载\n");
    
    return 0;
}

5. 编译和运行说明

# 编译示例程序
gcc -o io_comparison_example1 example1.c
gcc -o io_comparison_example2 example2.c
gcc -o io_comparison_example3 example3.c

# 运行示例
./io_comparison_example1
./io_comparison_example2
./io_comparison_example3

6. 系统要求检查

# 检查内核版本
uname -r

# 检查 glibc 版本
ldd --version

# 检查系统调用支持
grep -E "(pread|pwrite|prlimit)" /usr/include/asm/unistd_64.h

# 查看文件系统性能
hdparm -Tt /dev/sda  # 硬盘性能测试

7. 重要注意事项

  1. 原子性: pread/pwrite 操作是原子的
  2. 位置独立: 不改变文件描述符的当前位置
  3. 错误处理: 始终检查返回值和 errno
  4. 内存对齐: 在某些架构上有对齐要求
  5. 权限检查: 确保有足够的权限进行操作
  6. 资源清理: 及时关闭文件描述符

8. 最佳实践总结

// 安全的 I/O 操作封装
ssize_t safe_pread(int fd, void *buf, size_t count, off_t offset) {
    if (fd < 0 || !buf || count == 0) {
        errno = EINVAL;
        return -1;
    }
    
    ssize_t result;
    do {
        result = pread(fd, buf, count, offset);
    } while (result == -1 && errno == EINTR);
    
    return result;
}

// 安全的分散读取封装
ssize_t safe_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
    if (fd < 0 || !iov || iovcnt <= 0 || iovcnt > IOV_MAX) {
        errno = EINVAL;
        return -1;
    }
    
    ssize_t result;
    do {
        result = preadv(fd, iov, iovcnt, offset);
    } while (result == -1 && errno == EINTR);
    
    return result;
}

// 资源限制检查
int check_resource_limits() {
    struct rlimit64 limit;
    
    // 检查文件大小限制
    if (prlimit64(0, RLIMIT_FSIZE, NULL, &limit) == 0) {
        if (limit.rlim_cur != RLIM64_INFINITY && limit.rlim_cur < 1024 * 1024) {
            printf("警告: 文件大小限制过小 (%lld 字节)\n", 
                   (long long)limit.rlim_cur);
        }
    }
    
    // 检查文件描述符限制
    if (prlimit64(0, RLIMIT_NOFILE, NULL, &limit) == 0) {
        if (limit.rlim_cur < 1024) {
            printf("警告: 文件描述符限制过小 (%lld)\n", 
                   (long long)limit.rlim_cur);
        }
    }
    
    return 0;
}

这些示例全面展示了 Linux I/O 系统调用的功能特点、使用方法和实际应用场景,帮助开发者根据具体需求选择合适的 I/O 操作方式。

此条目发表在未分类分类目录。将固定链接加入收藏夹。

发表回复

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