захват вывода командной строки непосредственно в буфере - PullRequest
0 голосов
/ 19 января 2010

Я хочу выполнить команду, используя команду system () или execl, и хочу записать вывод непосредственно в буфер в C. Есть ли возможность записать вывод в буфер, используя системный вызов dup () или pipe ().Я не хочу использовать какой-либо файл между использованием mkstemp или любой другой временный файл.Пожалуйста, помогите мне в этом. Спасибо заранее.

Я пробовал это с помощью fork (), создавая два процесса и передавая выходные данные, и это работает. Однако я не хочу использовать системный вызов fork, так как собираюсь запуститьмодуль бесконечно использует отдельный поток, и он вызывает много fork (), а система иногда исчерпывает ресурсы.

Чтобы понять, что я делаю, это захват вывода сценария оболочки в буфереобработать вывод и отобразить его в окне, которое я спроектировал с помощью ncurses. Спасибо.

Ответы [ 5 ]

1 голос
/ 19 января 2010

Вот некоторый код для захвата вывода программы;он использует exec () вместо system (), но это легко сделать, вызвав оболочку напрямую:

Как я могу программно реализовать 'tee' в C?

void tee(const char* fname) {
    int pipe_fd[2];
    check(pipe(pipe_fd));
    const pid_t pid = fork();
    check(pid);
    if(!pid) { // our log child
        close(pipe_fd[1]); // Close unused write end
        FILE* logFile = fname? fopen(fname,"a"): NULL;
        if(fname && !logFile)
                fprintf(stderr,"cannot open log file \"%s\": %d (%s)\n",fname,errno,strerror(errno));
        char ch;
        while(read(pipe_fd[0],&ch,1) > 0) {
                //### any timestamp logic or whatever here
                putchar(ch);
                if(logFile)
                        fputc(ch,logFile);
                if('\n'==ch) {
                        fflush(stdout);
                        if(logFile)
                                fflush(logFile);
                }
        }
        putchar('\n');
        close(pipe_fd[0]);
        if(logFile)
                fclose(logFile);
        exit(EXIT_SUCCESS);
    } else {
        close(pipe_fd[0]); // Close unused read end
        // redirect stdout and stderr
        dup2(pipe_fd[1],STDOUT_FILENO);  
        dup2(pipe_fd[1],STDERR_FILENO);  
        close(pipe_fd[1]);  
    }
}
0 голосов
/ 19 января 2010

Вы хотите использовать последовательность, подобную этой:

Call pipe once per stream you want to create (eg. stdin, stdout, stderr)
Call fork
in the child
   close the parent end of the handles
   close any other handles you have open
   set up stdin, stdout, stderr to be the appropriate child side of the pipe
   exec your desired command
   If that fails, die.

in the parent
   close the child side of the handles
   Read and write to the pipes as appropriate
   When done, call waitpid() (or similar) to clean up the child process.

Остерегайтесь блокирования и буферизации. Вы не хотите, чтобы ваш родительский процесс блокировал запись, в то время как дочерний процесс блокировался на чтение; убедитесь, что вы используете неблокирующий ввод / вывод или потоки для решения этих проблем.

0 голосов
/ 19 января 2010

Вы можете попробовать popen(), но ваша основная проблема заключается в слишком большом количестве процессов. Вы должны убедиться, что ваши команды завершены, в противном случае вы получите именно те проблемы, которые у вас возникли. popen() внутренне вызывает fork() в любом случае (или эффект такой, как если бы он это делал).

Итак, в итоге, вы должны убедиться, что программа, которую вы хотите запустить из ваших потоков, завершается "достаточно быстро".

0 голосов
/ 19 января 2010

Простой способ - использовать popen (http://www.opengroup.org/onlinepubs/007908799/xsh/popen.html),, который возвращает FILE*.

0 голосов
/ 19 января 2010

Если вы внедрили программу на C и хотите выполнить скрипт, вы хотите использовать fork (). Если вы не хотите встраивать интерпретатор сценариев в вашу программу, вам придется использовать fork () (system () использует fork () внутри).

Если у вас заканчиваются ресурсы, скорее всего, вы не пожинаете своих детей. До тех пор, пока родительский процесс не получит код выхода, ОС нуждается в том, чтобы дочерний процесс оставался «процессом зомби». Вам нужно выполнить вызов wait () , чтобы ОС освободила окончательные ресурсы, связанные с дочерним элементом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...