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

Объяснение системных вызовов fork, exec, wait и exit в Linux


Последовательность инструкций и данных, которые могут выполняться один раз, несколько раз или одновременно, называются программами. И процесс представляет собой выполнение таких программ. Таким образом, эти процессы могут запускать множество программ. В одном и том же процессе операционная система может загружать разные программы. Повторно используемые состояния процессов, такие как текущие каталоги, привилегии, дескрипторы файлов и т. д., наследуются новыми программами. Такие вещи выполняются на том же уровне, что и системные вызовы, такие как fork(), exec(), wait() и exit().

В этой статье мы собираемся подробно обсудить системные вызовы Linux fork(), exec(), wait() и exit() с примерами и вариантами использования.

вилка()

fork() — это один из системных вызовов, который очень специфичен и полезен в системах Linux/Unix. Он используется процессами для создания процессов, которые являются копиями самих себя. С помощью таких системных вызовов дочерний процесс может быть создан родительским процессом. Пока дочерний процесс не будет выполнен полностью, родительский процесс приостанавливается.

Некоторые из важных моментов в fork() заключаются в следующем.

  • Родительский процесс получит идентификатор дочернего процесса с ненулевым значением.
  • Нулевое значение возвращается дочернему элементу.
  • Если при создании дочернего элемента возникнут какие-либо системные или аппаратные ошибки, в fork() возвращается -1.
  • Поскольку уникальный идентификатор процесса, полученный дочерним процессом, не соответствует идентификатору какой-либо существующей группы процессов.

Чтобы подробнее рассказать о fork(), давайте рассмотрим пример, поясняющий концепцию fork().

sudo vim fork.c

Вот код для его копирования/вставки:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main(int argc, char **argv)
{
pid_t pid;
pid = fork();
if(pid==0)
{
printf("It is the child process and pid is %d\n",getpid());
exit(0);
}
else if(pid > 0)
{
printf("It is the parent process and pid is %d\n",getpid());
}
else
{
printf("Error while forking\n");
exit(EXIT_FAILURE);
}
return 0;
}

Выход:

$make fork

Запустив скрипт, мы получим результат, как показано на скриншоте ниже.

./fork

исполнитель()

Exec() — это такой системный вызов, который выполняется путем замены текущего образа процесса новым образом процесса. Однако исходный процесс остается новым процессом, но новый процесс заменяет головные данные, данные стека и т. д. Он запускает программу из точки входа, загружая программу в текущее пространство процесса.

Чтобы уточнить больше, давайте возьмем пример, показанный ниже.

sudo vim exec.c

И вот код:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

main(void) {
  pid_t pid = 0;
  int status;
  pid = fork();

if (pid == 0) {
  printf("I am the child.");
  execl("/bin/ls", "ls", "-l", "/home/ubuntu/", (char *) 0);
  perror("In exec(): ");
}

if (pid > 0) {
  printf("I am the parent, and the child is %d.\n", pid);
  pid = wait(&status);
  printf("End of process %d: ", pid);

  if (WIFEXITED(status)) {
    printf("The process ended with exit(%d).\n", WEXITSTATUS(status));
  }

  if (WIFSIGNALED(status)) {
    printf("The process ended with kill -%d.\n", WTERMSIG(status));
  }
}

if (pid < 0) {
  perror("In fork():");
}

exit(0);
}

Выход:

make exec

Запустив скрипт, мы получим результат, как показано на скриншоте ниже.

./exec

ждать()

Как и в случае с ветвлением, дочерние процессы создаются и выполняются, но родительский процесс приостанавливается до тех пор, пока не выполнится дочерний процесс. В этом случае системный вызов wait() активируется автоматически из-за приостановки родительского процесса. После того, как дочерний процесс завершает выполнение, родительский процесс снова получает управление.

Чтобы подробнее рассказать о wait(), давайте рассмотрим пример, поясняющий системный вызов wait().

sudo vim wait.c

Вот пример кода:

#include<stdio.h> // printf()
#include<stdlib.h> // exit()
#include<sys/types.h> // pid_t
#include<sys/wait.h> // wait()
#include<unistd.h> // fork

int main(int argc, char **argv)
{

pid_t pid;
pid = fork();

if(pid==0)

{
printf("It is the child process and pid is %d\n",getpid());

int i=0;
for(i=0;i<8;i++)
{
printf("%d\n",i);
}

exit(0);

}
else if(pid > 0)
{

printf("It is the parent process and pid is %d\n",getpid());

int status;
wait(&status);
printf("Child is reaped\n");
}

else
{

printf("Error in forking..\n");
exit(EXIT_FAILURE);

}

return 0;

}

Выход:

make wait

Запустив скрипт, мы получим результат, как показано на скриншоте ниже.

./wait

Выход()

Exit() — это такая функция или один из системных вызовов, который используется для завершения процесса. Этот системный вызов определяет, что выполнение потока завершено, особенно в случае многопоточной среды. Для дальнейшего использования фиксируется состояние процесса.

После использования системного вызова exit() все ресурсы, используемые в процессе, извлекаются операционной системой, а затем завершают процесс. Системный вызов Exit() эквивалентен выходу().

Краткое описание

#include <unistd.h>
void _exit(int status);
#include <stdlib.h>
void _Exit(int status);

Вы можете увидеть использование функции exit() в приведенных выше примерах fork(), wait(). Использование системного вызова exit() предназначено для завершения процесса.

Заключение

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

Статьи по данной тематике: