popen()函数详解 具体问题具体分析 popen函数获取不到标准I/O流 您所在的位置:网站首页 lua运行错误信息 popen()函数详解 具体问题具体分析 popen函数获取不到标准I/O流

popen()函数详解 具体问题具体分析 popen函数获取不到标准I/O流

2023-10-02 08:08| 来源: 网络整理| 查看: 265

文章目录 1、popen()1.1函数定义:1.2包含头文件:1.3函数说明:1.4函数返回值1.5 函数错误状态 2、简单示例理解3、具体问题4、问题分析并解决5、补充——Linux命令行返回值

自己给自己挖的坑(bug),终究是要自己填上的~~

先简单的解释一下popen函数吧~

1、popen()

popen():进程I/O函数,与pclose函数一起使用。

1.1函数定义:

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

1.2包含头文件:

#include

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。

**百度百科:**https://baike.baidu.com/item/popen/5301781?fr=aladdin

2、简单示例理解

下面放一个简单的代码:

#include #include #include int main(int argc ,char **argv) { char ret[1024] = {0}; FILE *fp; fp = popen("ls -l popen.c","r"); //popen.c文件名 //fp = popen("ifconfig eth0","r"); /* fgets从标准IO流中,一行行读取数据存到ret中,如果不为空的话 */ while(fgets(ret, sizeof(ret), fp)) { printf("read ret %d byte\n",strlen(ret)); printf("%s",ret); return 0; //这里我只读一行就返回了,方便理解 } printf("read ret %d byte\n", strlen(ret)); printf("%s",ret); return 0; }

运行结果:

执行 ls -l popen.c 结果如下:

read ret 51 byte -rw-r--r-- 1 nbiot nbiot 1004 Jul 26 14:15 popen.c

执行 ifconfig eth0 结果如下:

read ret 59 byte eth0: flags=4163 mtu 1500

这里可以看到,结果是符合我们预期的

为什么我会在这里放一个 ifconfig eth0 的命令呢?我自己给自己挖的bug就在这了 ╮(╯▽╰)╭

因为在封装一个函数时,功能是判断某个网卡是否存在?然后就需要用到这个命令嘞

3、具体问题

让我们来看一下,bug到底是什么

还是上面那个示例代码,但是将那个执行的命令改一下:

执行 ifconfig bughere 结果如下:

bughere: error fetching interface information: Device not found read ret 0 byte

这里我们可以看到,它确实有输出,输出就是bughere:…

但是发现什么问题没有?read ret 0 byte , 并没有读到数据,而且这两个输出的顺序好像不太一样~~~

让我们再看一组结果:

执行 ls -l popenbug2 结果如下:

ls: cannot access 'popenbug2': No such file or directory read ret 0 byte

又是这样让人难以接受的结果

为什么会这样呢???

4、问题分析并解决

一开始,我实在不能理解,也不相信,难道读到的数据真的是0个字节嘛???

于是我想到把该(ret)空间的首地址的数据打印一下看看

ls: cannot access 'popenbug2': No such file or directory read ret 0 byte ret buf: ret ascii: 0x0

这个结果彻底打消了我的念头 ≧ ﹏ ≦

popen确实没有获取到任何数据

于是我只能从popen函数本身出发,去反复检查关于popen函数的定义,返回值等等。。。

如果调用 fork() 或 pipe() 失败,或者不能分配内存将返回NULL,否则返回标准 I/O 流。

一开始,我并没有完全理解这句话,我天真的以为:执行的命令有输出,就是fork()成功调用了,理应返回标准I/O流,但是事与愿违。。。

最后我想到了检查popen执行的命令在命令行执行的返回值

在这里插入图片描述

​ 然后还真让我发现了问题,凡是带有No、not found等等类型字样的(文件找不到啊、网卡不存在啊),也就是你请求的命令,没有得到你想要的结果的(命令输错,内容不存在),这些命令的返回值都是大于零的,而命令得到正确回复的,返回值都是零。

​ 而且最终的结果也是命令行返回值不是0的,都无法被popen函数获取到I/O流,带着这个收获,又去琢磨了一番popen函数的相关定义和返回值说明,终于是琢磨出了味道来。。。 ( •̀ ω •́ )y

​ 这是一个很简单的问题,但是从头到尾都完完全全的被我给忽略了

如果 type 是 “r” 则文件指针连接到 command 的标准输出;如果 type 是 “w” 则文件指针连接到 command 的标准输入。

问题就在这啊,命令执行有问题的,那是标准出错啊,哪里是什么标准输出啊,忽略了这个问题,绕了一个大圈子,最后又回来了 /(ㄒoㄒ)/~~

所以,使用的函数一定要清楚其用法和定义,一定不要出错

最后,不要忘记。除了标准输入、输出,它还有一个标准出错啊

5、补充——Linux命令行返回值

在Linux下,不管你是启动一个桌面程序也好,还是在控制台下运行命令。所有的程序在结束时.都会返回一个数字值、这个值叫做返回值或者称为错误号(Error Number )。

​ 在控制台下,有一个特殊的环境变量"$?",保存着前一个程序的返回值,上面已经用过了。

这里有个错误对照表: https://wenku.baidu.com/view/36a4e12b497302768e9951e79b89680203d86b28.html



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有