如何在 C 程序运行时正确调用可执行文件?

How to properly call an executable in C program runtime?

我有一个 C 应用程序,其工作之一是调用可执行文件。该文件在编译期间在中间代码级别插入了性能测量例程。它可以测量时间或 L1/L2/L3 缓存未命中。换句话说,我已经修改了 LLVM 编译器以插入对该函数的调用并将结果打印到任何已编译程序的 stdout

现在,就像我在开头提到的那样,我想从一个单独的 C 应用程序中执行程序(并将此结果返回给 stdout)并保存该结果。我现在的做法是:

void executeProgram(const char* filename, char* time) {
    printf("Executing selected program %s...\n", filename);
    char filePath[100] = "/home/michal/thesis/Drafts/output/";
    strcat(filePath, filename);
    FILE *fp;
    fp = popen(filePath, "r");
    char str[30];
    if (fp == NULL) {
        printf("Failed to run command\n" );
        exit(1);
    }
    while (fgets(str, sizeof(str) - 1, fp) != NULL) {
        strcat(time, str);
    }
    pclose(fp);
}

其中 filename 是编译后的可执行文件的名称 运行。结果保存到 time 字符串。

问题是,与通过简单地从命令行 运行 运行可执行文件 'by hand' 返回的结果相比,我得到的结果非常不同且不稳定 (./test16).它们看起来像:

231425 
229958 
230450 
228534 
230033 
230566 
231059 
232016 
230733 
236017 
213179 
90515 
229775 
213351 
229316 
231642 
230875 

所以它们大多在 230000 us 左右,偶尔会有一些下降。另一个应用程序中的相同可执行文件 运行 生成:

97097 
88706 
91418 
97970 
97972 
94597 
95846 
95139 
91070 
95918 
107006 
89988 
90882 
91986 
90997 
88824 
129136 
94976 
102191 
94400 
95215 
95061 
92115 
96319 
114091 
95230 
114500 
95533 
102294 
108473 
105730 

请注意,调用的是 相同的 可执行文件。然而它 returns 的测量时间是不同的。正在测量的程序包括对简单嵌套循环的函数调用,访问数组元素。这是代码:

#include "test.h"
#include <stdio.h>

float data[1000][1000] = {0};


void test(void)
{
    int i0, i1;
    int N = 80;
    float mean[1000];
    for (i0 = 0; i0 < N; i0++)
    {
        mean[i0] = 0.0;
        for (i1 = 0; i1 < N; i1++) {
            mean[i0] += data[i0][i1];
        }
        mean[i0] /= 1000;
    }
}

我怀疑在代码中调用程序的方式有问题,也许应该分叉进程或其他什么?有什么想法吗?

您没有指定时间测量子程序的确切插入位置,所以我只能提供猜测。

结果似乎暗示恰恰相反 - 运行从 shell 启动应用程序速度较慢,因此我不会担心您从 C 启动进程的方式代码。我的猜测是 - 当您 运行 来自 shell 的程序时,是终端拖慢了您的速度。当您从 C 代码 运行ning 进程时,您将输出通过管道返回到您的 'starter' 应用程序,该应用程序已经在管道上等待输入。

作为旁注,考虑从 strcat 切换到更安全的东西,例如 strncat