использование exec для выполнения системной команды в новом процессе - PullRequest
17 голосов
/ 12 апреля 2011

Я пытаюсь создать процесс, который выполняет системную команду, в то время как моя собственная программа все еще продолжается, и два процесса будут работать параллельно. Я работаю над Linux.

Я посмотрел в Интернете и, похоже, мне следует использовать семью exec (). Но это не работает так, как я ожидал. Например, в следующем коде я вижу только «до», но не «готово».

Мне любопытно, если я что-нибудь выдаю?

#include <unistd.h>
#include <iostream>

using namespace std;

main()
{
   cout << "before" << endl;
   execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);
   cout << "done" << endl;
}

[UPDATE]

Спасибо за ваши комментарии, ребята. Теперь моя программа выглядит так. Все работает нормально, кроме как в конце, я должен нажать Enter, чтобы закончить программу. Я не уверен, почему я должен нажать последний вход?

#include <unistd.h>
#include <iostream>

using namespace std;

main()
{
   cout << "before" << endl;
   int pid = fork();
   cout << pid << endl;
   if (pid==0) {
      execl("/bin/ls", "ls", "-r", "-t", "-l", (char *) 0);
   }
   cout << "done" << endl;
}

Ответы [ 3 ]

18 голосов
/ 12 апреля 2011

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


После того, как вы внесли это изменение, появляется только , которое необходимо нажать Enter для завершения программы. На самом деле происходит следующее: родительский процесс разветвляется и выполняет дочерний процесс. Оба процесса выполняются, и оба процесса печатают в стандартный вывод одновременно. Их вывод искажен. Родительский процесс имеет меньше действий, чем дочерний, поэтому он завершается первым. Когда он завершается, ваша оболочка, которая его ждала, просыпается и печатает обычную подсказку. Между тем, дочерний процесс все еще выполняется. Он печатает больше записей файла. Наконец, это заканчивается. Оболочка не обращает внимания на дочерний процесс (его внука), поэтому у оболочки нет причин повторно печатать подсказку. Посмотрите внимательнее на вывод, который вы получаете, и вы сможете найти свою обычную командную строку, скрытую в выводе ls выше.

Появится курсор , ожидающий нажатия клавиши. Когда вы это сделаете, оболочка напечатает подсказку, и все выглядит нормально. Но что касается снаряда, все уже было нормально. Вы могли набрать другую команду раньше. Это выглядело бы немного странно, но оболочка выполнила бы это нормально, потому что она получает ввод только с клавиатуры, а не от дочернего процесса, печатающего дополнительные символы на экране.

Если вы используете программу, подобную top, в отдельном окне консоли, вы можете посмотреть и подтвердить, что обе программы уже закончили работать, прежде чем нажимать Enter.

7 голосов
/ 12 апреля 2011

Семейство функций Exec заменяет текущий процесс новым исполняемым файлом.

Чтобы сделать то, что вам нужно, используйте одну из функций fork() и попросите дочерний процесс exec новое изображение.

[ответ на обновление]

Он делает именно то, что вы сказали: вам не нужно нажимать «ввод», чтобы завершить программу: она уже вышла. Оболочка уже выдала подсказку:

[wally@zenetfedora ~]$ ./z
before
22397
done
[wally@zenetfedora ~]$ 0               << here is the prompt (as well as the pid)
total 5102364
drwxr-xr-x.  2 wally wally       4096 2011-01-31 16:22 Templates
...

Вывод ls занимает некоторое время, поэтому он скрывает подсказку. Если вы хотите, чтобы вывод отображался в более логичном порядке, добавьте sleep(1) (или, возможно, дольше) перед словом "done".

2 голосов
/ 12 апреля 2011

Вам не хватает той части, где execl () заменяет текущую программу в памяти на /bin/ls

Я бы посоветовал взглянуть на popen(), который запустит и выполнит новый процесс, а затем позволит вам читать или записывать его через канал. (Или если вам нужно читать и писать, fork() самостоятельно, тогда exec())

...