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

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

问题描述

在Unix 环境中的高级编程",第 2 版,W. Richard Stevens 着.8.3 分叉函数.

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.

考虑一个 fork 子进程,然后等待子进程完成的进程.假设两个进程都将写入标准输出作为其正常处理的一部分.如果父级的标准输出重定向(可能是通过 shell),则当子级写入标准输出时,子级必须更新父级的文件偏移量.

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 输出偏移量或重定向输出(即 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} 更新是如何完成的?由子显式,由操作系统隐式,由文件描述符本身?fork之后,我认为父母和孩子各行其是,拥有自己的文件描述符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.

如果父子进程都写入同一个描述符,没有任何形式的同步,比如让父进程等待子进程,它们的输出将被混合(假设它是一个在fork之前打开的描述符).虽然这是可能的,但这不是正常的操作模式.

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.

父母和孩子各行其是.在这里,在 fork 之后,父进程关闭它不需要的描述符,子进程也做同样的事情.这样,既不会干扰对方的开放描述符.网络服务器经常出现这种情况.

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?

我对这些概念有点陌生.

I am kind of new to the concepts.

推荐答案

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

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
", 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 "的前半部分存入文件中,并将文件偏移量提前6.文件偏移量在struct file!

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

子进程退出,父进程的 wait() 完成,父进程使用 fd 3 写入,该文件仍然与相同的文件描述相关联,其文件偏移量由子进程的 更新写().所以消息的后半部分存储在第一部分之后,不会像父文件偏移量为零时那样覆盖它,如果文件描述不是分享.

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天全站免登陆