更改子进程的偏移量

时间:2017-04-30 15:52:12

标签: c file-descriptor

假设我有一个父进程,然后创建一些子进程以便从同一个文件中读取。

  1. 当每个进程从文件描述符读取时,是否在他所有兄弟的进程之间改变了偏移量?

  2. 所以,每个进程是否可能会读取一个唯一的行,或者如果没有同步应用程序,每个进程都会读取与其兄弟姐妹相同的行?

    id = fork();
    
    if (id < 0)
        exit(EXIT_FAILURE);
    
    if (pipe(fd) == -1)
        exit(EXIT_FAILURE);
    
    switch (id) {
    case 0:
        //child process
        readFromFile(filename);
        exit(0);
        break;
    default:
        //Parent process doing something..
        break;
    }
    

2 个答案:

答案 0 :(得分:3)

在POSIX系统上,子进程通过fork调用继承的文件描述符引用系统范围表中的相同文件描述符。以下是open(2)的Linux手册页中的相关引文:

  

术语打开文件描述是POSIX用来引用的术语   系统范围的打开文件表中的条目...   当文件描述符重复时(使用dup(2)或类似),   duplicate是指与原始文件相同的打开文件描述   文件描述符,因此两个文件描述符共享   文件偏移和文件状态标志。这种共享也可能发生   进程之间:通过fork(2)创建的子进程继承   它的父文件描述符的重复,以及那些重复   请参阅相同的打开文件说明。

这意味着父和子共享文件偏移量相同的信息,读入一个将改变所有其他进程看到的偏移量。如果进程并行读取而读取之间没有lseek,则没有两个进程会读取相同的数据。

您可以在以下测试程序中看到此操作,该程序打印命令行中给出的文件的前20个字符。 (如果未共享位置信息,则会打印前10个字符两次)。

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

char buffer[256];

int
main(int argc, char ** argv)
{
    int fd = open(argv[1], O_RDONLY);
    fork();
    read(fd, buffer, 10);
    write(1, buffer, 10);
    return 0;
}

HOWEVER ,这是一个巨大的“但是”,这仅适用于读取文件的低级系统调用界面:open(2)read(2)等。如果您使用更高级别的缓冲接口,例如fgetsstdio.h中的其他功能,则事情会变得复杂。当进程被分叉时,即使它们继承了指向内核中单个系统范围的文件信息的共享结构的文件描述符的副本,它们也继承了用户空间缓冲信息的单独的副本。由stdio.h调用使用,这个缓冲信息包括它自己的偏移量(显然是缓冲区),它们在进程之间不同步。

答案 1 :(得分:0)

  

所以,每个进程是否可能会读取一个唯一的行

作为K. A. Buhr says,进程将读取文件的不同部分,因为从一个读取将更新另一个的位置。

但是如果你正在读行,那你就麻烦了。

除非您事先知道线条的长度(即它们具有固定长度),否则您可能会读取部分线条,而另一个线条可能会读取其他部分。要解决这个问题,您需要一次读取一个字符,或者在阅读后寻找行边界。这两个都将受到竞争条件的影响:另一个过程可能在您的阅读之间或您的阅读与寻求之间进行读取。