在“UNIX环境高级编程”,第二版,由理查德·史蒂文斯。
第8.3节叉功能。
这里的介绍:
该家长和孩子共享同一个文件偏移量是很重要的。
考虑到派生一个子项,然后等待孩子完成的过程。 假定这两个过程写入到标准输出作为其正常的处理的一部分。 如果家长有重定向(由外壳,也许)它的标准输出很重要的是父母的文件偏移由孩子当孩子写到标准输出进行更新。
[1。 这是什么意思? 如果父母的STD输出重定向到一个“文件1”为例,此时孩子应该更新后的孩子写的东西? 父母原STD输出偏移或重定向输出中(即文件1)偏移? 不能在后面,对吗?]
[2。 更新是怎么做的? 通过孩子明确,通过OS含蓄,通过文件描述自己? 叉后,我以为父母和孩子去自己的方式,有自己的文件描述符的COPY。 那么,如何对子更新偏移父母身边?]
在这种情况下,孩子可以写,而家长在等待它的标准输出; 对孩子后,家长可以继续写下去标准输出,知道它的输出将被附加到任何孩子写道。 如果家长和孩子没有共享相同的文件偏移,这种类型的交互将更加难以完成的,需要由家长明确的行动。
如果双方父母和孩子写相同的描述,没有任何形式的同步,诸如具有用于孩子的家长等待,它们的输出将被混合(假设它是被叉在开放之前的描述符)。 虽然这是可能的,这不是正常的操作模式。
有两种通常情况下的叉后处理的描述符。
家长等待孩子完成。 在这种情况下,父母并不需要做其描述东西。 当孩子终止,任何孩子读或写的都会有自己的文件偏移量相应地更新共享描述符。
无论是家长和孩子走自己的方式。 在这里,叉后,父进程关闭,它不需要描述符,和孩子做同样的事情。 这样一来,既不与其他的开放描述干扰。 这种情形往往是与网络服务器的情况。”
[3。 当调用fork()的,我所不解的是,孩子得到了什么样的父母,文件描述符的副本在这种情况下,并就执行。 如果有任何偏移变化文件描述符父母子女分享,那只能是因为描述符记得偏移本身。 我对吗?]
对不起,我是一种新的概念。
任何帮助吗? 谢谢。
它的文件描述符 ,这是这一进程中的读取和写入调用用来标识文件小的整数, 文件描述 ,这是在内核结构之间的区别是很重要的。 该文件偏移量是文件描述的一部分。 它生活在内核中。
作为一个例子,让我们用这个程序:
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
int main(void)
{
int fd;
fd = open("output", O_CREAT|O_TRUNC|O_WRONLY, 0666);
if(!fork()) {
/* child */
write(fd, "hello ", 6);
_exit(0);
} else {
/* parent */
int status;
wait(&status);
write(fd, "world\n", 6);
}
}
(所有错误检查已被省略)
如果我们编译这个程序,把它hello
,像这样运行它:
./hello
这里是发生了什么:
该程序打开output
文件,创建它,如果不存在,或将其截断至零大小,如果它确实存在。 内核创建一个文件描述(在Linux内核中,这是一个struct file
),并将其与调用进程(最低的非负整数尚未在该进程的文件描述符表使用)文件描述符关联。 文件描述符返回并分配到fd
的程序。 为了讨论的方便假设fd
为3。
程序调用fork()。 新的子进程得到其父的文件描述符表的副本 ,但该文件描述是不可复制的。 在这两个进程的文件表项数3指向同一struct file
。
父进程等待,而子进程写入。 孩子的写入导致上半年"hello world\n"
将被存储在文件中,并提出了由文件偏移6.文件偏移是struct file
!
孩子离开时,父母的wait()
结束,和父写道,利用FD 3,它仍与有它的文件抵消孩子的更新相同的文件描述相关联write()
因此,消息的第二半存储在第一部分之后 ,不覆盖它,因为它会做如果父有文件的零点偏移,如果文件的描述是不共享这将是这种情况。
最后,家长退出,内核看到的struct file
不再使用,将其释放。
在相同的部分,书,存在示出3个表内是否有一个文件被打开时的图。
用户文件描述符表(进程表条目的一部分),文件表和inode表(v节点表)。 现在文件描述符(这是一个索引文件的描述符表)项指向的文件表项,它指向一个inode表项。
现在, 文件偏移 (从下一个读/写操作发生在那里的位置)有没有在文件表。
所以说,你在父母开了一个文件,这意味着它是有一个描述符,文件表条目和索引节点引用过。
现在,当你创建一个子文件描述符表被复制的孩子。 所以在文件表项(为打开描述符)的引用计数增加那意味着现在有相同的文件表项的两个引用。
这个描述现在都在父母和孩子可以,指向同一个文件表项,因此共享偏移。 现在有这样的背景,让我们看看你的问题,
- 这是什么意思? 如果父母的STD输出重定向到一个“文件1”为例,此时孩子应该更新后的孩子写的东西? 父母原STD输出偏移或重定向输出中(即文件1)偏移? 不能在后面,对吗?]
孩子明确不需要任何更新。 这本书的作者试图
告诉,假设父母的标准输出放重定向到一个文件和一个叉呼叫。 此后,父母是wating.So描述符现在复制,即文件偏移也被共享。 现在,只要现在孩子写东西到标准输出,写入的数据被保存在重定向的文件。 自动偏移通过写入呼叫递增。
现在,说孩子离开。 所以家长出来的等待和标准写出来的东西(这被重定向)。 现在,在父母的写入调用的输出将被置于 - >数据,这是写在孩子之后。 为什么 - >既然孩子已经写完后偏移的当前值现在已经改变。
Parent ( )
{
open a file for writing, that is get the
descriptor( say fd);
close(1);//Closing stdout
dup(fd); //Now writing to stdout means writing to the file
close(fd)
//Create a child that is do a fork call.
ret = fork();
if ( 0 == ret )
{
write(1, "Child", strlen("Child");
exit ..
}
wait(); //Parent waits till child exit.
write(1, "Parent", strlen("Parent");
exit ..
}
PL。 看到上面的伪代码,使得打开的文件包含将ChildParent最终的数据。 所以你看,当孩子写,这是所能得到的利勃海尔给母公司写调用,因为offest共享文件偏移量得到了改变。
2.How的更新呢? 通过孩子明确,通过OS含蓄,通过文件描述自己? 叉后,我以为父母和孩子去自己的方式,有自己的文件描述符的COPY。 那么,如何对子更新偏移父母身边?]
Now I think the answer is clear-> by the system call that is by the OS.
[3。 当调用fork()的,我所不解的是,孩子得到了什么样的父母,文件描述符的副本在这种情况下,并就执行。 如果有任何偏移变化文件描述符父母子女分享,那只能是因为描述符记得偏移本身。 我对吗?]
这也应该是清楚的。 用户文件表点到文件表表项的条目(其中包含抵消)。
换句话说,该系统调用可以获取从描述符的偏移。
文章来源: Can anyone explain a simple description regarding 'file descriptor' after fork()?