Как использовать функцию execvp() в C/C++
В этой статье мы рассмотрим использование функции execvp() в C/C++.
В UNIX функция execvp() очень полезна, если вы хотите запустить другую программу, используя нашу программу на C.
ПРИМЕЧАНИЕ. Эта функция применима только к операционным системам на базе UNIX. Это не работает в Windows
Давайте посмотрим на выполнение UNIX-команд из нашей программы на наглядных примерах!
Базовый синтаксис execvp()
Эта функция принимает имя запускаемой команды UNIX в качестве первого аргумента.
Он находится в заголовочном файле
, поэтому мы должны включить его в нашу программу.
#include <unistd.h>
int execvp(const char* command, char* argv[]);
Здесь мы называем «командой» любой двоичный исполняемый файл, который является частью переменной среды PATH
. Поэтому, если вы хотите запускать пользовательские программы, убедитесь, что вы добавили его в свой Переменная PATH
!
Второй аргумент (argv
) представляет собой список аргументов для command
. Это массив строк char*
.
Здесь argv
содержит полную команду вместе с ее аргументами.
Например, приведенный ниже массив соответствует формату argv
.
char* argument_list[] = {"ls", "-l", NULL}; // NULL terminated array of char* strings
// Ok! Will execute the command "ls -l"
execvp("ls", argument_list);
Этот массив ДОЛЖЕН быть завершен NULL
, т. е. последний элемент argv
должен быть указателем NULL
.
Что теперь происходит с нашей программой на C?
Эта функция передает управление текущим процессом (программой на C) команде. Таким образом, программа на C мгновенно заменяется фактической командой.
Таким образом, все, что идет после execvp()
, НЕ будет выполнено, так как наша программа полностью перехвачена!
Однако, если команда по какой-то причине не удалась, execvp()
вернет -1.
Итак, всякий раз, когда вы используете execvp()
, если вы хотите поддерживать свою программу на C, вы обычно используете fork()
, чтобы сначала создать новый процесс, а затем использовать execvp()
в этом новом процессе.
Это называется моделью «fork-exec» и является стандартной практикой для запуска нескольких процессов с использованием C.
Давайте теперь рассмотрим несколько примеров, чтобы лучше понять эту функцию. Мы также будем использовать fork()
вместе с execvp()
, так что у нас все еще может быть наша программа на C!
Использование execvp() в C/C++ — некоторые примеры
Если вы хотите увидеть, что именно произойдет, если вы попытаетесь использовать execvp()
без создания нового процесса, используя fork()
. приведенная ниже программа показывает это.
Мы будем выполнять \ls -l из нашей программы на C.
Обратите внимание, что оператор printf()
после execvp()
НЕ выполняется, так как другой процесс взял на себя управление!
#include <stdio.h>
#include <unistd.h>
int main() {
char* command = "ls";
char* argument_list[] = {"ls", "-l", NULL};
printf("Before calling execvp()\n");
// Calling the execvp() system call
int status_code = execvp(command, argument_list);
if (status_code == -1) {
printf("Process did not terminate correctly\n");
exit(1);
}
printf("This line will not be printed if execvp() runs correctly\n");
return 0;
}
Выход
Before calling execvp()
total 3
-rwxrwxrwx 1 user user 22088 May 30 16:37 a.out
-rwxrwxrwx 1 user user 16760 May 30 16:37 sample
-rw-rw-rw- 1 user user 1020 May 30 16:37 sample.c
Как видите, часть после execvp()
вообще не выполняется, так как \ls -l взяла на себя управление нашим процессом!
Давайте перепишем тот же пример, но поместим системный вызов execvp()
в другой процесс, используя fork()
.
Посмотрим, что произойдет сейчас.
#include <stdio.h>
#include <unistd.h>
int main() {
char* command = "ls";
char* argument_list[] = {"ls", "-l", NULL};
printf("Before calling execvp()\n");
printf("Creating another process using fork()...\n");
if (fork() == 0) {
// Newly spawned child Process. This will be taken over by "ls -l"
int status_code = execvp(command, argument_list);
printf("ls -l has taken control of this child process. This won't execute unless it terminates abnormally!\n");
if (status_code == -1) {
printf("Terminated Incorrectly\n");
return 1;
}
}
else {
// Old Parent process. The C program will come here
printf("This line will be printed\n");
}
return 0;
}
Выход
Before calling execvp()
Creating another process using fork()...
This line will be printed
user@shell:$ total 3
-rwxrwxrwx 1 user user 22088 May 30 16:37 a.out
-rwxrwxrwx 1 user user 16760 May 30 16:37 sample
-rw-rw-rw- 1 user user 1020 May 30 16:37 sample.c
Если вы находитесь в оболочке, вывод может выглядеть странно, но это потому, что несколько процессов выполняются параллельно! Оба вывода действительно были напечатаны, поэтому мы смогли решить нашу проблему.
Заключение
Мы узнали об использовании функции execvp() в C/C++ для выполнения других программ из нашей программы на C. Однако обратите внимание, что это даст другой программе полный контроль над нашим процессом.
Из-за этого нам нужно заключить это в другой процесс, используя системный вызов fork()
. Надеюсь, это имело для вас смысл, и вы смогли запускать другие программы, сохраняя при этом контроль над своей программой на C!
Рекомендации
- Справочная страница Linux по функции execvp() в C