1

我使用管道读取了执行程序的标准输出:

int pipes[2];
pipe(pipes);
if (fork() == 0) {
    dup2(pipes[1], 1);
    close(pipes[1]);
    execlp("some_prog", "");
} else {
    char* buf = auto_read(pipes[0]);
}

要从标准输出读取,我有一个函数auto_read可以根据需要自动分配更多内存。

char* auto_read(int fp) {
    int bytes = 1000;
    char* buf = (char*)malloc(bytes+1);
    int bytes_read = read(fp, buf, bytes);
    int total_reads = 1;
    while (bytes_read != 0) {
        realloc(buf, total_reads * bytes + 1);
        bytes_read = read(fp, buf + total_reads * bytes, bytes);
        total_reads++;
    }
    buf[(total_reads - 1) * bytes + bytes_read] = 0;
    return buf;
}

我这样做的原因是我不知道程序会提前吐出多少文本,而且我不想创建一个过大的缓冲区并成为内存占用者。我想知道是否有:

  1. 一种更简洁的方式来写这个。
  2. 执行此操作的内存或速度效率更高的方法。
4

1 回答 1

4

如果popen您只需要从进程中读取并且在 *NIX 平台上,请使用:

FILE *programStdout = popen("command", "r");

// read from programStdout (fread(), fgets(), etc.)
char buffer[1024];

while (fgets(buffer, 1024, programStdout))
{
    puts(buffer);
}

编辑:您要求一种将程序输出映射到文件的方法,所以在这里:

#import <stdio.h>
#import <unistd.h>
#import <sys/mman.h>

void *dataWithContentsOfMappedProgram(const char *command,  size_t *len)
{
    // read the data
    char template[] = "/tmp/tmpfile_XXXXXX";
    int fd = mkstemp(template);

    FILE *output = fdopen(fd, "w+");
    FILE *input = popen(command, "r");

#define BUF_SIZ 1024
    char buffer[BUF_SIZ];
    size_t readSize = 0;
    while ((readSize = fread(buffer, 1, BUF_SIZ, input)))
    {
        fwrite(buffer, 1, readSize, output);
    }
    fclose(input);

    input = NULL;
#undef BUF_SIZ

    // now we map the file
    long fileLength = ftell(output);
    fseek(output, 0, SEEK_SET);

    void *data = mmap(NULL, fileLength, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, 0);

    close(fd);

    if (data == MAP_FAILED)
        return NULL;

    return data;
}


int main()
{
    size_t fileLen = 0;
    char *mapped = dataWithContentsOfMappedProgram("echo Hello World!", &fileLen);

    puts(mapped);

    munmap(mapped, fileLen);
}
于 2012-06-21T00:32:03.663 回答