【问题标题】:C - How to locate temp files previously created by tmpfile()?C - 如何找到以前由 tmpfile() 创建的临时文件?
【发布时间】:2010-12-01 19:45:06
【问题描述】:

我正在开发一个多进程程序,它基本上对 RVB 文件的每一层执行模糊化。 (1 个进程 -> 1 层)。每个子进程都使用函数tmpfile() 传递一个临时文件。每个子进程完成其工作后,主进程必须读取创建的每个临时文件并组装数据。问题是我不知道如何读取主进程中的每个临时文件,因为我无法访问子进程的内存,所以我不知道创建的临时文件的临时指针是什么!

有什么想法吗?

如有需要,请随时要求澄清。

【问题讨论】:

  • 我的第一个建议是使用线程?但是,是的,需要进一步澄清。
  • RVB Rhino 是 3D Visual Basic 吗?或者是其他东西?只是好奇……
  • @Jonathan: 完全没有,一些用 C 手动编写的代码仅此而已:)

标签: c fork temp


【解决方案1】:

tmpfile() 函数返回一个FILE 指向一个没有确定名称的文件的指针——事实上,即使是子进程也不能轻易地确定文件的名称,更不用说父进程了(在许多 Unix 系统上,文件没有名称;在tmpfile() 返回调用者之前已取消链接)。

extern FILE *tmpfile(void);

因此,如果您必须传达文件名,那么您使用了错误的临时文件创建原语。

您有多种选择:

  1. 让父进程使用tmpfile() 创建文件流,以便父进程和子进程共享文件。有一些小的协调问题需要处理 - 在阅读孩子们写的内容之前,父母需要回到起点,并且只有在孩子退出后才应该这样做。
  2. 改用文件名生成原语之一 - mkstemp() 很好,如果您需要一个 FILE 指针而不是文件描述符,您可以使用 fdopen() 创建一个。您仍然面临从子级到父级获取文件名的问题;同样,父母可以打开文件,或者您可以为每个孩子使用管道,或者一些共享内存,或者......选择 IPC 机制。
  3. 在分叉之前让父级为每个子级打开一个管道。子进程关闭管道的读端,写入写端;父关闭管道的写端并安排从读端读取。这里有多个孩子的问题是任何给定管道的容量都是有限的(而且非常小 - 通常约为 5 KiB)。因此,您需要确保父级完全读取所有管道,请记住,在读取所有数据之前,子级将无法退出(严格来说,除了最后一个缓冲区已满之外的所有数据都已被读取)。李>
  4. 考虑使用线程 - 但要注意使用线程的协调问题。
  5. 决定您不需要使用多个控制线程 - 无论是进程还是线程 - 只需让主程序完成工作即可。这消除了协调和 IPC 问题 - 这确实意味着您不会从机器上的多核处理器中受益。

其中,假设并行执行至关重要,我可能会使用管道从子级获取文件名(选项 2);它的协调问题最少。但为简单起见,我会选择“主程序完成所有工作”(选项 5)。

【讨论】:

  • mkstempt 究竟是如何工作的?当我在父进程上创建一个临时文件并写入它时。之后,我想从子进程访问文件。我该怎么做,你能举个小例子吗?
  • 我假设您的意思是mkstemp()mkstemp() 函数既返回一个打开的文件描述符,又修改作为参数传递的文件名模板(不要尝试传递字符串文字)。您可以使用您设置的任何通信机制将文件名从父级传递给子级。有无限的可能性——使用管道、共享内存、消息队列、具有已知名称的文件或其他任何东西。如果在父级创建临时文件后启动子级,则子级可以访问该名称。
  • 非常感谢。我想查一下共享内存和消息队列的方法,可以给我一些链接吗?
  • 搜索 SO 可能是最简单的。建议搜索:“[c] shared memory”和“[c] message queue”。有两个共享内存系统和两个消息队列系统——System V IPC 系统(shmatt()msgget() 等)和更新的 POSIX 系统(shm_open()mq_open() 等)。您可以将这些名称中的一个或多个添加到搜索字符串中。如果子级在父级创建临时文件后启动,则子级可以访问该名称。如果您执行另一个程序,则可以将名称作为参数传递。如果您不执行程序,则可以使用名称。
【解决方案2】:

子进程可以将文件描述符发送回父进程。

编辑:APUE 站点中的示例代码(src.tar.gz/apue.2e/lib、recvfd.c、sendfd.c)

【讨论】:

    【解决方案3】:

    使用线程而不是子进程?将临时文件的名称放在另一个文件中?不要为临时文件使用随机名称,而是(例如)基于父进程的 pid 的名称(以允许您的程序的多个实例同时运行)加上序号?

    【讨论】:

      【解决方案4】:

      如果您在父进程中调用tmpfile(),子进程将继承所有打开的描述符并能够写入文件,并且父进程也可以访问打开的文件。

      【讨论】:

        【解决方案5】:

        您可以在父进程中创建一个临时文件,然后 fork,然后让子进程使用它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-04-20
          • 1970-01-01
          • 2010-11-04
          • 2012-07-14
          • 1970-01-01
          • 1970-01-01
          • 2016-04-10
          相关资源
          最近更新 更多