进程和共享文件描述符

Posted

技术标签:

【中文标题】进程和共享文件描述符【英文标题】:Processes and a shared file descriptor 【发布时间】:2015-06-28 17:28:16 【问题描述】:

我有一个应用程序,它自己创建多个实例(进程),并且这些进程具有共享的数据结构。在该结构中,有一个文件描述符用于将数据记录到文件中。在日志记录函数中有一个检查,检查文件描述符是否为 -1,如果是,则打开文件并设置共享文件描述符的值。

其他进程/线程执行相同的检查,但此时 fd 为 != -1。所以文件不会被打开。然后他们继续写入文件。大部分时间写入失败并返回 -1。当写入没有失败时,我使用 readlink 检查了 fd 的文件路径。路径是日志文件以外的其他文件。

我假设这是因为即使文件描述符值始终为 11,即使在后续运行中,该值也指向每个进程的不同文件。那么它是进程打开的第十一个文件吗?因此,日志文件甚至不被视为对这些进程打开,即使它们确实打开了文件,fd 也会有所不同。

所以我的问题是正确的吗?我的第二个问题是,鉴于多个进程需要写入此日志文件,我该如何重新实现此方法。每个进程都需要打开该文件吗.. 还是有其他更有效的方法.. 我是否需要关闭该文件以便其他进程可以打开并写入它..?

编辑:

该软件是一个名为filebench的开源软件。 文件可见here。

日志方法是filebench_log。第 204 行是我提到的文件打开位置的第一个检查。写入发生在第 293 行。fd 值在所有进程中为 11,并且值相同:11。它实际上是由所有进程共享的,并且主要是 here。该文件只打开一次(通过打印语句验证)。

具有 fd 的共享数据结构被称为

filebench_shm 

fd 是

filebench_shm->shm_log_fd 

编辑 2: 我得到的错误消息是错误的文件描述符。 Errno 是 9 岁。

编辑 3: 所以似乎每个进程都有不同的fds索引表。维基:

On Linux, the set of file descriptors open in a process can be accessed under the path /proc/PID/fd/, where PID is the process identifier.

所以我遇到的问题是,对于进程 ID 为 101、102 的两个进程,两个进程的文件描述符 11 不同:

/proc/101/fd/11 
/proc/102/fd/11

我在这些进程之间有一个共享的数据结构。除了 fd 之外,我还有其他方法可以在它们之间共享打开的文件,因为那不起作用?

【问题讨论】:

"大部分时间写入失败并返回 -1" 并且errno 设置为哪个值? 创建多个实例”如何? 一些代码会有所帮助。但是请注意,除非您将结构放在共享内存中,否则它在多个进程之间共享。当您生成子进程时,每个子进程都有自己的副本。其他所有内容(假设您通过fork()ing 启动新副本)。 共享数据结构”怎么样? 发生这一切的平台也会很有趣。 【参考方案1】:

在产生新进程之前打开文件似乎是最简单的。通过将文件集中到一个时间和地点,这避免了与打开文件有关的所有协调复杂性。

【讨论】:

我在 ipc_init 中调用了 log 方法,它正在初始化所有共享数据结构,并且在创建任何其他进程之前。还是同样的问题。似乎对于每个进程,fd 会导致文件未找到,或者最终写入不同的文件,其中每个进程的不同文件是不同的。 写入不同的文件”这些文件有何不同? 我这样做 readlink("/proc/self/fd/11", filepath, 300); .正如我提到的 fd 的值始终为 11。它第一次打印日志文件的正确路径并写入文件。大多数时候它是一个空字符串,所以什么都没有打印出来,我得到 errno =9。其他时候,我会得到 /fist/upper/bigfileset/00000002/00000001 的变体,例如 /fist/upper/bigfileset/00000002/000000013。由于这是一个文件平台软件,它会创建一堆文件/目录。注意:除了上述方法之外,我不会在任何地方对 fd=11 进行硬编码。【参考方案2】:

我最初写这个是为了解决问题:

创建一个共享内存段。 将文件描述符变量放在段中。 在段中放置一个互斥信号量 每个进程都访问段中的文件描述符。如果没有打开,锁定信号量,检查是否打开,如果没有打开 文件。释放互斥锁。

这样所有进程共享相同的文件描述符。

但这假设底层文件描述符对象也在共享内存中,我认为不是。

改为使用另一个答案中提到的open 然后fork 方法,或者让每个进程打开文件并在需要时使用flock 序列化访问。

【讨论】:

这是正在发生的事情,除了没有锁。正如我在帖子中提到的,所有进程的 fd 值为 11。但是,当我打印文件路径时,每个进程要么打印一个不同的文件,要么什么都不打印,因为每个进程都打开了一组不同的文件。 这就是为什么需要锁。 我加了一个锁,但没有帮助。如果您检查我添加的编辑中的第一个链接 (void) ipc_mutex_lock(&filebench_shm->shm_msg_lock);在第 202 行并在 if 块之后将其解锁。不幸的是,这并没有解决它。 这些步骤“如果它没有打开,锁定信号量,检查它是否打开”似乎有点乱了。第一次锁定信号量然后检查它是否打开,不需要再次检查它是否打开,然后根据您的答案进行其余操作。 @alk - 检查它是否已经打开可以避免锁定,这很昂贵。

以上是关于进程和共享文件描述符的主要内容,如果未能解决你的问题,请参考以下文章

文件描述符表和系统调用

(2.5)文件和目录操作——Linux文件共享

将文件描述符从主进程传递到其线程

Linux中的文件描述符

在 fork() 之后寻求有关“文件描述符”的简单描述

Linux查看进程打开多少文件描述符命令