在C/C++程序中调用popen来执行cmd命令,且用fgets来读命令的打印,读到最后一个字节之后就陷入无尽等待

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在C/C++程序中调用popen来执行cmd命令,且用fgets来读命令的打印,读到最后一个字节之后就陷入无尽等待相关的知识,希望对你有一定的参考价值。

代码主要是

int execmd(const char *cmd,char* result)

char buf[128]=0;
FILE *pipe = _popen(cmd,"r");
int i = 0;
char c;
if(!pipe)
return -1;
while(!feof(pipe))
if(fread(&c,1,1,pipe)==1)

result[i++]=c;

if(c==0)

break;



result[i]=0;
_pclose(pipe);
return 0;

输入一个命令,得到的是打印在result中
我调用的是adb命令,如果在cmd界面执行 adb start-server,在本程序执行“adb devices”没问题。
如果先kill server,再本程序执行adb start-server,则读pipe可以读到cmd命令下同样的打印,只是到最后一个字符(换行符)之后,就永久停留在fread语句中。此时在cmd界面,执行adb kill-server,程序又活了。求问怎么破解这个局
没什么分,全给了,以后有分了可以再追加,拜托
补充下是win32系统下,
问题的关键似乎是为什么读的时候读不到结束符,管道另外一边不放手,也不写,所以读的这一边吊在这里,所以一旦kill server,就释放了,程序就活了,不然就吊死在那里,求问可有什么办法解决这种吊死的情况

参考技术A 起码你的代码有一个漏洞:第一次进入while时,!feof(pipe)是在判断谁?说明你对feof()这个函数并没有掌握,它必须在逻辑上“紧跟”在读文件动作之后才能正确生效,这第一次是“紧跟”在哪个读动作之后?到了文件结尾处就更可笑了:经while(!feof(pipe))判断文件还没有结束,比如说文件中还剩一个最后的'\n',可是体中的if(fread(&c,1,1,pipe)==1)中的fread函数还能读到什么?细节我就不说了,太长。建议把
while(!feof(pipe))
if(fread(&c,1,1,pipe)==1)
result[i++]=c;
if(c==0)
break;


这一段改成
while(fread(&c,1,1,pipe),!feof(pipe))
result[i++]=c;
//if(c==0)//这两句考虑一下吧,文件中有0吗?不可能有0,所以逻辑就有问题,建议删除
//break;

一试。
这里有一点好多网友没弄清,那就是feof()函数本身不读文件,只检查最近一次读动作越界(跨过文件结束符读)了没有。可续问。追问

这里的关键是本来大部分命令都可以正常运行,唯独在某个情况下不行,似乎pipe一直没出现EOF标志,我一开始还用fgets试过,都一样
这个修改我也试过了,一样的现象
文件中读到最后确实剩余了一个“\n",是一个额外空行的换行符,读完这个之后,feof判断文件没读到末尾,这时候继续用fread或者fgets,都直接挂在这里的,读不到东西,也释放不了

追答

把你的命令文件内容传过来一些,我给你做。按我改的,不可能有你追问中说的情况……

本回答被提问者和网友采纳

如何在C语言中调用shell命令

在C语言中调用shell命令的方法实现。
C程序调用shell脚本共有两种方法 :system()、popen(),分别如下:
system()
不用自己去创建进程,系统已经封装了这一步,直接加入自己的命令即可
popen() 也可以实现执行的命令,比system
开销小
以下分别说明:
1)system(shell命令或shell脚本路径);
system()
会调用fork()产生 子历程,由子历程来调用/bin/sh-c string来履行 参数string字符串所代表的命令,此命令履行
完后随即返回原调用的历程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被漠视 。

回值:如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值。 如果
system()调用成功 则最后会返回履行 shell命令后的返回值,但是此返回值也有可能为system()调用/bin/sh失败所返回的127,因
此最好能再反省 errno 来确认履行 成功 。
system命令以其简略
高效的作用得到很很广泛 的利用 ,下面是一个例子
例:在/tmp/testDir/目录下有shell脚本tsh.sh,内容为

#!/bin/sh
wget $1
echo "Done!"
2)popen(char
*command,char *type)
popen()
会调用fork()产生 子历程,然后从子历程中调用/bin/sh -c来履行 参数command的指令。参数type可应用
“r”代表读取,“w”代表写入。遵循此type值,popen()会建立 管道连到子历程的标准 输出设备 或标准 输入设备
,然后返回一个文件指针。随后历程便可利用 此文件指针来读取子历程的输出设备 或是写入到子历程的标准 输入设备 中。此外,所有应用 文
件指针(FILE*)操作的函数也都可以应用 ,除了fclose()以外。
返回值:若成功
则返回文件指针,否则返回NULL,差错 原因存于errno中。注意:在编写具SUID/SGID权限的程序时请尽量避免应用
popen(),popen()会继承环境变量,通过环境变量可能会造成系统安全的问题。
例:C程序popentest.c内容如下:
#include<stdio.h>
main

FILE * fp;
charbuffer[80];
fp=popen(“~/myprogram/test.sh”,”r”);
fgets(buffer,sizeof(buffer),fp);
printf(“%s”,buffer);
pclose(fp);
参考技术A 有个函数是 command 直接调用就可以了 参考技术B system("")

~~~~~~~~~~~

以上是关于在C/C++程序中调用popen来执行cmd命令,且用fgets来读命令的打印,读到最后一个字节之后就陷入无尽等待的主要内容,如果未能解决你的问题,请参考以下文章

如何在C语言中调用shell命令

如何在C语言中调用shell命令

如何在C语言中调用cmd命令?

linux下如何用c语言调用shell命令

linux下如何用c语言调用shell命令

C/C++程序中的event该如何理解