【问题标题】:Combined system() and popen()?组合 system() 和 popen()?
【发布时间】:2017-01-30 21:56:15
【问题描述】:

Edit2:考虑一下,这里可能是一个更好的问题:

如果我使用 popen 写入 sysfs 文件,它会阻塞直到写入完成,但不会等待 sysfs 文件完成处理。我怎样才能等待那个 sysfs 文件完成它正在做的事情?

我想在程序中运行一个命令,等待它完成(这将需要几秒钟)并将终端输出返回给我,而不是将其打印到控制台。

通过阅读其他问题,我看到system()exec() 调用可用于运行命令。然而,这些并没有给你终端的输出,所以你需要做一些笨拙的事情,比如写入一个文件,然后打开并读取那个文件,然后删除它。

我看到的另一个选项是popen(),它提供了一个文件描述符,您可以使用它来获取终端输出。但是,这似乎并没有等待命令完成,这导致我的程序有点搞砸了。

那么我怎样才能获得 popen 的功能,同时强制它等待子进程完成后再做其他事情呢?

编辑:这是我目前正在做的事情:

#include <stdio.h>

int main(){
    FILE *file;
    char terminal[512];

    sprintf(terminal,"/bin/cat /home/Config/BASE_SETTINGS.bin > /sys/bus/iio/devices/iio\:device3/profile_config");
    if(!(file=popen(terminal,"r"))){return -1;}
    while(fgets(terminal,sizeof(terminal),file)!=NULL){
        printf("%s\n", terminal);
    }
    pclose(file);
}

这是程序的一部分,我做了几次同样的事情,只是每次都改变“sprintf”中的命令。据我所知 pclose 应该阻止。但是,当我从终端运行命令时,写入 sysfs 文件后需要几秒钟才能完成配置。但是,当我通过程序执行此操作时,程序运行时间不到一秒。

因为我的程序中后面的命令依赖于正在配置的 sysfs 驱动程序,并且它似乎在 sysfs 进程完成之前执行后面的命令,所以后面的命令失败,因为它们最终在配置完成之前运行.

【问题讨论】:

  • popen() 确实等待。另请参阅 pclose()
  • 请出示您的代码。 popen 不会等待,但 pclose 会。但是您的问题可能会受到XY problem 的影响(询问您尝试的解决方案而不是您的实际问题)。请提供“导致我的程序搞砸”的详细信息,以便我们更容易指出解决实际问题的正确方法(它可能涉及也可能不涉及popen)。
  • 只是一个细节:popen() 为您提供文件流 (FILE *),而不是文件描述符 (int)。
  • 如果您循环读取通过popen() 运行的命令的输出,读取代码应该挂起,直到有更多数据或命令终止(更准确地说,关闭您正在读取的标准输出过程)。此时,您将收到指示 EOF 的读取错误。没有您的代码,很难知道您做错了什么。
  • @kaylum 我添加了我正在使用的代码的 sn-p

标签: c system


【解决方案1】:

pclose() 和 _pclose()(在 Windows 上)将阻塞,直到子进程的执行完成。要获得输出,只需使用 FILE 指针打开它们并使用 fgets 读取它们。请参阅以下示例(适用于 win32 和 unix 系统):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined(_WIN32)
    #include <Windows.h>
#else
    #include <unistd.h>
#endif

#ifndef PATH_MAX
    #define PATH_MAX 255 //Usually defined in <Windows.h>
#endif

FILE *popenHandler(const char *args, const char *method)
{
    #if defined(_WIN32)
        return _popen(args, method);
    #else
        return popen(args, method);
    #endif
}

int pcloseHandler(FILE *fp)
{
    #if defined(_WIN32)
        return _pclose(fp);
    #else
        return pclose(fp);
    #endif
}

int main()
{
    FILE *fp; //file pointer to point to command
    char path[PATH_MAX]; //char buffer to store output

#if defined(_WIN32)
    char command[PATH_MAX] = "dir"; //command to execute
#else
    char command[PATH_MAX] = "ls -l"; //command to execute
#endif

    //If you want to include stderr in the results, uncomment the below string
    //strncpy(command, " 2>&1", PATH_MAX); //Merges stderror with stdout

    fp = popenHandler(command, "r"); //function to work on win32 or unix
    if (fp == NULL) {
        printf("ERROR: Failed to execute command %s\n", command);
        return -1;
    }
    int lineNumber = 0;
    while (fgets(path, PATH_MAX, fp) != NULL) {
        printf("Line #%i of output from command: %s\n", lineNumber++, path);
    }
    int returnValue = pcloseHandler(fp); //Make sure to close!
    printf("The sub-process returned %i\n", returnValue);
}

【讨论】:

  • 我所看到的似乎并没有遵循这一点。我正在写入 sysfs 文件以加载一些配置。当我从命令提示符处执行此操作时,sysfs 需要几秒钟才能完成它所做的任何事情。但当。我在一个程序中执行此操作,程序立即完成。这让我觉得程序在配置正确加载之前正在运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 2011-08-06
相关资源
最近更新 更多