Системные вызовы

Системный вызов Linux Exec

Системный вызов Linux Exec

Системный вызов exec используется для выполнения файла, находящегося в активном процессе. При вызове exec предыдущий исполняемый файл заменяется и выполняется новый файл.

Точнее, мы можем сказать, что использование системного вызова exec заменит старый файл или программу из процесса новым файлом или программой. Все содержание процесса заменено новой программой.

Сегмент пользовательских данных, который выполняет системный вызов exec (), заменяется файлом данных, имя которого указывается в аргументе при вызове exec ().

Новая программа загружается в то же пространство процесса. Текущий процесс просто превращается в новый процесс, и, следовательно, идентификатор PID процесса не изменяется, это связано с тем, что мы не создаем новый процесс, мы просто заменяем процесс другим процессом в exec.

Если текущий запущенный процесс содержит более одного потока, все потоки будут завершены, а новый образ процесса будет загружен и затем выполнен. Нет функций деструктора, которые завершают потоки текущего процесса.

PID процесса не изменяется, но данные, код, стек, куча и т. Д. процесса изменяются и заменяются на новые загруженные процессы. Новый процесс выполняется с точки входа.

Системный вызов Exec - это набор функций, и на языке программирования C стандартные имена этих функций следующие:

  1. execl
  2. экзекль
  3. execlp
  4. execv
  5. Execve
  6. execvp


Здесь следует отметить, что эти функции имеют одинаковую базу exec за которым следует одна или несколько букв. Это объясняется ниже:

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

l: l - аргументы командной строки передают список функции

п: p - это переменная среды пути, которая помогает найти файл, переданный в качестве аргумента для загрузки в процесс.

v: v - для аргументов командной строки. Они передаются как массив указателей на функцию.

Почему используется exec?

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

Внутренняя работа exec

Чтобы понять, как работает exec, обратите внимание на следующие моменты:

  1. Текущий образ процесса перезаписывается новым образом процесса.
  2. Новый образ процесса - это тот, который вы передали в качестве аргумента exec
  3. Текущий процесс завершен
  4. Новый образ процесса имеет тот же идентификатор процесса, ту же среду и тот же дескриптор файла (поскольку процесс не заменяется, образ процесса заменяется)
  5. На статистику ЦП и виртуальную память влияет. Отображение виртуальной памяти текущего образа процесса заменяется виртуальной памятью нового образа процесса.

Синтаксисы функций семейства exec:

Ниже приведены синтаксисы для каждой функции exec:

int execl (const char * путь, const char * arg,…)
int execlp (const char * файл, const char * arg,…)
int execle (const char * путь, const char * arg,…, char * const envp [])
int execv (const char * путь, const char * argv [])
int execvp (const char * файл, const char * argv [])
int execvpe (const char * файл, const char * argv [], char * const envp [])

Описание:

Тип возвращаемого значения этих функций - Int. Когда образ процесса успешно заменен, вызывающей функции ничего не возвращается, потому что вызвавший его процесс больше не работает. Но если есть какая-либо ошибка, будет возвращено -1. Если произошла какая-либо ошибка, errno установлен.

В синтаксисе:

  1. дорожка используется для указания полного имени файла, который должен быть запущен.
  1. аргумент аргумент передан. На самом деле это имя файла, который будет выполняться в процессе. В большинстве случаев значение arg и path одинаково.
  1. const char * arg в функциях execl (), execlp () и execle () рассматривается как arg0, arg1, arg2,…, argn. По сути, это список указателей на строки с завершающим нулем. Здесь первый аргумент указывает на имя файла, которое будет выполнено, как описано в пункте 2.
  1. envp представляет собой массив, содержащий указатели, указывающие на переменные среды.
  1. файл используется для указания имени пути, которое будет определять путь к новому файлу образа процесса.
  1. Функции вызова exec, заканчивающиеся на е используются для изменения среды для нового образа процесса. Эти функции передают список настроек среды с помощью аргумента envp. Этот аргумент представляет собой массив символов, который указывает на строку с завершающим нулем и определяет переменную среды.

Чтобы использовать функции семейства exec, вам необходимо включить следующий файл заголовка в вашу программу C:

#включать

Пример 1: Использование системного вызова exec в программе на C

Рассмотрим следующий пример, в котором мы использовали системный вызов exec при программировании на C в Linux, Ubuntu: У нас есть два файла c. Пример.c и привет.c:

пример.c

КОД:

#включать
#включать
#включать
int main (int argc, char * argv [])

printf ("PID примера.c =% d \ n ", getpid ());
char * args [] = "Привет", "C", "Программирование", NULL;
execv ("./ привет ", аргументы);
printf ("Вернуться к примеру.c ");
возврат 0;

