【问题标题】:Fail to read command output using popen function使用 popen 函数读取命令输出失败
【发布时间】:2014-07-02 09:34:11
【问题描述】:

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

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

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

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

所以请任何人告诉我这个问题背后的确切根本原因是什么以及如何适当地解决这个问题?

【问题讨论】:

  • 我不明白你的 while 循环 - 你只调用一次 popen,为什么你在读取输出时循环?
  • 抱歉误会,这只是我用来编写函数的编码格式。它在这里没有意义,因为它是while(0)。不会循环播放。
  • pid0line的内容是什么?
  • 行变量为空。看到它工作了 100 次,但不知何故它失败了,你可以说它失败了 100 次。
  • 添加一些运行 perror 的代码,如果 fgets 返回 null 并告诉我们错误消息是什么。

标签: c linux process popen pid


【解决方案1】:

好的,错误的根本原因存储在 errno 变量中(顺便说一句,您不需要初始化该变量)。您可以使用功能获取信息性消息

perror("Error: ");

如果你使用 perror 变量 errno 被解释并且你得到一个描述性的消息。

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

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

第二次编辑:Errno 存储最后一个错误(返回值)。您应该编写并立即检查 errno,而不是像您一样调用函数:

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

【讨论】:

  • 我很欣赏你的想法。但是我已经使用 gdb 进行了调试以找到根本原因。这里的问题是在尝试读取 FILE* 时 fgets() 中没有输出。所以这是我的一些 i/o 缓冲机制的问题。
  • @ravibhuva9955 fgets() 返回什么?您可以使用 strace 命令来监控程序的系统调用(包括 I/O 操作)。
  • fgets 在这种情况下返回 NULL。
  • 好的,fgets 返回 null 的一种情况(高于所有其他错误)是 EOF 时。你能确认不是吗?因为如果它是 EOF(管道上没有可读取的内容),这是正常行为
猜你喜欢
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 2017-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 2013-12-28
相关资源
最近更新 更多