popen/pclose 函数

函数作用

如果说system在一定程度上是execl的优化版,那么popen就一定程度上是system的优化版,使用popen不仅可以运行代码,还可以获取运行的输出结果但是system和exec族函数还是非常重要的,也有自己的特定应用场景)。

并且popen函数使用到了管道的概念(之后会详细学习):

" popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程。这个管道必须由pclose()函数关闭,而不是fclose()函数。pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose()返回的终止状态与shell已执行exit一样。"

需要添加的库

#include 

函数原型

FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);

函数参数

  • command:是一个指向以NULL结束的shell命令字符串的指针。这行命令将被传到bin/sh并使用-c标志,shell将执行这个命令
  • type:只能是读或者写中的一种,得到的返回值(标准I/O流)也具有和type相应的只读或只写类型。如果type是"r"则文件指针连接到command的标准输出;如果type是"w"则文件指针连接到command的标准输入,如果想要实现类似system功能,此处应该是"r"
  • 返回值:如果调用fork()或pipe()失败,或者不能分配内存将返回NULL,否则返回标准I/O流。popen()没有为内存分配失败设置errno值。如果调用fork()或pipe()时出现错误,errno被设为相应的错误类型。如果type参数不合法,errno将返回EINVAL

实操演示

demo6.c:

根据上面所说,fopen返回的是一个文件流(FILE *型),那么如果想要读取流的数据其实就是使用之前学到的fread函数,详见:

使用fopen等标准C库来操作文件_mjmmm的博客-CSDN博客

#include 
#include 
#include 


int main(void)
{
    char ret[1024] = {0};
    FILE *fp;

    fp = popen("ls -l","r");

    //size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    fread(&ret, sizeof(char), 1024, fp);

    printf("return value of ls = %s\n",ret);

    pclose(fp);
    
    return 0;
}

运行代码:

popen/pclose 函数_第1张图片

虽然实现的效果似乎和之前没什么区别,但其实很不一样,system或execl调用后只能将结果打印在屏幕上,结果的数据是无法保存的而popen的结果是可以保存的,之所以打到屏幕上是我使用了printf,如果我不使用printf而是将这些数据写入其他文件或进行其他操作,那么system和execl就无法做到了。 

你可能感兴趣的:(linux,运维,服务器,系统编程,C语言)