本篇文章简单讲述了c语言接口popen/pclose
的用法
1.函数作用
函数定义如下
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
1.1 popen
popen函数会创建一个管道,fork后调用shell来打开进程。由于管道的定义是单向的,第二个参数type只能指定读或写,不能同时指定读和写;
所得到的管道相应地是只读或只写的
The popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.
简单说来,popen会自动帮我们fork创建子进程和一个管道,将我们传入的参数command
在shell中执行后,将返回值以管道文件的形式发送给调用方。
如果调用fork或pipe
失败,或者不能分配内存,将返回NULL;否则返回标准I/O流。popen()
没有为内存分配失败设置errno值。如果调用fork()或pipe()时出现错误,errno被设为相应的错误类型。如果type参数不合法,errno将返回EINVAL
1.2 pclose
这个函数没有什么好说的,是用来关掉popen打开的文件的(即popen的返回值)
但是,它的返回值可有说到了,其返回值就是我们终端操作的退出状态,以标识命令是否成功执行
但是这个返回是通过wait4
得到的,如果wait4
出现错误,就会返回-1并设置errno
The pclose() function returns -1 if wait4(2) returns an error, or some other error is detected. In the event of an error, these functions set errnro to indicate the cause of the error.
这里还出现了一个新的错误码errnro
,但是经过我的一番百度,没有发现任何地方有对errnro的说明,man手册下方又变成了errno
If pclose() cannot obtain the child status, errno is set to ECHILD.
而且编译执行的时候,errnro
是会报错的,所以姑且认为这里是man手册出错了!
errno
才是正确的
int ret = pclose(f);
printf("pclose: %d | %s\n",ret,strerror(errno));
2.代码示例
2.1 popen读
以下方最简单的ls命令为例,我们以读方式打开,popen就会将ls的执行结果写到文件里面返回给我们
#include <stdio.h>
int main()
{
FILE *f;
char readBuf[1024] = {0};
f = popen("ls","r");
fread(readBuf,1024,1,f);
printf("%s\n",readBuf);
pclose(f);
return 0;
}
编译后执行结果如下
$ ./test
test
test.cpp
2.2 popen写
和读不同,如果用写方式执行popen,命令的输出结果会直接打印到屏幕上
void test2(FILE* f)
{
f = popen("ls","w");
int ret = pclose(f);
printf("pclose: %d | %s\n",ret,strerror(errno));
}
makefile test test.cpp
pclose: 0 | Success
这里我还以为后续可以接着往管道里面写数据,让他继续执行命令
void test2(FILE* f)
{
f = popen("ls","w");
// 缓冲区中写入数据
strcpy(readBuf,"ls -l");
printf("cmd: %s\n",readBuf);
// 写道管道文件中
fwrite(readBuf,1024,1,f);
int ret = pclose(f);
printf("pclose: %d | %s\n",ret,strerror(errno));
}
可测试的结果告诉我,并不行
cmd: ls -l
makefile test test.cpp
pclose: 0 | Success
网上的资料大多数都是只演示了r方法,我不确定这里是不是我写的代码有问题,还是说本来就是这样的。暂且停留在这里吧!
end
关于popen和pclose的简单介绍到这里就结束了,欢迎评论区交流