C 无法使用popen函数读取命令输出

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

在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);

    //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(在管道上没有读取内容),这是一种正常行为