我测试了APUE(UNIX环境中的高级编程,3ed)、15.3 popen和plcose函数的示例。
示例代码如下
#include "apue.h"
#include <sys/wait.h>
#define PAGER "${PAGER:-more}" /* environment variable, or default */
int
main(int argc, char *argv[])
{
char line[MAXLINE];
FILE *fpin, *fpout;
if (argc != 2)
err_quit("usage: a.out <pathname>");
if ((fpin = fopen(argv[1], "r")) == NULL)
err_sys("can't open %s", argv[1]);
if ((fpout = popen(PAGER, "w")) == NULL)
err_sys("popen error");
/* copy argv[1] to pager */
while (fgets(line, MAXLINE, fpin) != NULL) {
if (fputs(line, fpout) == EOF)
err_sys("fputs error to pipe");
}
if (ferror(fpin))
err_sys("fgets error");
if (pclose(fpout) == -1)
err_sys("pclose error");
exit(0);
}
我的输入文件是“temp.in”,我们有
$ cat temp.in
test sentence
示例的输出如下
$ ./popen2 temp.in
test sentence
如 APUE 中所示,执行
fpout = popen(cmdstring, "w")
类似于其子进程执行 sh -c cmdstring
。因此,上一节中显示的代码 popen
应该执行
sh -c "${PAGER:-more} test sentence"
我的操作系统(Ubuntu 22.04.3 LTS)没有名为
PAGER
的环境值,因此它应该执行
sh -c "more test sentence"
但是,据我所知,命令
more
的选项应该是文件名。在我的系统中测试以下顺序并获得输出,这与我上面推断的不同:
$ ${PAGER:-more} temp.in
test sentence
$ ${PAGER:-more} test sentence
more: can't open test: no such file or directory
more: can't open sentence: no such file or directory
我的推论有什么问题吗?
好了,
popen()
的逐步工作原理如下(我们忽略一些不相关的检查):pipe()
创建管道
int pfd[2];
pipe(pfd);
第二:当前进程调用
fork()
创建子进程。
if (fork() == 0)
/* child process work */
else if(fork() > 0)
/* parent process work */
第三:子进程和父进程关闭自己的fileno以创建单向管道。编辑
popen(cmdstring, "r")
,父进程关闭其写文件号,子进程关闭其读文件号。
/* child process work */
close(pfd[0]); // pfd[0] is read port
/* parent process work */
close(pfd[1]); // pfd[0] is write port
第四:父进程和chile进程重定向自己的fileno。编辑
popen(cmdstring, "r")
,父进程将其 STDIN_FILENO
重定向至读端口,子进程将其 STDOUT_FILENO
重定向至写端口。
/* child process work */
dup2(pfd[1], STDOUT_FILENO);
close(pfd[1]);
/* parent process work */
dup2(pfd[0], STDIN_FILENO);
close(pfd[0]);
然后,子进程可以将其输出写入管道,父进程可以通过其标准输入从其子进程读取消息。
回到问题。
popen({PAGER:-more}, "w")
将货币进程的标准输出连接到 more
进程的标准输入。fgets(line, MAXLINE, fpin)
从argv[1]
读取字符串并将字符串通过管道传输到more,more将其打印到终止。例子的效果类似
cat $argv1 | ${PAGER:-more}