Как вы порождаете другой процесс в C? - PullRequest
27 голосов
/ 20 августа 2008

Как запустить внешнюю программу и передать ей параметры командной строки, используя C? Если вам нужно использовать API операционной системы, включите решение для Windows, Mac и Linux.

Ответы [ 8 ]

16 голосов
/ 21 августа 2008

Это действительно зависит от того, что вы пытаетесь сделать, именно так:

  1. ОС зависит
  2. Не совсем понятно, что вы пытаетесь сделать.

Тем не менее, я постараюсь предоставить вам некоторую информацию для принятия решения.
В UNIX fork() создает клон вашего процесса из того места, где вы назвали fork. Смысл, если у меня следующий процесс:

#include <unistd.h>
#include <stdio.h>

int main()
{
    printf( "hi 2 u\n" );
    int mypid = fork();

    if( 0 == mypid )
        printf( "lol child\n" );
    else
        printf( "lol parent\n" );

    return( 0 );
}

Вывод будет выглядеть следующим образом:

привет 2 u
лол ребенок
лол родитель

Когда вы fork(), pid, возвращаемый в потомке, равен 0, а pid, возвращаемый в родительском элементе, - это pid ребенка. Обратите внимание, что "hi2u" печатается только один раз ... родителем .

execve() и его семейство функций почти всегда используются с fork(). execve() и т. П. Перезаписывают текущий стековый фрейм именем приложения, которое вы передаете ему. execve() почти всегда используется с fork(), когда вы разветвляете дочерний процесс, и если вы родитель, вы делаете все, что вам нужно, а если вы - ребенок, вы запускаете новый процесс. execve() также почти всегда используется с waitpid() - waitpid берет pid дочернего процесса и, буквально, ждет , пока ребенок не завершит работу, и вернет вам статус выхода ребенка.

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

ПРИМЕЧАНИЕ. Это * * nix! Это НЕ будет работать в Windows.

Надеюсь, это помогло.

15 голосов
/ 20 августа 2008

Если вы хотите выполнять более сложные операции, такие как чтение выходных данных внешней программы, вам может лучше помочь системный вызов popen . Например, чтобы программно получить доступ к списку каталогов (это несколько глупый пример, но полезный как пример), вы можете написать что-то вроде этого:

#include <stdio.h>

int main()
{
  int entry = 1;
  char line[200];
  FILE* output = popen("/usr/bin/ls -1 /usr/man", "r");
  while ( fgets(line, 199, output) )
  {
    printf("%5d: %s", entry++, line);
  }
}

чтобы вывести вот так

1: cat1
2: cat1b
3: cat1c
4: cat1f
5: cat1m
6: cat1s
...
12 голосов
/ 20 августа 2008
#include <stdlib.h>

int main()
{
    system("echo HAI");

    return 0;
}
5 голосов
/ 28 декабря 2012

Я хочу дать большое предупреждение не использовать систему и 100% никогда не использовать систему, когда вы пишете библиотеку. Он был разработан 30 лет назад, когда многопоточность была неизвестна операционной системе Unix. И он по-прежнему не может использоваться, даже если сегодня почти все программы многопоточные.

Используйте popen или выполните fork + execvp, все остальное затруднит обнаружение проблем с обработкой сигналов, сбоями в коде обработки среды и т. Д. Это чистое зло и позор, что выбранный и наиболее оцененный ответ способствует использованию "системы". Более полезно пропагандировать использование кокаина на рабочем месте.

4 голосов
/ 20 августа 2008

В UNIX, я думаю, вам, в основном, нужно его разветвить, если вы хотите, чтобы порожденный процесс запускался отдельно от порождающего: например, если вы не хотите, чтобы ваш порожденный процесс завершался при выходе из процесса порождения.

Вот страница , которая объясняет все тонкие различия между Fork, System, Exec.

Если вы работаете на Win, Mac и Linux, я могу порекомендовать вам Qt Framework и его объект QProcess , но я не знаю, подходит ли вам этот вариант. Большим преимуществом является то, что вы сможете скомпилировать один и тот же код для Windows Linux и Mac:

 QString program = "./yourspawnedprogram";
 QProcess * spawnedProcess = new QProcess(parent);
 spawnedProcess->start(program);
 // or spawnedProcess->startDetached(program);

Кроме того, вы можете даже убить дочерний процесс из материнского процесса, и поддерживать связь с ним через поток.

2 голосов
/ 20 августа 2008

Одним из решений является системная функция, определенная в stdlib.h

int system(const char *string);

Пример системного API

1 голос
/ 23 декабря 2008

Говоря о зависимых от платформы рецептах, в Windows используется CreateProcess , в Posix (Linux, Mac) - fork + execvp. Но system() должен покрывать ваши основные потребности и является частью стандартной библиотеки.

1 голос
/ 23 декабря 2008

Если вам нужно проверить / прочитать / проанализировать вывод вашей внешней команды, я бы предложил использовать popen () вместо system ().

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