2014-02-05 5 views
4

Прямо сейчас, мне нужно запустить внешний процесс в C. В настоящее время я использую posix_spawn для создания процесса. Необходимо, чтобы я мог контролировать, завершился ли процесс. Мне нужно также иметь ссылку на стандарт вне процесса. Я посмотрел на использование popen, однако он не обеспечивает «легкий» способ получения pid. Я медленно схожу с ума, так как не может быть так сложно получить стандартное выполнение текущего процесса в Linux.Получить stdout уже запущенного процесса в Linux в C

Кроме того, в следующем примечании мне нужна помощь в расшифровке того, что означает параметр file_actions. человек (3) для posix_spawn по этой теме говорит:

Если file_actions не NULL, то файловые дескрипторы открытых в дочернем процессе, должны быть те, открытым в процессе вызова, как модифицируется икру файлов действий указываемого объекта файловыми файлами и флагом FD_CLOEXEC каждого оставшегося дескриптора открытого файла после обработки действий файла spawn.

Если это не определение вступительного предложения, я понятия не имею, что это такое.

+0

Когда вы говорите STD_OUT, вы имеете в виду PID? – suspectus

+0

Нет, я имею в виду STD_OUT. Мне нужен стандартный вывод процесса с заданным PID, который я получаю от его создания с помощью posix_spawn. – alekpr

+0

Возможно, вы хотите [popen (3)] (http://man7.org/linux/man-pages/man3/popen.3.html), иначе я не понимаю ваш вопрос. Прочитайте [Расширенное программирование Linux] (http://advancedlinuxprogramming.com/) –

ответ

6

Поскольку у вас есть PID (возвращается с posix_spawn), и вы работаете под управлением Linux, вы обнаружите, что процесс начинается с /proc/<pid>/fd/1. Просто open (или fopen) файл для чтения.

Стандартным способом является использование fork. Используйте pipe и dup2, чтобы получить файловый дескриптор для чтения выходных данных ребенка, как в this question.

+1

Кроме того, предпочитайте 'fork', чтобы избежать малого состояния гонки (процесс, возможно, умер до вызова' open') –

+1

Спасибо, мне было интересно, что все записи в/proc//fd представлены. Я действительно пытаюсь избежать использования fork/pipe/dup2, но похоже, что мне, возможно, придется это сделать. – alekpr

+1

Эти записи в proc - это дескрипторы открытых файлов для соответствующего процесса. –

3

Вы можете использовать posix_spawn для этого, не используя возможности, связанные с расой, для Linux /proc/<pid>/fd/N. Вы можете сохранить все преимущества posix_spawn.

Вы были на правильном пути, думая о file_actions. Ниже приведен пример, который выводит исходный код дочернего элемента в тройных кавычках в стиле Python, а также код выхода ребенка из родительского процесса, используя posix_spawn и file_actions.

Вот пример примера вывода.

child pid: 17468 
child exit status: 0 
child stdout: 
"""Hello World! 
""" 

Вот пример.

#define _DEFAULT_SOURCE 
#include <spawn.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/wait.h> 

extern char **environ; 

static void dump_child_stdout(int filedes) 
{ 
    ssize_t num_read; 
    char buf[1]; 

    printf("child stdout:\n\"\"\""); 
    for (;;) 
    { 
     num_read = read(filedes, buf, sizeof(buf)); 
     if (num_read > 0) 
     { 
      printf("%c", buf[0]); 
     } 
     else 
     { 
      break; 
     } 
    } 
    printf("\"\"\"\n"); 
} 

int main(int argc, char *argv[]) 
{ 
    int status; 
    pid_t pid; 
    int out[2]; 
    posix_spawn_file_actions_t action; 
    char *args[] = {"/bin/echo", "Hello World!", NULL }; 

    posix_spawn_file_actions_init(&action); 

    pipe(out); 

    posix_spawn_file_actions_adddup2(&action, out[1], STDOUT_FILENO); 
    posix_spawn_file_actions_addclose(&action, out[0]); 

    status = posix_spawn(&pid, args[0], &action, NULL, args, environ); 
    if (status == 0) 
    { 
     printf("child pid: %d\n", pid); 
     if (waitpid(pid, &status, 0) < 0) 
     { 
      perror("waitpid"); 
     } 
     else 
     { 
      if (WIFEXITED(status)) 
      { 
       printf("child exit status: %d\n", WEXITSTATUS(status)); 
      } 
      else 
      { 
       printf("child died an unnatural death.\n"); 
      } 

      close(out[1]); 
      dump_child_stdout(out[0]); 
     } 
    } 
    else 
    { 
     fprintf(stderr, "posix_spawn: %s\n", strerror(status)); 
     close(out[1]); 
    } 

    posix_spawn_file_actions_destroy(&action); 

    return 0; 
} 
+0

Важно отметить, что буфер не завершен нулем. Это может вызвать проблемы, если вы хотите создать строку из возвращаемых символов. – Dula

Смежные вопросы