You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多进程文件操作问题:如何实现进程接续读取文件内容

实现父子进程指定位置接续读取文件

我来帮你解决这个问题——你现在遇到的核心问题是fork后父子进程共享文件表的偏移量:默认情况下父进程读了内容后,子进程会从父进程停下的位置继续读,但你需要子进程跳到指定的第5行开始,这就需要手动控制文件偏移量,或者让父子进程各自独立管理文件访问位置。

下面分两种可行的方案来实现你的需求:

方案1:共享文件描述符,子进程手动定位偏移量

当你在父进程中打开文件后再fork子进程,父子进程的文件描述符指向同一个底层文件表,偏移量是共享的。但我们可以让子进程通过lseek()函数手动跳转到目标行的起始位置,再开始读取。

示例代码(exec.c)

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>

#define BUFFER_SIZE 256

// 辅助函数:定位到目标行的起始位置
off_t seek_to_target_line(int fd, int target_line) {
    char buffer[BUFFER_SIZE];
    ssize_t bytes_read;
    int current_line = 0;

    // 先将偏移量重置到文件开头
    lseek(fd, 0, SEEK_SET);

    while ((bytes_read = read(fd, buffer, BUFFER_SIZE)) > 0) {
        for (int i = 0; i < bytes_read; i++) {
            if (buffer[i] == '\n') {
                current_line++;
                // 找到目标行的前一行末尾,此时偏移量就是目标行开头
                if (current_line == target_line - 1) {
                    return lseek(fd, 0, SEEK_CUR);
                }
            }
        }
    }
    // 找不到目标行则返回文件末尾
    return lseek(fd, 0, SEEK_END);
}

int main() {
    int fd = open("sample.txt", O_RDONLY);
    if (fd == -1) {
        perror("Failed to open file");
        return 1;
    }

    char buffer[BUFFER_SIZE];
    ssize_t bytes_read;
    int lines_read = 0;

    // 父进程读取前两行
    printf("Parent process reading first 2 lines:\n");
    while ((bytes_read = read(fd, buffer, BUFFER_SIZE)) > 0 && lines_read < 2) {
        for (int i = 0; i < bytes_read; i++) {
            putchar(buffer[i]);
            if (buffer[i] == '\n' && ++lines_read == 2) break;
        }
        if (lines_read == 2) break;
    }
    printf("\n");

    // 创建子进程
    pid_t pid = fork();
    if (pid == -1) {
        perror("Failed to fork");
        close(fd);
        return 1;
    } else if (pid == 0) {
        // 子进程定位到第5行开头,读取4行
        printf("Child process reading lines 5-8:\n");
        off_t target_offset = seek_to_target_line(fd, 5);
        if (target_offset == -1) {
            perror("Failed to seek to target line");
            close(fd);
            return 1;
        }

        int lines_read_child = 0;
        while ((bytes_read = read(fd, buffer, BUFFER_SIZE)) > 0 && lines_read_child < 4) {
            for (int i = 0; i < bytes_read; i++) {
                putchar(buffer[i]);
                if (buffer[i] == '\n' && ++lines_read_child == 4) break;
            }
        }
        printf("\n");
        close(fd);
        return 0;
    } else {
        // 父进程等待子进程完成
        wait(NULL);
        close(fd);
        return 0;
    }
}

方案2:父子进程各自独立打开文件

如果不想共享文件偏移量,可以让父子进程分别打开文件,这样各自的文件表完全独立,偏移量互不影响。父进程读取前两行,子进程自行定位到第5行开始读取。

示例代码(test.c)

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>

#define BUFFER_SIZE 256

// 通用读取函数:从start_line开始读取num_lines行
void read_specified_lines(int fd, int start_line, int num_lines) {
    char buffer[BUFFER_SIZE];
    ssize_t bytes_read;
    int current_line = 0;

    // 先跳过start_line-1行
    lseek(fd, 0, SEEK_SET);
    while ((bytes_read = read(fd, buffer, BUFFER_SIZE)) > 0 && current_line < start_line - 1) {
        for (int i = 0; i < bytes_read; i++) {
            if (buffer[i] == '\n' && ++current_line == start_line - 1) break;
        }
    }

    // 读取目标行数
    printf("Reading lines %d to %d:\n", start_line, start_line + num_lines - 1);
    int lines_read = 0;
    while ((bytes_read = read(fd, buffer, BUFFER_SIZE)) > 0 && lines_read < num_lines) {
        for (int i = 0; i < bytes_read; i++) {
            putchar(buffer[i]);
            if (buffer[i] == '\n' && ++lines_read == num_lines) break;
        }
    }
    printf("\n");
}

int main() {
    pid_t pid = fork();
    if (pid == -1) {
        perror("Failed to fork");
        return 1;
    } else if (pid == 0) {
        // 子进程独立打开文件,读取5-8行
        int fd = open("sample.txt", O_RDONLY);
        if (fd == -1) {
            perror("Child: Failed to open file");
            return 1;
        }
        read_specified_lines(fd, 5, 4);
        close(fd);
        return 0;
    } else {
        // 父进程独立打开文件,读取1-2行
        int fd = open("sample.txt", O_RDONLY);
        if (fd == -1) {
            perror("Parent: Failed to open file");
            wait(NULL);
            return 1;
        }
        read_specified_lines(fd, 1, 2);
        close(fd);
        wait(NULL);
        return 0;
    }
}

测试用sample.txt示例

Line 1: This is the first line
Line 2: This is the second line
Line 3: This is the third line
Line 4: This is the fourth line
Line 5: This is the fifth line
Line 6: This is the sixth line
Line 7: This is the seventh line
Line 8: This is the eighth line
Line 9: This is the ninth line
Line 10: This is the tenth line

关键注意点

  • 文件偏移量共享机制:fork后父子进程的文件描述符指向同一个文件表,所以偏移量会同步变化——这就是你之前未达预期的核心原因。
  • lseek()的通用性:示例中用逐行遍历的方式定位目标行,适合每行长度不固定的场景;如果你的文件每行长度固定,也可以直接计算字节偏移量用lseek(fd, (target_line-1)*line_length, SEEK_SET)跳转。
  • 进程同步:示例中用wait()保证父进程先完成读取操作,如果你需要更灵活的同步逻辑,也可以用信号、管道等机制。

内容的提问来源于stack exchange,提问作者Goktug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:19:57