使用字符串输入和输出运行进程
这里有很多与 fork() 和 exec() 相关的问题。不过,我还没有找到真正使使用它们的过程变得简单的方法,而让程序员的生活变得简单就是目标。
我需要一个 C++、Linux 友好的函数来执行以下操作:
string RunCommand(string command, string input){}
该函数应该能够运行 shell 命令,例如 grep,并将输入内容“通过管道”传输到其中并读取输出并返回它。因此,如果我在命令行执行以下操作:
ps -elf | grep somequerytext
我会在代码中执行以下操作:
string psOutput = RunCommand("ps -elf","");
string grepOutput = RunCommand("grep somequerytext", psOutput);
*编辑:问题是 RunCommand 函数的最佳实现是什么。
*编辑:popen 被认为是一种简单的解决方案,但 popen 限制您只能通过管道输入数据或通过管道输出数据,但不能同时使用两者。
There are plenty of questions on here related to fork() and exec(). I have not found one that really makes the process of using them simple though, and making programmer's lives simple is the goal.
I need a C++, linux-friendly function that does the following:
string RunCommand(string command, string input){}
This function should be able to run a shell command, like grep, and "pipe" the content of input into it and read the ouptut and return it. So if I would do the following at the command line:
ps -elf | grep somequerytext
I would in code do:
string psOutput = RunCommand("ps -elf","");
string grepOutput = RunCommand("grep somequerytext", psOutput);
*edit: The question is what is the best implementation of the RunCommand function.
*edit: popen was considered as a solution for simplicity, but popen restricts you to piping data in or piping data out, but not both.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看来您需要一个函数来:
这个大纲的唯一潜在问题是,如果子进程在完成读取输入之前写入输出,并且它写入了太多输出,以致管道已满(它们的容量有限且通常很小)。在这种情况下,进程将死锁 - 父进程尝试写入子进程,子进程尝试写入父进程,并且两者都在等待对方读取某些数据。您可以通过在父级中使用两个线程来避免这种情况,一个处理写入,另一个处理读取。或者,您可以使用两个子进程,一个用于运行命令,另一个用于写入标准输入,而父进程则从命令的标准输出读取到字符串中。
没有标准函数来执行此操作的原因之一正是难以确定什么是适当的语义。
我忽略了错误处理和信号处理问题;它们增加了一切的复杂性。
It appears that you need a function to:
The only potential problem with this outline is if the child writes output before it is finished reading its input, and it writes so much output that the pipe is full (they have a finite and usually quite small capacity). In that case, the processes will deadlock - the parent trying to write to the child, and the child trying to write to the parent, and both stuck waiting for the other to read some data. You can avoid that by having two threads in the parent, one processing the writing, the other processing the reading. Or you can use two child processes, one to run the command and one to write to the standard input, while the parent reads from the command's standard output into a string.
One of the reasons there isn't a standard function to do this is precisely the difficulty of deciding what are the appropriate semantics.
I've ignored error handling and signal handling issues; they add to the complexity of it all.
在讨论 RunCommand 的实现之前,让我们考虑一下这个代码片段:
在上面的代码片段中,问题在于命令是顺序运行的,而不是并发/并行运行的。 (请参阅使用 POSIX 线程编程 p.9 ) 举个例子,如果
ps -elf
生成大量数据,这些数据将存储在psOutput
然后传递给下一个命令。但在实际实现中,管道中的每个进程都是并发运行的,并且通过pipe
传递数据(当然有一些缓冲),不需要等待一个进程执行后再开始执行的其他进程。我建议您查看 Richard Steven 的 Unix 环境中的高级编程 第 8 章“进程控制”第 223 页,以了解
system
的实现。基于 Richard Steven 的代码,RunCommand
的示例实现如下(只是框架代码,没有错误检查):然后将调用上述函数:
shell 负责解析其输入并通过在命令之间设置管道来运行命令。
如果您有兴趣了解 shell 的实现方式,请参阅 Terrence Chan 使用 C++ 进行 Unix 系统编程 第 8 章“Unix 进程”中的“A Minishell 示例”(Jonathan Leffler 的 答案几乎描述了一个shell实现!)
Before discussing the implementation of
RunCommand
, let us consider this code fragment:In the above code fragment, the problem is that the commands are run sequentially, and does not run concurrently/in parallel. (See Programming with POSIX threads p.9 ) To give an example if
ps -elf
generates huge amount of data, that will be stored inpsOutput
and then passed to next command. But in actual implementation, each process in the pipe are run concurrently and data is passed withpipe
(with some buffering of course) and there is no need to wait for the execution of one process before starting the execution of other process.I suggest you to look into the Richard Steven's Advanced Programming in the Unix Environment chapter.8 "Process Control" p.223 for an implementation of
system
. Based on Richard Steven's code, a sample implementation ofRunCommand
will be as follows (just skeleton code, no error checking):and then one would invoke the above functions as:
The shell takes care of parsing its input and running the commands by setting up
pipe
s in between them.If you are interested in understanding how a shell is implemented, see "A Minishell example" in Terrence Chan Unix System Programming using C++ chap.8 "Unix Processes" (Jonathan Leffler's answer pretty much describes a shell implementation!)
为什么不使用
popen()
?它位于标准库中,并且使用起来非常简单:Why not use
popen()
? It's in the standard library, and very simple to use: