1、popen()
popen():进程I/O函数,与pclose函数一起使用。
1.1函数定义:
FILE * popen ( const char * command , const char * type );
int pclose ( FILE * stream );
1.2包含头文件:
#include <stdio.h>
1.3函数说明:
popen() 函数通过创建一个管道,调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程。这个进程必须由 pclose() 函数关闭,而不是 fclose() 函数。pclose() 函数关闭标准 I/O 流,等待命令执行结束,然后返回 shell 的终止状态。如果 shell 不能被执行,则 pclose() 返回的终止状态与 shell 已执行 exit 一样。
type 参数只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写类型。如果 type 是 "r" 则文件指针连接到 command 的标准输出;如果 type 是 "w" 则文件指针连接到 command 的标准输入。
command 参数是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用-c 标志,shell 将执行这个命令。
popen 的返回值是个标准 I/O 流,必须由 pclose 来终止。前面提到这个流是单向的。所以向这个流写内容相当于写入该命令的标准输入;命令的标准输出和调用 popen 的进程相同。与之相反的,从流中读数据相当于读取命令的标准输出;命令的标准输入和调用 popen 的进程相同。
1.4函数返回值
如果调用 fork() 或 pipe() 失败,或者不能分配内存将返回NULL,否则返回标准 I/O 流。
1.5 函数错误状态
popen 没有为内存分配失败设置 errno 值。
如果调用 fork() 或 pipe() 时出现错误,errno 被设为相应的错误类型。
如果 type 参数不合法,errno将返回EINVAL。
1.6 实例1
C代码调用 Shell的 ls 命令 ,打印当前路径文件夹下的所有文件名:
#include<stdio.h>
#define _LINE_LENGTH 300
int main(void)
{
FILE *file;
char line[_LINE_LENGTH];
file = popen("ls", "r");
if (NULL != file)
{
while (fgets(line, _LINE_LENGTH, file) != NULL)
{
printf("line=%s\n", line);
}
}
else
{
return 1;
}
pclose(file);
return 0;
}
输出结果:
line=ls_command.c
line=ls_command.o
line=popen.c
line=popen.o
2、从popen()返回的流中读取命令执行结果的字符串,字符串'\0'结尾符号前面还有一个'\n' 换行符号的问题
#include<stdio.h>
#include<string.h>
#define _LINE_LENGTH 256
#define COMMAND "sudo dmidecode -t2 | grep 'Product Name' | awk '{print $3}'"
int main(void)
{
FILE *file;
char line[_LINE_LENGTH];
file = popen(COMMAND, "r");
int Length = -1;
char *p = NULL;
int count = 0;
if (NULL != file)
{
while (fgets(line, _LINE_LENGTH, file) != NULL)
{
// line is end with '\n''\0'
printf("line=%s", line);
Length = strlen(line);
printf("Length = %d\n",Length);
printf("line[Length - 1] = %d:%c",line[Length - 1],line[Length - 1]);
printf("line[Length] = %d:%c",line[Length],line[Length]);
if(line[Length] == '\0')
{
printf("line is end with \'\\0\'\n");
}
line[Length - 1] = '\0';\\ replace line[Length - 1] = '\n' with '\0'
if(strcmp(line,"LNVNB161216") == 0)
{
printf("The Product Name is Matched!\n");
}
}
}
else
{
return 1;
}
pclose(file);
return 0;
}
输出结果:
line=LNVNB161216
Length = 12
line[Length - 1] = 10:
line[Length] = 0:line is end with '\0'
The Product Name is Matched!
从上面的结果可以看出,从popen()返回的文件流指针file中读取的命令执行结果字符串,每一个行字符串是以ASCII的换行符'\n'结尾的,ASCII的换行符号(LF),ASCII值为10。
求执行结果一行字符串的长度strlen函数放回的长度值是包含换行符号的。
参考
[1]https://baike.baidu.com/item/popen/5301781?fr=aladdin
[2]https://baike.baidu.com/item/ASCII/309296?fromtitle=ascii%E7%A0%81&fromid=99077&fr=aladdin