C 无法使用popen函数读取命令输出
在Linux中,我通过使用“pidof process_name”命令打开管道,然后使用fgets函数读取其输出来查找进程的pid。但它偶尔也找不到pid。下面是查找进程pid的代码C 无法使用popen函数读取命令输出,c,linux,process,popen,pid,C,Linux,Process,Popen,Pid,在Linux中,我通过使用“pidof process_name”命令打开管道,然后使用fgets函数读取其输出来查找进程的pid。但它偶尔也找不到pid。下面是查找进程pid的代码 int FindPidByProcessName(char *pName) { int pid = -1; char line[30] = { 0 }; char buf[64] = { 0 }; sprintf(buf, "pidof %s", pName); //pi
int FindPidByProcessName(char *pName)
{
int pid = -1;
char line[30] = { 0 };
char buf[64] = { 0 };
sprintf(buf, "pidof %s", pName);
//pipe stream to process
FILE *cmd = popen(buf, "r");
if (NULL != cmd)
{
//get line from pipe stream
fgets(line, 30, cmd);
//close pipe
pclose(cmd); cmd = NULL;
//convert string to unsigned LONG integer
pid = strtoul(line, NULL, 10);
}
return pid;
}
在输出中,有时pid=0出现,即使进程在“ps”命令输出中可用。
所以,我试图找到这个问题背后的根本原因,我发现输入/输出缓冲机制可能会在我的场景中产生问题
所以我在打开popen()之前尝试使用sync()函数,奇怪的是,我的函数开始以100%的精度工作
现在sync()函数需要花费太多的时间(有时大约2分钟)来完成它的执行,这是不可取的。所以我尝试使用fflush()、fsync()和fdatasync(),但这些都不能正常工作
因此,请告诉我这个问题背后的确切根本原因是什么,以及如何适当地解决这个问题?好的,错误的根本原因存储在errno变量中(顺便说一句,您不需要初始化该变量)。您可以使用该功能获取信息性消息
perror("Error: ");
如果使用perr,则会解释变量errno,并得到一条描述性消息
找到根本原因的另一种方法(正确的方法!)是使用-g标志编译程序,并使用gdb运行二进制文件
编辑:我强烈建议使用gdb调试器,这样您就可以准确地查看代码遵循的路径,从而可以解释您描述的奇怪行为
第二次编辑:Errno存储最后一个错误(返回值)。您应该立即编写并检查errno,而不是像这样调用函数:
if ((<function>) <0) {
perror("<function>: ");
exit(1);
}
如果(()我不理解你的while
循环-你只调用了一次popen
,为什么你在读取输出时循环?很抱歉误解,这只是我用来编写函数的编码格式。它在这里没有意义,因为它是while(0)。它不会循环。当pid
为0
时,line
的内容是什么?line变量为空。查看它工作100次,但不知何故它无法工作,您可以说它每100次失败一次。如果fgets
返回null,请添加一些运行peror
的代码,并告诉我们错误消息是的。我很欣赏你的想法。但我已经使用gdb进行了调试,以找到根本原因。这里的问题是,当尝试读取文件*时,fgets()中没有输出。因此,这是我的一些I/o缓冲机制的问题。@ravibhuva9955 fgets()返回什么?您可以使用strace命令监视程序的系统调用(包括I/O操作)。在这种情况下,fgets返回NULL。好的,fgets返回NULL的一种情况(首先是所有其他错误)是当它是EOF时。您能确认它不是吗?因为如果它是EOF(在管道上没有读取内容),这是一种正常行为