用mknod()创建命名管道不起作用。

4

语言:C 操作系统:Ubuntu

我只是想使用以下命令创建一个命名管道:

state = mknod("pipe.txt", S_IFIFO | 0666, 0);

问题是我总是得到状态值为-1(表示失败),而不是0。 perror返回“pipe.txt:文件已存在”
我不知道应该如何调试这个问题或者原因是什么,希望任何人都可以指导我错在哪里。
(注意:文件pipe.txt存在于源文件相同的路径中。)

mknod() 成功时返回零,如果发生错误则返回-1(此时errno会被适当设置)。"errno"是什么?如果使用“perror”,则可以从一开始就很容易看到。 - Jonathon Reinhart
在检测到mknod()失败后,使用perror("mknod: pipe.txt") - jxh
当系统调用(例如mkfifo)返回-1时,表示出现了错误。要获取错误信息,您需要查看errno。要打印errno中的错误代码的可用字符串版本,请使用strerror获取可打印字符串,或者使用perror直接打印。但是,仅在函数失败(即返回-1NULL或指定为失败返回值的内容)时才应检查errno - Some programmer dude
你说的perror是对的,我得到的错误是:“pipe.txt:文件已存在”。可能是因为我不理解事情的运作方式,但我认为文件应该存在,这不是整个想法吗? - Popokoko
Popokoko,不,如果你按照我的回答中的链接(http://linux.die.net/man/2/mknod)进行查看,你会发现它实际上是不存在的。`mknod`会在文件系统空间中创建一个条目。 - paxdiablo
2个回答

5

阅读:int mknod(const char *path, mode_t mode, rdev_t dev_identifier);
概述:
使用在路径参数中指定的路径名创建新的字符特殊文件或FIFO特殊文件(命名管道)。

如果文件已经存在,则会出现错误:文件已存在

为了避免这个错误,要删除(unlink())文件,就像我在下面的代码中所做的一样(参考注释):

int main() {
  char* file="pipe.txt";
  unlink(file);  // Add before mknod()
  int state = mknod(file, S_IFIFO | 0666, 0);
  if(state < 0){
    perror("mknod() error");
  }
  return 0;
}

在解除链接之前,请确保这是“您”的文件 :-) - paxdiablo
1
谢谢@Grijesh Chauhan,您的代码示例澄清了我的疑惑。我之前对事情的运作方式有些误解。同时也感谢@paxdiablo! - Popokoko
小更新:我觉得我把事情搞砸了,在使用unlink命令后,我无法再次运行我的项目,有些东西卡在后台了:构建时显示:Blocked: The user operating is waiting for background work :( - Popokoko
你有任何想法如何停止后台的阻塞问题吗? - Popokoko
谢谢你的出色回答。我们是否可以通过添加所有必要的#include语句将其转换为最小工作示例? - puk
显示剩余2条评论

0

您应该检查errno以查看错误是什么,但可能是EEXIST,因为我认为如果文件已经存在,则会发生这种情况。

来自mknod的Linux文档

如果路径名已经存在,或者是符号链接,则此调用将失败并显示EEXIST错误。

然而,如果文件已经存在且就是您在之前运行中创建的管道,则可以安全地重新打开它。所有mknod(及其经常使用的近亲,mkfifo)实际上都是创建 FIFO,您仍然必须在两端打开它才能开始数据传输。


嗯,我现在明白了,我本来很确定它应该获取一个已存在的文件,但我现在理解它应该获取一个文件描述符或类似的东西。 - Popokoko
@Popokoko,你不能从'mknod'获得文件描述符,你只能获得0或-1。你必须打开所创建的fifo才能使用它。 - paxdiablo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接