Привет.c

КОД:

#включать
#включать
#включать
int main (int argc, char * argv [])

printf ("Здравствуйте!.c \ n ");
printf ("PID приветствия.c =% d \ n ", getpid ());
возврат 0;

ВЫХОД:

PID примера.с = 4733
Мы в привет.c
PID привет.с = 4733

В приведенном выше примере у нас есть пример.c файл и привет.c файл. В примере .c, прежде всего мы напечатали идентификатор текущего процесса (пример файла.c работает в текущем процессе). Затем в следующей строке мы создали массив символьных указателей. Последний элемент этого массива должен быть NULL в качестве конечной точки.

Затем мы использовали функцию execv (), которая принимает в качестве аргумента имя файла и массив символьных указателей. Здесь следует отметить, что мы использовали ./ с именем файла, он указывает путь к файлу. Поскольку файл находится в папке, где находится пример.c находится, поэтому нет необходимости указывать полный путь.

Когда вызывается функция execv (), наш образ процесса будет заменен теперь на файл example.c не в процессе, но файл hello.c находится в процессе. Видно, что идентификатор процесса такой же, если привет.c - образ процесса или пример.c - образ процесса, потому что процесс такой же, а образ процесса только заменяется.

Затем у нас есть еще одна вещь, на которую следует обратить внимание, это оператор printf () после того, как execv () не выполняется. Это связано с тем, что управление никогда не возвращается обратно к старому образу процесса, если его заменяет новый образ процесса. Управление возвращается к вызывающей функции только в том случае, если замена образа процесса не удалась. (В данном случае возвращаемое значение -1).

Разница между системными вызовами fork () и exec ():

Системный вызов fork () используется для создания точной копии запущенного процесса, и созданная копия является дочерним процессом, а запущенный процесс - родительским процессом. В то время как системный вызов exec () используется для замены образа процесса новым образом процесса. Следовательно, в системном вызове exec () нет концепции родительских и дочерних процессов.

В системном вызове fork () родительский и дочерний процессы выполняются одновременно. Но в системном вызове exec (), если замена образа процесса прошла успешно, управление не вернется туда, где была вызвана функция exec, а выполнит новый процесс. Управление будет передано обратно только в случае ошибки.

Пример 2: Объединение системных вызовов fork () и exec ()

Рассмотрим следующий пример, в котором мы использовали системные вызовы fork () и exec () в одной программе:

пример.c

КОД:

#включать
#включать
#включать
int main (int argc, char * argv [])

printf ("PID примера.c =% d \ n ", getpid ());
pid_t p;
р = вилка ();
если (p == - 1)

printf ("Ошибка при вызове fork ()");

если (p == 0)

printf ("Мы находимся в дочернем процессе \ n");
printf ("Привет.c из дочернего процесса \ n ");
char * args [] = "Привет", "C", "Программирование", NULL;
execv ("./ привет ", аргументы);

еще

printf («Мы находимся в родительском процессе»);

возврат 0;

Привет.c:

КОД:

#включать
#включать
#включать
int main (int argc, char * argv [])

printf ("Здравствуйте!.c \ n ");
printf ("PID приветствия.c =% d \ n ", getpid ());
возврат 0;

ВЫХОД:

PID примера.с = 4790
Мы находимся в родительском процессе
Мы находимся в дочернем процессе
Звонок привет.c из дочернего процесса
Мы в привет.c
PID привет.с = 4791

В этом примере мы использовали системный вызов fork (). Когда дочерний процесс будет создан, 0 будет присвоен p, а затем мы перейдем к дочернему процессу. Теперь будет выполняться блок операторов с if (p == 0). Отображается сообщение, и мы использовали системный вызов execv () и текущий образ дочернего процесса, который является примером.c будет заменен на привет.c. Перед вызовом execv () дочерний и родительский процессы были одинаковыми.

Видно, что PID примера.с и привет.c теперь другое. Это потому, что пример.c - образ родительского процесса и привет.c - образ дочернего процесса.

Лучшие эмуляторы игровой консоли для Linux
В этой статье будет перечислено популярное программное обеспечение для эмуляции игровых консолей, доступное для Linux. Эмуляция - это уровень совмести...
Лучшие дистрибутивы Linux для игр в 2021 году
Операционная система Linux прошла долгий путь от своего первоначального простого серверного вида. Эта ОС значительно улучшилась за последние годы и те...
Как записать и транслировать игровую сессию в Linux
В прошлом игры считались только хобби, но со временем игровая индустрия увидела огромный рост с точки зрения технологий и количества игроков. Игровая ...