对于分叉父进程和子进程之间共享的给定文件描述符,在子进程从同一文件描述符读取后,父进程中的文件位置是否保持不变,这是正常的吗?
这种情况正在发生在我身上。这是设置:
我正在编写一个C ++ CGI程序,因此它从stdin读取http请求。在处理multipart_form时,我使用中间对象(Multipart_Pull)处理stdin,该对象具有检测边界字符串的getc()方法并在每个字段的末尾返回EOF,因此我可以假装字段的内容是文件。当字段是文件上载时,我将两次fork,以便将Multipart_Pull :: getc的结果传递给运行ssconvert
的子进程的stdin,以便从Excel文件生成CSV文件以供进一步处理。我编写了子进程,将文件指针保留在父进程可以获取的位置。父进程使用wait()来确保子进程在继续之前完成。
为了在开发Multipart_Pull时进行测试,我打算通过打开从真正的multipart_form请求复制的磁盘文件来伪造stdin。
伪造stdin时,子进程返回后,父进程中读取的第一个字符与子进程启动时读取的第一个字符相同。也就是说,文件指针没有在父文件的副本中移动。
我已经确认子进程实际通过运行gdb并使用set follow-fork-mode child
跟踪相应的子进程来读取数据,并通过比较对文件读取的字符来确认返回的父进程的文件位置从中读取数据。
当我真的从stdin读书时,我不认为这会是一个问题,因为(如果我错了,请纠正我),当你从stdin读取一个角色时,它就永远消失了。
我意识到有解决这个特定问题的解决方法,最简单的方法是忽略multipart_form上文件上传之后的任何字段,即父级不会尝试在fork之后继续读取。但是,我讨厌削弱生产代码或做出不必要的限制,主要是因为我真的只是想了解发生了什么。
提前致谢。
答案 0 :(得分:1)
对于分叉父进程和子进程之间共享的给定文件描述符,在子进程从同一文件描述符读取后,父进程中的文件位置是否保持不变,这是正常的吗?
由于您调出fork()
,我认为您正在使用符合POSIX标准的系统。否则,答案取决于C ++实现的具体细节。
在POSIX术语中,文件描述符和流都是"处理"在基础"打开文件描述"。在同一个打开的文件描述中可能有多个不同的句柄,可能由不同的进程持有。 fork()
函数是出现这种情况的一种方式。
如果操作同一个打开文件描述上的多个句柄,POSIX会明确声明结果未指定,但specific conditions下除外。您的子进程通过显式或正常进程终止来关闭其流来满足这些要求的一部分。但是,根据POSIX,为了父母随后使用其流来指定行为,它必须执行适当的lseek()或fseek()(适用于句柄类型) 。位置"
换句话说,父进程不能依赖子进程'文件偏移的操作自动对它可见,实际上在孩子操纵他们的流副本之后根本不能依赖任何特定的偏移。