2014-07-02 60 views
0

在Linux中,我使用“pidof process_name”命令打开管道,然后使用fgets函数读取输出,从而找到进程的pid。但它偶尔会发现一次失败。以下是我的代码,用于查找我的流程的pid。使用popen函数读取命令输出失败

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; 
} 

即使进程在“ps”命令输出中可用,输出中也有时会出现pid = 0。 所以,我试图找到这个问题背后的根本原因,我发现像输入/输出缓冲机制可能在我的方案中创建问题。

所以我尝试在打开popen()之前使用sync()函数,奇怪的是我的函数开始以100%的精度工作。

现在sync()函数花费太多时间(大约2分钟)来完成它的执行,这是不可取的。所以我尝试使用fflush(),fsync()和fdatasync(),但这些都不能正常工作。

所以请任何人告诉我这个问题背后的确切根源以及如何正确解决这个问题?

+0

我不明白你的'while'循环 - 你只是调用'popen'一次,你为什么而循环读取输出? – Ariel

+0

抱歉误会,这只是我用来编写函数的编码格式。它在这里没有意义,因为它是(0)。它不会被循环。 – ravibhuva9955

+0

当'pid'为'0'时,'line'的内容是什么? – Ariel

回答

2

好吧,错误的根本原因存储在errno变量(这btw你不需要初始化)。您可以使用温控功能

perror("Error: "); 

如果u使用PERROR的变量errno解释得到通知消息,你会得到一个描述性的消息。

查找根本原因的另一种方式(正确方法)是使用-g标志编译程序并使用gdb运行二进制文件。

编辑:我强烈建议使用gdb调试器,以便您可以确切地查看代码遵循的路径,以便您可以解释所描述的奇怪行为。

第二编辑:Errno存储最后一个错误(返回值)。而不是调用函数为你做什么,你应该写,并立即检查错误号:

if ((<function>) <0) { 
    perror("<function>: "); 
    exit(1); 
} 
+0

我很欣赏你的想法。但我已经使用gdb进行调试以查找根本原因。这里的东西是没有输出是在fgets()尝试读取FILE *时进入的。所以这是我的一些I/O缓冲机制的问题。 – ravibhuva9955

+0

@ ravibhuva9955 fgets()返回什么?您可以使用strace命令来监视程序的系统调用(包括I/O操作)。 – sestus

+0

fgets在这种情况下返回NULL。 – ravibhuva9955