Поиск по сайту:

Как использовать функцию 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