在启动过程的什么时候可以使用管道

At what point of the boot process is it ok to use pipes

我有一个使用 Linux 的 RTAI 扩展构建的系统。它有一个 运行 在启动时以 root 身份运行的进程。它创建了一些命名管道和 chmod 777 它们。管道由 root 拥有并具有 prwxrwxrwx 权限,但 none 的用户进程可以写入或读取它们。管道是这样制作的(在 C 中)

unlink(pipename);
mkfifo(pipename, 0777);
chmod(pipename, 0777);

如果我以用户身份登录,su 到 root,终止进程并重新启动它,从 root 退出,命名管道仍然由 root 拥有并具有 prwxrwxrwx 权限,但这次,用户进程可以读取并从他们那里写信。

问题:如果程序 运行 作为启动过程的一部分,我还需要做什么才能访问命名管道。

此外,我如何确保它是在所有通信机制设置完成后执行的最后一个进程。

编辑

我更改了标题(旧标题是为启动进程设置管道权限

我终于通过将流程转移到 rc.local 使其正常工作。由于编码员使用的是 RTAI,他认为该进程必须与所有其他 RTAI 进程同时启动。其他进程不使用任何 Unix 通信机制,因此无关紧要。当他开始使用管道时,它不得不被转移到多用户级别的末尾。

这是我找不到解释的部分:在启动过程中的什么时候可以使用管道?我已经把它移到了最后,但它可能更早。

问题

Took a while to figure out how to find out what state the process was in. All the programs just block on open. I could try O_NONBLOCK but I don't know how well that will work. I also hate polling.

进程是否挂起 open() 取决于打开模式(O_RDONLYO_WRONLYO_RDWR)。

  • 没有O_NONBLOCK:

    • with O_RDONLY, open() 将阻塞,直到打开 fifo 以从任何进程写入;
    • with O_WRONLY, open() 将阻塞直到打开 fifo 以读取任何进程;
    • O_RDWRopen()将立即return。
  • O_NONBLOCK:

    • O_RDONLYopen()将立即return;
    • with O_WRONLY, open() 将 return 如果未打开 fifo 以从任何进程读取错误;
    • O_RDWRopen()将立即return。

详见open(3) (O_NONBLOCK section) and fifo(7)

如果您的 open() 挂起,则表明:

  • 您正在使用 O_RDONLYO_WRONLY 而没有 O_NONBLOCK;
  • fifo 未在任何其他进程中打开以进行写入或读取。

解决方案

如果您预计 fifo 已从另一个进程打开,请检查为什么没有打开。可能应该保持打开状态的进程已死,或者您以错误的顺序启动进程,或者存在竞争条件。

否则,您可以执行以下操作之一:

  • 使用O_RDWR开启方式,open()会立即return。

    但是,请注意,从 fifo 读取时(因为您一直打开读取端)或写入 fifo 时永远不会得到 EOF(因为您一直在写入)结束打开)。

  • 使用O_RDONLY | O_NONBLOCKopen()会立即return。

    请注意,如果未打开 fifo 以从任何进程读取,read() 将 return EOF

  • 稍后打开fifo,当另一个进程已经打开fifo的另一端时。

终于追根究底了

  1. 我添加了延迟,但没有任何区别。
  2. 然后我发现虽然我mkfifo是666,但是权限还是644。由于FIFO是root所有的,其他进程不能写入。结果我在mkfifo后面加了一个chmod。这使得 FIFO 可写。
  3. 写作问题已解决,但作者仍然没有return公开。
  4. 这是一个特定于 SuSE 的问题。该过程于 boot.local 开始,为时过早。在其他系统上,它可以在 rc.local 上启动,但在 SuSE 上,它必须在 after.local 上启动。将程序移动到 after.local,一切都神奇地开始工作。

简而言之,修复是

  1. 创建 FIFO 后的 chmod
  2. 在 SuSE
  3. 上将可执行文件移动到 after.local

对于 Ubuntu、Centos 和 Debian,我的问题的答案放在 rc.local 中,对于 SuSE,放在 after.local 中。