当前位置:  开发笔记 > 编程语言 > 正文

C++:在子进程上使用cin

如何解决《C++:在子进程上使用cin》经验,为你挑选了1个好方法。

我正在编写一个早期分析的C++程序,以及在子进程和父进程中使用std :: cout和std :: cin的地方.出于某种原因,在Linux上,cin似乎没有在子进程中工作; 它永远不会提示任何输入.有趣的是,这个程序在Mac上运行得很好.有谁知道为什么会这样?谢谢.



1> FauChristian..:

您观察到的是因为fork和exec模型1.正如您所料,所有文件描述符都被复制,但两个进程从单个描述符读取时的优先顺序是未定义的2.fork()返回后,它们是父和子是无关紧要的.

因此,您的情况甚至比仅仅依赖于实现还要糟糕.您可以在SAME系统上获得两个不同的结果.

您的方案称为竞争条件.在这种情况下,两个程序副本中的哪一个(父或子)获取哪个字符取决于许多与时序相关的细节.甚至其他进程对您的系统要求的资源也可能会影响观察到的行为.

读操作本质上不是原子的2.
如果您可以在任何操作系统上通过父级和子级从同一个流中读取相同的字符,则该操作系统无法正确防范此竞争条件,并且这是一个内核问题,应该报告为可能的错误3.

您可以使用信号量或其他同步方法来解决此功能歧义.如果正确使用这种机制来保证原子读取,您可能会实现线程安全(或者在这种情况下是过程安全),但是您可能仍然没有所需的.

经典的解决方案可能是决定你想要读取std :: cin的两个进程中的哪一个,并在另一个进程中关闭std :: cin.执行此操作的标准机制是测试fork调用的返回整数.如果(fork()== 0)那么你就是孩子.(示例在fork()文档中给出.)

如果您需要两个进程中的值,则可以在fork之前使用pipe()和dup2(),并在每个进程中使用正确的close()以将字符的副本从主要读取器流式传输到次要读取器.这是代理设计模式.如果不同的流程应该处理不同的消息类型,您也可能希望实现责任链设计模式.

有趣的是,由std :: cout和std :: cerr包装的输出文件描述符没有竞争条件风险,您可以混合父项和子项4的输出.

.......

[1] POSIX标准可以追溯到早期的UNIX,早在PDP11之前.

[2]开放组基础规范第7期IEEE Std 1003.1-2008,2016版预读和读状态手册页,"标准开发人员考虑将原子性要求添加到管道或FIFO中,但认识到由于管道的性质和FIFO不能保证{PIPE_BUF}的读取的原子性或任何其他大小可以帮助应用程序的可移植性."

[3]相同消息字节的连续读取可能违反标准条件.在从输入流中获取字节或字符时应该有一个系统信号量或其他关键代码保护,以便在再次读取之前丢弃字节或字符读取.

[4]当消息可能超过该低级别的POSIX保证时,写入来自父节点和子节点的相同流,<= 512字节的写入将以原子方式进入输出流(根据Linux"man 7 pipe").此外,为了使用多个编写器维护年表,需要在每次写入后刷新更高级别的C函数或C++方法.但是,如果已知消息在限制范围内并且仅执行低级write()操作,则具有多个写入器是完全安全的.

推荐阅读
Chloemw
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有