从分叉的 child 进程返回后的文件指针

File pointers after returning from a forked child process

对于在分叉的 parent 和 child 进程之间共享的给定文件描述符,parent 进程中的文件位置在 child 进程从同一个文件描述符读取?

这正在发生在我身上。这是设置:

我正在编写一个 C++ CGI 程序,因此它从标准输入读取 http 请求。在处理 multipart_form 时,我使用中介 object (Multipart_Pull) 处理 stdin,它有一个检测边界字符串的 getc() 方法和最后的 returns EOF每个字段的,所以我可以假装一个字段的内容是一个文件。当该字段是文件上传时,我 fork 两次以便将 Multipart_Pull::getc 的结果通过管道传输到运行 ssconvert 的 child 进程的标准输入,以从 Excel 文件进行进一步处理。我编写了 child 进程以将文件指针留在 parent 可以拾取它的位置。 parent 进程使用 wait() 来确保 child 进程在继续之前完成。

为了在开发 Multipart_Pull 时进行测试,我通过打开从真实 multipart_form 请求复制的磁盘文件来伪造标准输入。

伪造标准输入时,在 child 进程 returns 之后,在 parent 进程中读取的第一个字符与 child 进程中读取的第一个字符相同开始时阅读。也就是说,文件指针在 parent 的文件副本中没有移动。

我已经确认 child 进程实际上通过 运行 gdb 读取数据并使用 set follow-fork-mode child 遵循适当的 child 进程,并且还确认了文件parent 在 return 上的位置,方法是将读取的字符与从中读取数据的文件进行比较。

当我真正从 stdin 读取时,我不认为这会成为问题,因为(如果我在这里错了请纠正我),当您从 stdin 读取一个字符时,它就永远消失了。

我意识到有解决此特定问题的解决方法,最简单的方法是忽略 multipart_form 上文件上传后的任何字段,即 parent 不会尝试分叉后继续阅读。但是,我讨厌破坏生产代码或进行不必要的限制,主要是因为我真的只想了解正在发生的事情。

提前致谢。

Is it normal, for a given file descriptor shared between a forked parent and child process, that the file position in the parent process remains the same after a child process reads from the same file descriptor?

既然你提到了 fork(),我推测你正在使用一个符合 POSIX 的系统。否则,答案取决于您的 C++ 实现的具体细节。

在 POSIX 术语中,文件描述符和流都是底层 "open file description" 上的 "handles" 类型。同一个打开的文件描述可能有多个不同的句柄,可能由不同的进程持有。 fork() 函数是可能出现这种情况的一种方式。

如果对同一个打开文件描述的多个句柄进行操作,POSIX 明确声明未指定结果,但 specific conditions 除外。您的子进程通过关闭它们的流来满足它们的部分要求,无论是显式关闭还是作为正常进程终止的结果。然而,根据 POSIX,为了让父级后续使用其流具有指定的行为,它 "shall perform an lseek() or fseek() (as appropriate to the type of handle) to an appropriate location."

换句话说,父进程不能依赖子进程对文件偏移量的操作来自动对它可见,事实上,在子进程操作它们的副本后,根本不能依赖任何特定的偏移量流。