о системном вызове fork и execve

говорят, что fork системный вызов создает клон вызывающего процесса, а затем (обычно) дочерний процесс выдает execve системный вызов для изменения образа и запуска нового процесса. Почему два шага?

кстати, что значит execve стоять?

5 ответов


каждый шаг относительно прост.

в Unix ваш процесс состоит из двух частей-области памяти только для чтения с кодом приложения ("текст") и области памяти для чтения и записи ("данные").

вилка клонирует область чтения и записи, оставляя текстовую страницу в покое. Теперь у вас есть два процесса, выполняющих один и тот же код. Они отличаются значением регистра -- возвращаемое значение от fork -- которое отделяет родителя от ребенка.

exec заменяет текстовую страницу, оставляя данные только Пейдж. Существует много форм exec, в зависимости от того, сколько информации о среде вы передаете ему. См.http://linux.die.net/man/3/exec для дополнительного списка вариантов.


причина два-шаг-гибкость. Между этими двумя шагами вы можете изменить контекст дочернего процесса, который унаследует новая исполняемая программа.

некоторые вещи, которые вы можете изменить:

  • файловые дескрипторы
  • ID пользователя/группы
  • идентификаторы групп и сеансов процессов
  • текущей директории
  • ограничения ресурсов
  • приоритет и сродство
  • маска создания файла (умаск)

Если вы не разделили fork и exec и вместо этого имели один системный вызов типа spawn, ему нужно было бы принять аргументы для каждого из этих атрибутов процесса, если вы хотите, чтобы они были установлены по-разному в дочернем процессе. Например, см. список аргументов для CreateProcess в API Windows.

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

настройки файл дескрипторы-одна из наиболее распространенных вещей, которые нужно изменить в контексте процесса ребенка. Если вы хотите захватить выходные данные программы, вы обычно создадите канал в родителе с системным вызовом pipe(2), и после fork(2)ing вы закроете конец записи в Родительском процессе и закроете конец чтения в дочернем процессе перед вызовом execve(2). (Вы также будете использовать dup (2), чтобы установить дочерний конец канала в качестве файлового дескриптора 1 (stdout)). Это было бы либо невозможно, либо ограничительно в один системный вызов.


  • exec: выполнить новый процесс
  • v: используйте массив аргументов
  • e: укажите также среду

другие вариации exec изобилуют:

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
  • l: перечислите arg на функции
  • p: используйте $PATH для поиска исполняемого файла

семейство функций "exec" заменяет текущий образ процесса(откуда он вызывается) новым образом процесса, поэтому вызывающий образ заменяется новым образом процесса. Для EG. если вы должны были запустить команду " ls " из оболочки(/bin/sh или /bin/csh), то оболочка будет раскошеливаться на новый процесс, который затем выполнит ls. После выхода команды ls она возвращает управление родительскому процессу,который в данном примере является оболочкой.

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

для вариаций в семействе "exec" посмотрите на ответ 0x6adb015.


Что значит execve стоять?

6 вариаций exec функции в C являются exec{l,v}{,e,p}. См. прототипы функций ниже для деталей.

аргументы командной строки

  • v - аргументы командной строки передаются в функцию в виде массива (vector) указателей.
  • l - аргументы командной строки передаются индивидуально (a list) к функции.

переменные среды (опционально)

  • e - массив указателей на eпеременные nvironment явно передаются в новый образ процесса

найдите файл для выполнения (необязательно)

  • p - использует PATH переменная среды, чтобы найти название в аргумент файла для выполнения

int execl (char const *path, char const *arg0, ...);
int execle(char const *path, char const *arg0, ..., char const *envp[]);
int execlp(char const *file, char const *arg0, ...);
int execv (char const *path, char const *argv[]);
int execve(char const *path, char const *argv[], char const *envp[]);
int execvp(char const *file, char const *argv[]);

источник