在fork()之后寻求有关“文件描述符"的简单描述 [英] Seeking a simple description regarding 'file descriptor' after fork()

查看:117
本文介绍了在fork()之后寻求有关“文件描述符"的简单描述的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在W.Richard Stevens撰写的"Unix环境中的高级编程",第二版中. 8.3节fork函数.

In "Advanced Programming in the Unix Environment", 2nd edition, By W. Richard Stevens. Section 8.3 fork function.

这里是描述:

重要的是,父母和孩子共享相同的文件偏移量.

It is important that the parent and the child share the same file offset.

考虑一个过程,该过程将派生一个孩子,然后等待该孩子完成.假定这两个进程都将其写入标准输出作为其正常处理的一部分.如果父级的标准输出(也许是通过外壳)重定向了,则在子级写入标准输出时,子级必须更新父级的文件偏移量.

Consider a process that forks a child, then waits for the child to complete. Assume that both processes write to standard output as part of their normal processing. If the parent has its standard output redirected (by a shell, perhaps) it is essential that the parent's file offset be updated by the child when the child writes to standard output.

我的答复:

{1}是什么意思?例如,如果将父级的std输出重定向到"file1",那么在子级写入后,子级应该更新什么?父母的原始std输出偏移量或重定向的ouput(即file1)偏移量?以后不会吧,对吧?

{1} What does it mean? if parent's std output is redirected to a 'file1' for example, then what should child update after child writes? parent's original std output offset or redirected ouput(i.e file1) offset? Can't be the later, right?

{2}更新如何完成?是由子进程显式表示的,由OS隐式表示的,还是由文件描述符本身表示的?分叉之后,我以为父母和孩子走了自己的路,并拥有了自己的文件描述符COPY.那么子级如何更新父级的偏移量?

{2} How is the update done? by child explicitly, by OS implicitly, by files descriptor itself? After fork, I thought parent and child went their own ways and has their own COPY of file descriptor. So how does child update offset to parent side?

在这种情况下,子级可以在父级等待时写入标准输出;在孩子完成后,父母可以继续写到标准输出,知道它的输出将附加到孩子写的任何内容上.如果父母和孩子没有共享相同的文件偏移,则这种类型的交互将更难以完成,并且需要父母的明确操作.

In this case, the child can write to standard output while the parent is waiting for it; on completion of the child, the parent can continue writing to standard output, knowing that its output will be appended to whatever the child wrote. If the parent and the child did not share the same file offset, this type of interaction would be more difficult to accomplish and would require explicit actions by the parent.

如果父级和子级都写入同一个描述符,而没有任何形式的同步,例如让父级等待子级,则它们的输出将混合在一起(假设这是在派生之前打开的描述符).尽管这是可行的,但这不是正常的操作模式.

If both parent and child write to the same descriptor, without any form of synchronization, such as having the parent wait for the child, their output will be intermixed (assuming it's a descriptor that was open before the fork). Although this is possible, it's not the normal mode of operation.

在分叉之后通常有两种处理描述符的情况.

There are two normal cases for handling the descriptors after a fork.

  1. 父级等待子级完成.在这种情况下,父级不需要对其描述符执行任何操作.当该子项终止时,该子项读取或写入的任何共享描述符都将相应地更新其文件偏移量.

  1. The parent waits for the child to complete. In this case, the parent does not need to do anything with its descriptors. When the child terminates, any of the shared descriptors that the child read from or wrote to will have their file offsets updated accordingly.

父母和孩子都走自己的路.在此之后,在派生之后,父级关闭不需要的描述符,而子级执行相同的操作.这样,两个都不会干扰对方的打开描述符.网络服务器通常就是这种情况.

Both the parent and the child go their own ways. Here, after the fork, the parent closes the descriptors that it doesn't need, and the child does the same thing. This way, neither interferes with the other's open descriptors. This scenario is often the case with network servers.

我的答复:

{3}调用fork()时,我所了解的是,子级获得父级拥有的COPY,在这种情况下,文件描述符执行该操作.如果父级和子级共享的文件描述符的任何偏移量发生变化,那只能是因为描述符记住偏移量本身.我说的对吗?

{3} When fork() is invoked, all i understand is that child get a COPY of what parent has, file descriptor in this case, and does its thing. If any offset changes to file descriptor that parent and child share, it can only be because the descriptor remember the offset itself. Am I right?

我对这些概念很陌生.

推荐答案

重要的是要区分文件描述符,该文件描述符是进程在其读写调用中用来标识的小整数文件,以及文件描述,它是内核中的结构.文件偏移量是文件描述的一部分.它位于内核中.

It's important to distinguish between the file descriptor, which is a small integer that the process uses in its read and write calls to identify the file, and the file description, which is a structure in the kernel. The file offset is part of the file description. It lives in the kernel.

作为一个例子,让我们使用这个程序:

As an example, let's use this program:

#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);
    }
}

(已省略所有错误检查)

(All error checking has been omitted)

如果我们编译该程序,则将其命名为hello,然后像这样运行它:

If we compile this program, call it hello, and run it like this:

./hello

会发生什么:

程序将打开output文件,如果尚不存在则创建该文件,如果存在则将其截断为零大小.内核创建一个文件描述(在Linux内核中,这是一个struct file)并将其与调用进程的文件描述符关联(该进程的文件描述符表中尚未使用的最低非负整数).返回文件描述符,并将其分配给程序中的fd.为了争辩,假设fd为3.

The program opens the output file, creating it if it didn't exist already or truncating it to zero size if it did exist. The kernel creates a file description (in the Linux kernel this is a struct file) and associates it with a file descriptor for the calling process (the lowest non-negative integer not already in use in that process's file descriptor table). The file descriptor is returned and assigned to fd in the program. For the sake of argument suppose that fd is 3.

程序执行fork().新的子进程将获得其父文件描述符表的副本,但不会复制文件描述.两个进程的文件表中的条目号3指向相同的struct file.

The program does a fork(). The new child process gets a copy of its parent's file descriptor table, but the file description is not copied. Entry number 3 in both processes' file tables points to the same struct file.

父进程在子进程写入时等待.孩子的写操作会导致"hello world\n"的前半部分存储在文件中,并使文件偏移量增加6.文件偏移量在struct file

The parent process waits while the child process writes. The child's write causes the first half of "hello world\n" to be stored in the file, and advances the file offset by 6. The file offset is in the struct file!

子项退出,父项的wait()完成,父项使用fd 3进行写入,而fd 3仍与文件描述已由子项write()更新的相同文件描述相关联.因此,消息的后半部分存储在第一部分的 之后,而不是覆盖它,因为如果父文件的文件偏移量为零,则将其覆盖,如果没有文件描述,情况将会如此共享的.

The child exits, the parent's wait() finishes, and the parent writes, using fd 3 which is still associated with the same file description that had its file offset updated by the child's write(). So the second half of the message is stored after the first part, not overwriting it as it would have done if the parent had a file offset of zero, which would be the case if the file description was not shared.

最后,父级退出,内核看到struct file不再使用并释放它.

Finally the parent exits, and the kernel sees that the struct file is no longer in use and frees it.

这篇关于在fork()之后寻求有关“文件描述符"的简单描述的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