两个不同的进程(父进程和子进程)是否可以看到同一个文本文件并对其进行操作?
我完成了这一点,但我必须使用 fopen() 在两个进程中打开文件。我的期望是其中一个进程打开文件,而另一个进程可以查看和操作它。
答案1
从手册fork(2)
在我的 OpenBSD 系统上(我的重点):
子进程有自己的父进程描述符副本。这些描述符引用相同的底层对象,因此,例如,文件对象中的文件指针在子级和父级之间共享,这样
lseek(2)
子进程中的描述符就可以影响后续的read(2)
或write(2)
父进程的描述符。 shell 还使用此描述符复制来为新创建的进程建立标准输入和输出以及设置管道。
这意味着,如果您在分叉子进程之前在父进程中打开文件,则两个进程都将打开相同的文件。但是,如果子进程从文件中读取,则父进程的文件指针也将被移动。
在两个进程中访问文件独立地,您必须分别在两个进程中打开该文件。
如果您在父级中打开文件后的调用fork()
,它不会在子进程中打开,反之亦然。
答案2
这是一些执行此操作的示例代码。
#include <err.h>
#include <stdio.h>
#include <unistd.h>
char buf[8];
int main(int argc, char *argv[])
{
int ch, fd[2], rv;
pipe(fd);
switch (fork()) {
case -1:
err(1, "could not fork");
case 0: // child
rv = lseek(STDIN_FILENO, -7, SEEK_END);
if (rv == -1) err(1, "could not seek");
sleep(3);
close(fd[1]);
break;
default: // parent
close(fd[1]);
read(fd[0], &ch, 1);
read(STDIN_FILENO, buf, 7);
printf("read '%s'\n", buf);
}
return 0;
}
发生的事情是,父进程阻塞等待子进程,同时子进程寻找标准输入的末尾,负七,然后关闭pipe(2)
父进程。这会解除父进程的阻塞,父进程从子进程将共享文件指针移动到的位置的共享描述符中读取数据。
$ make sharedseek
cc sharedseek.c -o sharedseek
$ echo asdfasdfasdf123456 > x
$ ./sharedseek < x
read '123456
'
$
如果标准输入不可查找,这将不起作用。此外,管道(或某种形式的通信)确实是必要的,否则父进程可能会在子进程之前运行。
如果文件描述符未共享,则父级将不会从子级将指针移动到的位置读取。