应用于Linux管道文件描述符的Open()、Close()和Read()函数。

3

这可能是一个简单的问题,但我想确认一下我对这些函数的理解 - 如果我完全错误的话请帮我澄清。

以下是情况描述:

我有一个多线程程序,通过管道传递数据,使用UNIX的pipe()函数。基本上,两个线程可以写入管道(当然它们是同步的),只有一个可以从管道中读取。

据我所知,read()命令将尝试从传递的文件描述符参数读取x字节数,并在达到EOF时返回0。

我写入管道的字节数是可变的,因此从管道中读取时会出现一些困难。我相信我在某个地方读到过,在close(my_pipe_file_descriptor)中使用EOF。如果是这样的话,read()一旦遇到EOF就会返回 - 这将会很好。

如果我上面说的关于close()read()的东西是正确的,我有一个问题。

如果我调用close(my_pipe_file_descriptor),那么管道会被销毁,使得任何对open(my_pipe_file_descriptor)的未来调用都无效吗?

我希望这讲得清楚。

1个回答

5
关于 close 的问题,是的,它会销毁管道,您不能在关闭它的进程中再使用它。如果您想使用新的管道,您必须再次创建一个。如果您关闭管道的写端口,则读端口仍然有效,允许读取器读取直到接收到所有数据。这最后一点意味着编写器不必等待直到知道读取器已经接收到所有数据(通常无法),而只需写入任何数据,然后关闭其端口即可。
关于 read 函数的理解,基本上是正确的。您要求它读取一定数量的字节,它将读取 至多 该数量的字节。它可能会读取较少的内容,您必须检查返回的值以了解它实际上读取了多少。这不仅适用于管道,还适用于套接字和文件。
我建议您阅读官方 POSIX 参考文献 出于完整性考虑(即使它不能用于打开或创建匿名管道): 如果您只搜索一下,就可以找到成千上万的使用管道的示例。

1
另一个很好的参考资料是《高级Linux编程》书籍。此外,了解多路复用系统调用,如poll(2)(或旧版的select(2) ...)非常有用。 - Basile Starynkevitch
谢谢您的回复,很有帮助。还有一个快速问题,文档中说如果read()遇到EOF将返回0。这感觉像是一种“hackish”的方式,但我能否简单地将EOF写入管道作为流控制的形式?也就是说,EOF被用来表示线程的写操作已完成。 - Mlagma
没事了,我忘记了EOF在平台上是依赖于特定的意义,因为没有ASCII字符代码 - 但是,我可以通过寻找我定义的特殊字符来解决这个问题。 - Mlagma
我的管道把多字节字符切成了两半。我该如何防止这种情况发生? - JRowan
@JRowan 如果你指的是wchar_t字符,那么请记住,wchar_t的实际类型(因此大小)是与具体实现相关的。如果写入程序和读取程序对wchar_t有不同的定义,则它们将无法很好地配合使用。如果您遇到这个问题,请发布一个问题,并提供编写程序和读取程序的 [mcve]。 - Some programmer dude

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