Execl, execle, execlp, execv, execve, execvp, execvpe


Содержание

EXEC(2)

НАЗВАНИЕ
exec: execl, execv, execle, execve, execlp, execvp выполнение файла

ОПИСАНИЕ
Все формы системного вызова exec превращают вызвавший процесс в новый процесс, который строится из обычного выполняемого файла, называемого в дальнейшем новым выполняемым файлом. Выполняемый файл состоит из заголовка [см. a.out(4)], сегмента команд (.text) и данных. Данные состоят из инициализированной (.data) и неинициализированной (.bss) частей. Если системный вызов exec закончился успешно, то он не может вернуть управление, так как вызвавший процесс уже заменен новым процессом.

При запуске C-программы ее вызывают следующим образом:

где argc равен количеству аргументов, argv — массив указателей собственно на аргументы и envp — массив указателей на цепочки символов, образующие окружение. Принято соглашение, по которому значение argc не меньше 1, а первый элемент массива argv указывает на цепочку символов, содержащую имя нового выполняемого файла.

Аргументам системных вызовов группы exec приписан следующий смысл.

Аргумент path указывает на маршрутное имя нового выполняемого файла.

Как и path, аргумент file указывает новый выполняемый файл, но маршрут этого файла определяется в результате просмотра каталогов, переданных через переменную окружения PATH [см. environ(5)]. Окружение поддерживается shell’ом [см. sh(1)].

Аргументы arg0, arg1, . argn — это указатели на цепочки символов, ограниченные нулевыми байтами. Эти цепочки образуют доступный новому процессу список аргументов. По соглашению, как минимум arg0 должен присутствовать и указывать на цепочку символов, равную path (или последнему компоненту path).

Массив argv содержит указатели на цепочки символов, ограниченные нулевыми байтами. Эти цепочки образуют доступный новому процессу список аргументов. По соглашению, в argv должен присутствовать как минимум первый элемент, указывающий на цепочку символов, равную path (или последнему компоненту path). За последним занятым элементом массива argv должен следовать пустой (нулевой) указатель.

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

Перед началом выполнения любой программы во внешнюю переменную environ, описание которой выглядит как

помещается адрес массива указателей на цепочки символов, образующие окружение процесса. С помощью этой переменной (как и с помощью аргумента envp функции main) в новом процессе всегда можно получить доступ к окружению, независимо от использовавшегося варианта системного вызова exec. Разница лишь в том, что в случае вызовов execle и execve окружение нового процесса задается явно, а в остальных случаях наследуется у вызвавшего процесса.

Файлы, открытые в вызвавшем процессе, остаются открытыми в новом процессе, за исключением тех, у которых установлен флаг «закрыть при выполнении вызова exec» [см. fcntl(2)]. Если файл остался открытым, то указатель текущей позиции в файле сохраняется.

Реакция на сигналы сохраняется, за исключением того, что сигналы, которые перехватывались в вызвавшем процессе, вызывают терминирование нового процесса [см. signal(2)].

В случае, когда реакция на сигналы устанавливалась вызовом sigset(2) и задавалась как SIG_DFL, SIG_IGN или SIG_HOLD, эта реакция наследуется у вызвавшего процесса. Однако, если сигнал перехватывался, то устанавливается реакция SIG_DFL и все полученные, но не обработанные сигналы этого типа откладываются.

Если у нового выполняемого файла установлен бит разрешения переустанавливать действующий идентификатор пользователя [см. chmod(2)], то действующий идентификатор пользователя нового процесса устанавливается равным идентификатору владельца нового выполняемого файла. Аналогично, если у нового выполняемого файла установлен бит разрешения переустанавливать действующий идентификатор группы, то действующий идентификатор группы нового процесса устанавливается равным идентификатору группы нового выполняемого файла. Реальный идентификатор пользователя и реальный идентификатор группы нового процесса наследуются у вызвавшего процесса.

Присоединенные разделяемые сегменты памяти не наследуются новым процессом [см. shmop(2)].

У нового процесса выключено профилирование.

Кроме того, новый процесс наследует у процесса, вызвавшего exec, следующие характеристики:

  1. Значение поправки к приоритету [см. nice(2)].
  2. Идентификатор процесса.
  3. Идентификатор родительского процесса.
  4. Идентификатор группы процессов.
  5. semadj значения [см. semop(2)].
  6. Идентификатор группы терминала [см. exit(2)].
  7. Режим трассировки [см. ptrace(2)].
  8. Время, оставшееся до срабатывания будильника [см. alarm(2)].
  9. Текущий рабочий каталог.
  10. Корневой каталог.
  11. Маска режима создания файлов [см. umask(2)].
  12. Ограничение на размер файла [см. ulimit(2)].
  13. Счетчики времени, потраченного для обслуживания этого процесса (tms_utime, tms_stime, tms_cutime, tms_cstime) [см. times(2)].
  14. Блокировки доступа к сегментам файлов [см. fcntl(2) и lockf(3C)].

Системный вызов exec завершается неудачей и управление возвращается, если выполнено хотя бы одно из следующих условий: [ENOENT] Компонент маршрута нового выполняемого файла не существует. [ENOTDIR] Компонент маршрута нового выполняемого файла не является каталогом. [EACCES] Один из каталогов, перечисленных в маршруте нового выполняемого файла, не доступен для просмотра. [EACCES] Новый выполняемый файл не является обычным файлом. [EACCES] Нет прав на выполнение нового файла. [ENOEXEC] Права на выполнение нового файла есть, но его заголовок не начинается с допустимого магического числа [см. a.out(4)]. [ETXTBSY] Новый выполняемый файл в настоящий момент открыт для записи некоторым процессом. [ENOMEM] Новый процесс требует больше памяти, чем позволяет системное ограничение MAXMEM. [E2BIG] Суммарная длина списка аргументов превышает системное ограничение, равное 5120 байт. [EFAULT] Отсутствует требуемое оборудование. [EFAULT] Некорректные адреса в качестве аргументов. [EAGAIN] Не хватает памяти. [ELIBACC] К требуемой разделяемой библиотеке не разрешен доступ на выполнение. [ELIBEXEC] Попытка непосредственно выполнить разделяемую библиотеку. [EINTR] Во время выполнения вызова exec перехвачен сигнал. [ENOLINK] Аргумент path указывает на удаленный компьютер, связи с которым в данный момент нет. [EMULTIHOP] Компоненты path требуют многократного обращения к удаленным компьютерам.

ДИАГНОСТИКА
Возврат из системного вызова exec свидетельствует об ошибке. В таком случае результат равен -1, а переменной errno присваивается код ошибки.

_exec, _wexec Functions

Each function in this family loads and executes a new process:

The letter at the end of the function name determines the variation.

_exec function suffix Description
e envp , array of pointers to environment settings, is passed to the new process.
l Command-line arguments are passed individually to _exec function. Typically used when the number of parameters to the new process is known in advance.
p PATH environment variable is used to find the file to execute.
v argv , array of pointers to command-line arguments, is passed to _exec . Typically used when the number of parameters to the new process is variable.

Remarks

Each _exec function loads and executes a new process. All _exec functions use the same operating-system function (CreateProcess). The _exec functions automatically handle multibyte-character string arguments as appropriate, recognizing multibyte-character sequences according to the multibyte code page currently in use. The _wexec functions are wide-character versions of the _exec functions. The _wexec functions behave identically to their _exec family counterparts except that they do not handle multibyte-character strings.

Generic-Text Routine Mappings

Tchar.h routine _UNICODE and _MBCS not defined _MBCS defined _UNICODE defined
_texecl _execl _execl _wexecl
_texecle _execle _execle _wexecle
_texeclp _execlp _execlp _wexeclp
_texeclpe _execlpe _execlpe _wexeclpe
_texecv _execv _execv _wexecv
_texecve _execve _execve _wexecve
_texecvp _execvp _execvp _wexecvp
_texecvpe _execvpe _execvpe _wexecvpe

The cmdname parameter specifies the file to be executed as the new process. It can specify a full path (from the root), a partial path (from the current working directory), or a file name. If cmdname does not have a file name extension or does not end with a period (.), the _exec function searches for the named file. If the search is unsuccessful, it tries the same base name with the .com file name extension and then with the .exe, .bat, and .cmd file name extensions. If cmdname has a file name extension, only that extension is used in the search. If cmdname ends with a period, the _exec function searches for cmdname with no file name extension. _execlp , _execlpe , _execvp , and _execvpe search for cmdname (using the same procedures) in the directories specified by the PATH environment variable. If cmdname contains a drive specifier or any slashes (that is, if it is a relative path), the _exec call searches only for the specified file; the path is not searched.

Parameters are passed to the new process by giving one or more pointers to character strings as parameters in the _exec call. These character strings form the parameter list for the new process. The combined length of the inherited environment settings and the strings forming the parameter list for the new process must not exceed 32 kilobytes. The terminating null character (‘\0’) for each string is not included in the count, but space characters (inserted automatically to separate the parameters) are counted.

Spaces embedded in strings may cause unexpected behavior; for example, passing _exec the string «hi there» will result in the new process getting two arguments, «hi» and «there» . If the intent was to have the new process open a file named «hi there», the process would fail. You can avoid this by quoting the string: «\»hi there\»» .


Do not pass user input to _exec without explicitly checking its content. _exec will result in a call to CreateProcess so keep in mind that unqualified path names could lead to potential security vulnerabilities.

The _exec functions validate their parameters. If expected parameters are null pointers, empty strings, or omitted, the _exec functions invoke the invalid parameter handler as described in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return -1. No new process is executed.

The argument pointers can be passed as separate parameters (in _execl , _execle , _execlp , and _execlpe ) or as an array of pointers (in _execv , _execve , _execvp , and _execvpe ). At least one parameter, arg0 , must be passed to the new process; this parameter is argv [0] of the new process. Usually, this parameter is a copy of cmdname . (A different value does not produce an error.)

The _execl , _execle , _execlp , and _execlpe calls are typically used when the number of parameters is known in advance. The parameter arg0 is usually a pointer to cmdname . The parameters arg1 through argn point to the character strings forming the new parameter list. A null pointer must follow argn to mark the end of the parameter list.

The _execv , _execve , _execvp , and _execvpe calls are useful when the number of parameters to the new process is variable. Pointers to the parameters are passed as an array, argv . The parameter argv [0] is usually a pointer to cmdname . The parameters argv [1] through argv [ n ] point to the character strings forming the new parameter list. The parameter argv [ n +1] must be a NULL pointer to mark the end of the parameter list.

Files that are open when an _exec call is made remain open in the new process. In _execl , _execlp , _execv , and _execvp calls, the new process inherits the environment of the calling process. _execle , _execlpe , _execve , and _execvpe calls alter the environment for the new process by passing a list of environment settings through the envp parameter. envp is an array of character pointers, each element of which (except for the final element) points to a null-terminated string defining an environment variable. Such a string usually has the form NAME = value where NAME is the name of an environment variable and value is the string value to which that variable is set. (Note that value is not enclosed in double quotation marks.) The final element of the envp array should be NULL. When envp itself is NULL, the new process inherits the environment settings of the calling process.

A program executed with one of the _exec functions is always loaded into memory as if the maximum allocation field in the program’s .exe file header were set to the default value of 0xFFFFH.

The _exec calls do not preserve the translation modes of open files. If the new process must use files inherited from the calling process, use the _setmode routine to set the translation mode of these files to the desired mode. You must explicitly flush (using fflush or _flushall ) or close any stream before the _exec function call. Signal settings are not preserved in new processes that are created by calls to _exec routines. The signal settings are reset to the default in the new process.

Execl, execle, execlp, execv, execve, execvp, execvpe

environ, execl, execv, execle, execve, execlp, execvp — execute a file

SYNOPSIS

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

DESCRIPTION

The exec family of functions shall replace the current process image with a new process image. The new image shall be constructed from a regular, executable file called the new process image file. There shall be no return from a successful exec, because the calling process image is overlaid by the new process image.

When a C-language program is executed as a result of this call, it shall be entered as a C-language function call as follows:

where argc is the argument count and argv is an array of character pointers to the arguments themselves. In addition, the following variable:

is initialized as a pointer to an array of character pointers to the environment strings. The argv and environ arrays are each terminated by a null pointer. The null pointer terminating the argv array is not counted in argc.

[THR] Conforming multi-threaded applications shall not use the environ variable to access or modify any environment variable while any other thread is concurrently modifying any environment variable. A call to any function dependent on any environment variable shall be considered a use of the environ variable to access that environment variable.

The arguments specified by a program with one of the exec functions shall be passed on to the new process image in the corresponding main() arguments.

The argument path points to a pathname that identifies the new process image file.

The argument file is used to construct a pathname that identifies the new process image file. If the file argument contains a slash character, the file argument shall be used as the pathname for this file. Otherwise, the path prefix for this file is obtained by a search of the directories passed as the environment variable PATH (see the Base Definitions volume of IEEE Std 1003.1-2001, Chapter 8, Environment Variables). If this environment variable is not present, the results of the search are implementation-defined.

There are two distinct ways in which the contents of the process image file may cause the execution to fail, distinguished by the setting of errno to either [ENOEXEC] or [EINVAL] (see the ERRORS section). In the cases where the other members of the exec family of functions would fail and set errno to [ENOEXEC], the execlp() and execvp() functions shall execute a command interpreter and the environment of the executed command shall be as if the process invoked the sh utility using execl() as follows:

where is an unspecified pathname for the sh utility, file is the process image file, and for execvp(), where arg0, arg1, and so on correspond to the values passed to execvp() in argv[0], argv[1], and so on.

The arguments represented by arg0. are pointers to null-terminated character strings. These strings shall constitute the argument list available to the new process image. The list is terminated by a null pointer. The argument arg0 should point to a filename that is associated with the process being started by one of the exec functions.

The argument argv is an array of character pointers to null-terminated strings. The application shall ensure that the last member of this array is a null pointer. These strings shall constitute the argument list available to the new process image. The value in argv[0] should point to a filename that is associated with the process being started by one of the exec functions.

The argument envp is an array of character pointers to null-terminated strings. These strings shall constitute the environment for the new process image. The envp array is terminated by a null pointer.

For those forms not containing an envp pointer ( execl(), execv(), execlp(), and execvp()), the environment for the new process image shall be taken from the external variable environ in the calling process.

The number of bytes available for the new process’ combined argument and environment lists is . It is implementation-defined whether null terminators, pointers, and/or any alignment bytes are included in this total.

File descriptors open in the calling process image shall remain open in the new process image, except for those whose close-on- exec flag FD_CLOEXEC is set. For those file descriptors that remain open, all attributes of the open file description remain unchanged. For any file descriptor that is closed for this reason, file locks are removed as a result of the close as described in close() . Locks that are not removed by closing of file descriptors remain unchanged.

Directory streams open in the calling process image shall be closed in the new process image.

The state of the floating-point environment in the new process image shall be set to the default.

[XSI] The state of conversion descriptors and message catalog descriptors in the new process image is undefined. For the new process image, the equivalent of:

shall be executed at start-up.


Signals set to the default action (SIG_DFL) in the calling process image shall be set to the default action in the new process image. Except for SIGCHLD, signals set to be ignored (SIG_IGN) by the calling process image shall be set to be ignored by the new process image. Signals set to be caught by the calling process image shall be set to the default action in the new process image (see ). If the SIGCHLD signal is set to be ignored by the calling process image, it is unspecified whether the SIGCHLD signal is set to be ignored or to the default action in the new process image. [XSI] After a successful call to any of the exec functions, alternate signal stacks are not preserved and the SA_ONSTACK flag shall be cleared for all signals.

After a successful call to any of the exec functions, any functions previously registered by atexit() are no longer registered.

[XSI] If the ST_NOSUID bit is set for the file system containing the new process image file, then the effective user ID, effective group ID, saved set-user-ID, and saved set-group-ID are unchanged in the new process image. Otherwise, if the set-user-ID mode bit of the new process image file is set, the effective user ID of the new process image shall be set to the user ID of the new process image file. Similarly, if the set-group-ID mode bit of the new process image file is set, the effective group ID of the new process image shall be set to the group ID of the new process image file. The real user ID, real group ID, and supplementary group IDs of the new process image shall remain the same as those of the calling process image. The effective user ID and effective group ID of the new process image shall be saved (as the saved set-user-ID and the saved set-group-ID) for use by setuid().

[XSI] Any shared memory segments attached to the calling process image shall not be attached to the new process image.

[SEM] Any named semaphores open in the calling process shall be closed as if by appropriate calls to sem_close().

[TYM] Any blocks of typed memory that were mapped in the calling process are unmapped, as if munmap() was implicitly called to unmap them.

[ML] Memory locks established by the calling process via calls to mlockall() or mlock() shall be removed. If locked pages in the address space of the calling process are also mapped into the address spaces of other processes and are locked by those processes, the locks established by the other processes shall be unaffected by the call by this process to the exec function. If the exec function fails, the effect on memory locks is unspecified.

[MF|SHM] Memory mappings created in the process are unmapped before the address space is rebuilt for the new process image.

[PS] For the SCHED_FIFO and SCHED_RR scheduling policies, the policy and priority settings shall not be changed by a call to an exec function. For other scheduling policies, the policy and priority settings on exec are implementation-defined.

[TMR] Per-process timers created by the calling process shall be deleted before replacing the current process image with the new process image.

[MSG] All open message queue descriptors in the calling process shall be closed, as described in mq_close() .

[AIO] Any outstanding asynchronous I/O operations may be canceled. Those asynchronous I/O operations that are not canceled shall complete as if the exec function had not yet occurred, but any associated signal notifications shall be suppressed. It is unspecified whether the exec function itself blocks awaiting such I/O completion. In no event, however, shall the new process image created by the exec function be affected by the presence of outstanding asynchronous I/O operations at the time the exec function is called. Whether any I/O is canceled, and which I/O may be canceled upon exec, is implementation-defined.

[CPT] The new process image shall inherit the CPU-time clock of the calling process image. This inheritance means that the process CPU-time clock of the process being exec-ed shall not be reinitialized or altered as a result of the exec function other than to reflect the time spent by the process executing the exec function itself.

[TCT] The initial value of the CPU-time clock of the initial thread of the new process image shall be set to zero.

[TRC] If the calling process is being traced, the new process image shall continue to be traced into the same trace stream as the original process image, but the new process image shall not inherit the mapping of trace event names to trace event type identifiers that was defined by calls to the posix_trace_eventid_open() or the posix_trace_trid_eventid_open() functions in the calling process image.

If the calling process is a trace controller process, any trace streams that were created by the calling process shall be shut down as described in the posix_trace_shutdown() function.

The new process shall inherit at least the following attributes from the calling process image:

В чем разница между функциями ехеса семейства системных вызовов, как и execve Exec?

Я следовал курс системного программирования в последнее время и я пришел через системные вызовы Exec () и execve () . До сих пор я не могу найти никакой разницы между этими двумя, даже Википедия не дает четкого объяснения, поэтому есть разница между Exec () и execve () .

И кто — то пожалуйста , может дать краткое описание о EXEC вызовов семейство систем , таких как execl () , execv () , execle () , execvp () .

Там нет exec системного вызова — это, как правило , используется для обозначения всех execXX вызовов в качестве группы. Они все делают по существу то же самое: Загрузка новой программы в текущий процесс, и обеспечить его аргументы и переменные окружения. Различия заключаются в том , как программа найдена, как указаны аргументы, и где среда приходит.

Вызовы с v именем принимают параметр массива , чтобы указать argv[] массив новой программы.

Вызовы с l именем принимают аргументы новой программы в виде списка аргументов переменной длины к самой функции.

Вызовы с e именем принимают дополнительный аргумент , чтобы обеспечить среду новой программы; в противном случае, программа наследует среду текущего процесса.

Вызовы с p именем поиск PATH переменной среды , чтобы найти программу , если она не имеет каталога в нем (т.е. не содержит / символ). В противном случае, название программы всегда интерпретируется как путь к исполняемому файлу .

Использование man exec и читать:

Таким образом, вы передать массив в качестве параметров

Почти то же самое, но не как массив, но оценщик в виде списка значений (строки), а затем массиву обозначают окружающую среду.

Вы вызываете файл, без пути, поэтому он ожидает , что вы уже быть в праве path перед вызовом.

Последний, но тем не менее важный:

Аналогично предыдущему, но теперь у вас есть два массива, для аргументов и переменных окружения.

Аргументы различны для этих функций.

Функция execl, функций имеют и execle требовать от каждого из аргументов командной строки в новой программе должны быть указаны в виде отдельных аргументов.


Execv, execvp и execve, мы должны создать массив указателей на аргументы, а также адрес этого массива является аргументом этих трех функций.

Функции execve, execle позволяют передать указатель на массив указателей на строки окружения. Остальные четыре функций используют environ переменные в процессе вызова , чтобы скопировать существующую среду в программу.

Буква e означает , что функция принимает envp[] массив вместо того , чтобы использовать текущую среду.

Новая программа наследует следующие дополнительные функции из вызывающего процесса.

  • Реальный идентификатор пользователя и реальный идентификатор группы остаются теми же через ехес но эффективные идентификаторы могут изменяться, в зависимости от состояния множества-идентификатор пользователя и набор-идентификатор группы бит для файла программы выполняется.

Поскольку все эти функции принадлежит EXEC () семья, позвольте мне в differentiate соответствии extra characters со значениями,

1.exec в ():

р: нет => имя запускаемой программы будут взяты из pathname

v: присутствует => аргумент будет передан в качестве array

е: присутствует => среда будет взята из envp argument

2.exec ле ():

р: нет => имя запускаемой программы будут взяты из pathname

л: присутствует => аргумент будет передан как list

е: присутствует => среда будет взята из envp argument

3.exec LP ():

р: присутствует => имя программы для запуска будет взят из filename поименованных или системы будет search for program file в PATH переменном.

л: присутствует => аргумент будет передан как list

е: нет => среда будет взята из caller’s environ

4.exec VP ():

р: присутствует => имя программы для запуска будет взят из filename поименованных или системы будет search for program file в PATH переменном.

v: присутствует => аргумент будет передан в качестве array

е: нет => среда будет взята из caller’s environ

5.exec v ():

р: нет => имя запускаемой программы будут взяты из pathname

v: присутствует => аргумент будет передан в качестве array

е: нет => среда будет взята из caller’s environ

6.exec л ():

р: нет => имя запускаемой программы будут взяты из pathname

л: присутствует => аргумент будет передан как list


е: нет => среда будет взята из caller’s environ

Изучаем процессы в Linux

В этой статье я хотел бы рассказать о том, какой жизненный путь проходят процессы в семействе ОС Linux. В теории и на примерах я рассмотрю как процессы рождаются и умирают, немного расскажу о механике системных вызовов и сигналов.

Данная статья в большей мере рассчитана на новичков в системном программировании и тех, кто просто хочет узнать немного больше о том, как работают процессы в Linux.

Всё написанное ниже справедливо к Debian Linux с ядром 4.15.0.

Содержание

Введение

Системное программное обеспечение взаимодействует с ядром системы посредством специальных функций — системных вызовов. В редких случаях существует альтернативный API, например, procfs или sysfs, выполненные в виде виртуальных файловых систем.

Атрибуты процесса

Процесс в ядре представляется просто как структура с множеством полей (определение структуры можно прочитать здесь).
Но так как статья посвящена системному программированию, а не разработке ядра, то несколько абстрагируемся и просто акцентируем внимание на важных для нас полях процесса:

  • Идентификатор процесса (pid)
  • Открытые файловые дескрипторы (fd)
  • Обработчики сигналов (signal handler)
  • Текущий рабочий каталог (cwd)
  • Переменные окружения (environ)
  • Код возврата

Жизненный цикл процесса

Рождение процесса

Только один процесс в системе рождается особенным способом — init — он порождается непосредственно ядром. Все остальные процессы появляются путём дублирования текущего процесса с помощью системного вызова fork(2) . После выполнения fork(2) получаем два практически идентичных процесса за исключением следующих пунктов:

  1. fork(2) возвращает родителю PID ребёнка, ребёнку возвращается 0;
  2. У ребёнка меняется PPID (Parent Process Id) на PID родителя.

После выполнения fork(2) все ресурсы дочернего процесса — это копия ресурсов родителя. Копировать процесс со всеми выделенными страницами памяти — дело дорогое, поэтому в ядре Linux используется технология Copy-On-Write.
Все страницы памяти родителя помечаются как read-only и становятся доступны и родителю, и ребёнку. Как только один из процессов изменяет данные на определённой странице, эта страница не изменяется, а копируется и изменяется уже копия. Оригинал при этом «отвязывается» от данного процесса. Как только read-only оригинал остаётся «привязанным» к одному процессу, странице вновь назначается статус read-write.

Состояние «готов»

Сразу после выполнения fork(2) переходит в состояние «готов».
Фактически, процесс стоит в очереди и ждёт, когда планировщик (scheduler) в ядре даст процессу выполняться на процессоре.

Состояние «выполняется»

Как только планировщик поставил процесс на выполнение, началось состояние «выполняется». Процесс может выполняться весь предложенный промежуток (квант) времени, а может уступить место другим процессам, воспользовавшись системным вывозом sched_yield .

Перерождение в другую программу

В некоторых программах реализована логика, в которой родительский процесс создает дочерний для решения какой-либо задачи. Ребёнок в данном случае решает какую-то конкретную проблему, а родитель лишь делегирует своим детям задачи. Например, веб-сервер при входящем подключении создаёт ребёнка и передаёт обработку подключения ему.
Однако, если нужно запустить другую программу, то необходимо прибегнуть к системному вызову execve(2) :

или библиотечным вызовам execl(3), execlp(3), execle(3), execv(3), execvp(3), execvpe(3) :

Все из перечисленных вызовов выполняют программу, путь до которой указан в первом аргументе. В случае успеха управление передаётся загруженной программе и в исходную уже не возвращается. При этом у загруженной программы остаются все поля структуры процесса, кроме файловых дескрипторов, помеченных как O_CLOEXEC , они закроются.

Как не путаться во всех этих вызовах и выбирать нужный? Достаточно постичь логику именования:

  • Все вызовы начинаются с exec
  • Пятая буква определяет вид передачи аргументов:
    • l обозначает list, все параметры передаются как arg1, arg2, . NULL
    • v обозначает vector, все параметры передаются в нуль-терминированном массиве;
  • Далее может следовать буква p, которая обозначает path. Если аргумент file начинается с символа, отличного от «/», то указанный file ищется в каталогах, перечисленных в переменной окружения PATH
  • Последней может быть буква e, обозначающая environ. В таких вызовах последним аргументом идёт нуль-терминированный массив нуль-терминированных строк вида key=value — переменные окружения, которые будут переданы новой программе.

Семейство вызовов exec* позволяет запускать скрипты с правами на исполнение и начинающиеся с последовательности шебанг (#!).

Есть соглашение, которое подразумевает, что argv[0] совпадает с нулевым аргументов для функций семейства exec*. Однако, это можно нарушить.


Любопытный читатель может заметить, что в сигнатуре функции int main(int argc, char* argv[]) есть число — количество аргументов, но в семействе функций exec* ничего такого не передаётся. Почему? Потому что при запуске программы управление передаётся не сразу в main. Перед этим выполняются некоторые действия, определённые glibc, в том числе подсчёт argc.

Состояние «ожидает»

Некоторые системные вызовы могут выполняться долго, например, ввод-вывод. В таких случаях процесс переходит в состояние «ожидает». Как только системный вызов будет выполнен, ядро переведёт процесс в состояние «готов».
В Linux так же существует состояние «ожидает», в котором процесс не реагирует на сигналы прерывания. В этом состоянии процесс становится «неубиваемым», а все пришедшие сигналы встают в очередь до тех пор, пока процесс не выйдет из этого состояния.
Ядро само выбирает, в какое из состояний перевести процесс. Чаще всего в состояние «ожидает (без прерываний)» попадают процессы, которые запрашивают ввод-вывод. Особенно заметно это при использовании удалённого диска (NFS) с не очень быстрым интернетом.

Состояние «остановлен»

В любой момент можно приостановить выполнение процесса, отправив ему сигнал SIGSTOP. Процесс перейдёт в состояние «остановлен» и будет находиться там до тех пор, пока ему не придёт сигнал продолжать работу (SIGCONT) или умереть (SIGKILL). Остальные сигналы будут поставлены в очередь.

Завершение процесса

Ни одна программа не умеет завершаться сама. Они могут лишь попросить систему об этом с помощью системного вызова _exit или быть завершенными системой из-за ошибки. Даже когда возвращаешь число из main() , всё равно неявно вызывается _exit .
Хотя аргумент системного вызова принимает значение типа int, в качестве кода возврата берется лишь младший байт числа.

Состояние «зомби»

Сразу после того, как процесс завершился (неважно, корректно или нет), ядро записывает информацию о том, как завершился процесс и переводит его состояние «зомби». Иными словами, зомби — это завершившийся процесс, но память о нём всё ещё хранится в ядре.
Более того, это второе состояние, в котором процесс может смело игнорировать сигнал SIGKILL, ведь что мертво не может умереть ещё раз.

Забытье

Код возврата и причина завершения процесса всё ещё хранится в ядре и её нужно оттуда забрать. Для этого можно воспользоваться соответствующими системными вызовами:

Вся информация о завершении процесса влезает в тип данных int. Для получения кода возврата и причины завершения программы используются макросы, описанные в man-странице waitpid(2) .

Передача argv[0] как NULL приводит к падению.

Бывают случаи, при которых родитель завершается раньше, чем ребёнок. В таких случаях родителем ребёнка станет init и он применит вызов wait(2) , когда придёт время.

После того, как родитель забрал информацию о смерти ребёнка, ядро стирает всю информацию о ребёнке, чтобы на его место вскоре пришёл другой процесс.

Благодарности

Спасибо Саше «Al» за редактуру и помощь в оформлении;

Спасибо Саше «Reisse» за понятные ответы на сложные вопросы.

Они стойко перенесли напавшее на меня вдохновение и напавший на них шквал моих вопросов.

Exec (системный вызов) — exec (system call)

В вычислениях , Exec является функциональностью в операционной системе , которая запускает исполняемый файл в контексте уже существующий процесс , заменяя предыдущий исполняемый файл. Этот акт также называют накладкой . Это особенно важно в Unix-подобных систем, хотя другие операционные системы реализуют его. Поскольку новый процесс не создается, исходный идентификатор процесса (PID) не изменяется, но машинный код , данные , куча , и стек процесса заменяются теми из новой программы.

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

содержание

Номенклатура

Интерфейсы для EXEC и его реализации различаются. В зависимости от языка программирования может быть доступен через одну или несколько функций , и в зависимости от операционной системы может быть представлена одним или несколькими реальными системных вызовов . По этой причине Exec иногда описывается как набор функций .

Стандартные имена таких функций в C являются execl , execle , функции имеют , execv , execve и execvp (см ниже ), но не «Exec» сами по себе. Ядро Linux имеет один соответствующий системный вызов с именем «execve», в то время как все вышеупомянутые функции пользовательского пространства обертки вокруг него.

Языки высокого уровня , как правило , обеспечивают один вызов по имени EXEC .

Unix, POSIX и других многозадачных систем

языка C прототипы

POSIX стандарт объявляет EXEC функции в unistd.h файл заголовка, в языке C . Те же функции объявлены в process.h для DOS (см ниже ), OS / 2 и Microsoft Windows.

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 []);

Некоторые реализации предоставляют эти функции, названные с начальным символом подчеркивания (например, _execl).

База каждый Exec (выполнить), за которым следует один или более букв:


е — массив указателей на переменные окружения явно передаются в новый образ процесса. л — Аргументы командной строки передаются по отдельности (в л IST) к функции. р — Использует переменную PATH среды , чтобы найти файл с именем в файл аргумент выполняются. v — аргументы командной строки передаются функции в качестве массива ( об Экторе) указателей.

В execl , функции имеют , execv и execvp вызовов, новый образ процесса наследует текущие переменные окружения.

аргументы

Последствия

Дескриптор файла открывается при Exec сделан вызов будет оставаться открытым в новом образе процесса, если он не был отмечен FD_CLOEXEC на fcntl или открыт O_CLOEXEC (последний был введен в POSIX.1-2001). Этот аспект используется для задания стандартных потоков (STDIN, STDOUT и STDERR) новой программы.

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

Возвращаемое значение

Успешное Exec заменяет текущий образ процесса, поэтому он не может ничего вернуться к программе , которая сделала вызов. Процессы действительно имеют статус выхода , но «Exec-ING» не завершение процесса — она продолжает существовать.

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

название Заметки
E2BIG Список аргументов превышает системное ограничение.
EACCES Указанный файл имеет запирающее или совместное нарушение.
ENOENT Имя файла или путь не найдено.
ENOMEM Не хватает памяти для выполнения нового образа процесса.

В Linux, ядро может уничтожить карту памяти старого процесса и начать строительство (загрузок) новый исполняемый файл, и только потом обнаружить , что новый исполняемый файл не может быть загружен (например, потому что некоторые поля во внутренних таблицах исполняемых файла содержат недопустимые ценности). В этом случае процесс убит фатальный сигнал (такие как SIGSEGV ). В идеале, ядро потерпит неудачу evecve и вернуть индикацию ошибки в старом исполняемый файл, но это будет значительно сложнее и медленнее.

операционные системы DOS

DOS не является многозадачной операционной система, но заменяя предыдущий исполняемый файл имеет большую заслугу там из — за жесткие первичную память ограничений и нехватку виртуальной памяти . Же API используется для перекладки программ в DOS и имеет последствия , аналогичные те , на системах POSIX.

MS-DOS Exec функция всегда загружает новую программу в память , как будто «максимальное выделение» в программах исполняемого файл заголовок устанавливается по умолчанию значения 0xFFFF. Утилита EXEHDR может быть использована для изменения максимального поля распределения программы. Однако, если это будет сделано , и программа вызывается с одним из EXEC функций, программа может вести себя по- разному с программой , запущенной непосредственно из командной строки операционной системы или с одним из грибницы функций (см ниже ).

Команда переводчиков

Многие Unix оболочка также предлагает встроенную EXEC команды , которая заменяет процесс оболочки с заданной программой. Wrapper сценарии часто использует эту команду , чтобы запустить программу (либо непосредственно , либо через переводчик или виртуальную машину ) после установки переменных окружения или другой конфигурации. Используя Exec , ресурсы , используемые программой оболочки не должны оставаться в использовании после запуска программы.

Exec команда может также выполнить перенаправление . В некоторых оболочках можно даже использовать EXEC команды только для перенаправления, без фактического наложения.

альтернативы

Традиционная Unix система не имеет функции , чтобы создать новый процесс , протекающий новую исполняемую программу на один шаг, который объясняет важность Exec для программирования Unix. Другие системы могут использовать икру в качестве основного инструмента для запуска исполняемых файлов. Его результат эквивалентен вилке-Exec последовательности Unix-подобных систем. POSIX поддерживает posix_spawn подпрограмму как необязательное расширение, как правило , реализуются с помощью vfork .

Другие системы

OS / 360 и преемники включают в себя системный вызов XCTL (контроль передачи) , который выполняет аналогичную функцию для Exec. Для типа 4 За исключением SVC , это использование редко. Более распространенным является использование LINK или ATTACH для вызова модуля нагрузки без завершения текущего загрузочного модуля. В частности, TSO вызывает команды с ATTACH, разделяя память.

execvpe(3) — Linux man page

execl, execlp, execle, execv, execvp, execvpe — execute a file

Synopsis

extern char **environ;

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[]);
int execvpe(const char *
file, char *const argv[],
char *const
envp[]);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)): execvpe(): _GNU_SOURCE

Description

The exec() family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for execve(2). (See the manual page for execve(2) for further details about the replacement of the current process image.)

The initial argument for these functions is the name of a file that is to be executed.

The const char *arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of as arg0, arg1, . argn. Together they describe a list of one or more pointers to null-terminated strings that represent the argument list available to the executed program. The first argument, by convention, should point to the filename associated with the file being executed. The list of arguments must be terminated by a NULL pointer, and, since these are variadic functions, this pointer must be cast (char *) NULL.

The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer.

The execle() and execvpe() functions allow the caller to specify the environment of the executed program via the argument envp. The envp argument is an array of pointers to null-terminated strings and must be terminated by a NULL pointer. The other functions take the environment for the new process image from the external variable environ in the calling process.

Special semantics for execlp() and execvp() The execlp(), execvp(), and execvpe() functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH environment variable. If this variable isn’t defined, the path list defaults to the current directory followed by the list of directories returned by confstr(_CS_PATH). (This confstr(3) call typically returns the value «/bin:/usr/bin».)


If the specified filename includes a slash character, then PATH is ignored, and the file at the specified pathname is executed.

In addition, certain errors are treated specially.

If permission is denied for a file (the attempted execve(2) failed with the error EACCES), these functions will continue searching the rest of the search path. If no other file is found, however, they will return with errno set to EACCES.

If the header of a file isn’t recognized (the attempted execve(2) failed with the error ENOEXEC), these functions will execute the shell (/bin/sh) with the path of the file as its first argument. (If this attempt fails, no further searching is done.)

Return Value

The exec() functions only return if an error has occurred. The return value is -1, and errno is set to indicate the error.

Errors

All of these functions may fail and set errno for any of the errors specified for execve(2).

Versions

The execvpe() function first appeared in glibc 2.11.

Conforming To

The execvpe() function is a GNU extension.

Notes

On some other systems, the default path (used when the environment does not contain the variable PATH) has the current working directory listed after /bin and /usr/bin, as an anti-Trojan-horse measure. Linux uses here the traditional «current directory first» default path.

The behavior of execlp() and execvp() when errors occur while attempting to execute the file is historic practice, but has not traditionally been documented and is not specified by the POSIX standard. BSD (and possibly other systems) do an automatic sleep and retry if ETXTBSY is encountered. Linux treats it as a hard error and returns immediately.

Traditionally, the functions execlp() and execvp() ignored all errors except for the ones described above and ENOMEM and E2BIG, upon which they returned. They now return if any error other than the ones described above occurs.

Execl, execle, execlp, execv, execve, execvp, execvpe

Load and execute new child processes.

or

Function Required Header Optional Headers Compatibility
_execlp Win 95, Win NT
_wexeclp Win NT

For additional compatibility information, see Compatibility in the Introduction.

LIBC.LIB Single thread static library, retail version
LIBCMT.LIB Multithread static library, retail version
MSVCRT.LIB Import library for MSVCRT.DLL, retail version

If successful, these functions do not return to the calling process. A return value of –1 indicates an error, in which case the errno global variable is set.

errno Value Description
E2BIG The space required for the arguments and environment settings exceeds 32K.
EACCES The specified file has a locking or sharing violation.
EMFILE Too many files open (the specified file must be opened to determine whether it is executable).
ENOENT File or path not found.
ENOEXEC The specified file is not executable or has an invalid executable-file format.
ENOMEM Not enough memory is available to execute the new process; or the available memory has been corrupted; or an invalid block exists, indicating that the calling process was not allocated properly.

Path of file to execute

List of pointers to parameters

Each of these functions loads and executes a new process, passing each command-line argument as a separate parameter and using the PATH environment variable to find the file to execute.

Execl, execle, execlp, execv, execve, execvp, execvpe

execl, execlp, execle, execv, execvp − execute a file

SYNOPSIS

extern char **environ;

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[]);


DESCRIPTION

The exec family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for the function execve(2). (See the manual page for execve for detailed information about the replacement of the current process.)

The initial argument for these functions is the pathname of a file which is to be executed.

The const char *arg and subsequent ellipses in the execl, execlp, and execle functions can be thought of as arg0, arg1, . argn. Together they describe a list of one or more pointers to null-terminated strings that represent the argument list available to the executed program. The first argument, by convention, should point to the file name associated with the file being executed. The list of arguments must be terminated by a NULL pointer.

The execv and execvp functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the file name associated with the file being executed. The array of pointers must be terminated by a NULL pointer.

The execle function also specifies the environment of the executed process by following the NULL pointer that terminates the list of arguments in the parameter list or the pointer to the argv array with an additional parameter. This additional parameter is an array of pointers to null-terminated strings and must be terminated by a NULL pointer. The other functions take the environment for the new process image from the external variable environ in the current process.

Some of these functions have special semantics.

The functions execlp and execvp will duplicate the actions of the shell in searching for an executable file if the specified file name does not contain a slash (/) character. The search path is the path specified in the environment by the PATH variable. If this variable isn’t specified, the default path ‘‘:/bin:/usr/bin’’ is used. In addition, certain errors are treated specially.

If permission is denied for a file (the attempted execve returned EACCES), these functions will continue searching the rest of the search path. If no other file is found, however, they will return with the global variable errno set to EACCES.

If the header of a file isn’t recognized (the attempted execve returned ENOEXEC), these functions will execute the shell with the path of the file as its first argument. (If this attempt fails, no further searching is done.)

RETURN VALUES

If any of the exec functions returns, an error will have occurred. The return value is −1, and the global variable errno will be set to indicate the error.

FILES

ERRORS

All of these functions may fail and set errno for any of the errors specified for the library function execve(2).

SEE ALSO

COMPATIBILITY

On some other systems the default PATH has the current working directory listed after /bin and /usr/bin, as an anti-Trojan-horse measure. As of libc 5.4.7, Linux still uses the traditional «current directory first» default PATH.

The behavior of execlp and execvp when errors occur while attempting to execute the file is historic practice, but has not traditionally been documented and is not specified by the POSIX standard. BSD (and possibly other systems) do an automatic sleep and retry if ETXTBSY is encountered. Linux treats it as a hard error and returns immediately.

Traditionally, the functions execlp and execvp ignored all errors except for the ones described above and ENOMEM and E2BIG, upon which they returned. They now return if any error other than the ones described above occurs.

STANDARDS

Execl, execv, execle, execlp and execvp conform to IEEE Std1003.1-88 (‘‘POSIX.1’’).

exec man page

execl, execlp, execle, execv, execvp, execvpe — execute a file

Synopsis

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

execvpe(): _GNU_SOURCE

Description

The exec() family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for execve(2). (See the manual page for execve(2) for further details about the replacement of the current process image.)

The initial argument for these functions is the name of a file that is to be executed.

The functions can be grouped based on the letters following the «exec» prefix.

l — execl(), execlp(), execle()

The const char *arg and subsequent ellipses can be thought of as arg0, arg1, . argn. Together they describe a list of one or more pointers to null-terminated strings that represent the argument list available to the executed program. The first argument, by convention, should point to the filename associated with the file being executed. The list of arguments must be terminated by a null pointer, and, since these are variadic functions, this pointer must be cast (char *) NULL.


By contrast with the ‘l’ functions, the ‘v’ functions (below) specify the command-line arguments of the executed program as a vector.

v — execv(), execvp(), execvpe()

The char *const argv[] argument is an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a null pointer.

e — execle(), execvpe()

The environment of the caller is specified via the argument envp. The envp argument is an array of pointers to null-terminated strings and must be terminated by a null pointer.

All other exec() functions (which do not include ‘e’ in the suffix) take the environment for the new process image from the external variable environ in the calling process.

p — execlp(), execvp(), execvpe()

These functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH environment variable. If this variable isn’t defined, the path list defaults to a list that includes the directories returned by confstr(_CS_PATH) (which typically returns the value «/bin:/usr/bin») and possibly also the current working directory; see Notes for further details.

If the specified filename includes a slash character, then PATH is ignored, and the file at the specified pathname is executed.

In addition, certain errors are treated specially.

If permission is denied for a file (the attempted execve(2) failed with the error EACCES), these functions will continue searching the rest of the search path. If no other file is found, however, they will return with errno set to EACCES.

If the header of a file isn’t recognized (the attempted execve(2) failed with the error ENOEXEC), these functions will execute the shell (/bin/sh) with the path of the file as its first argument. (If this attempt fails, no further searching is done.)

All other exec() functions (which do not include ‘p’ in the suffix) take as their first argument a (relative or absolute) pathname that identifies the program to be executed.

Return Value

The exec() functions return only if an error has occurred. The return value is -1, and errno is set to indicate the error.

Errors

All of these functions may fail and set errno for any of the errors specified for execve(2).

Versions

The execvpe() function first appeared in glibc 2.11.

Attributes

For an explanation of the terms used in this section, see attributes(7).

Interface Attribute Value
execl(), execle(), execv() Thread safety MT-Safe
execlp(), execvp(), execvpe() Thread safety MT-Safe env

Conforming to

The execvpe() function is a GNU extension.

Notes

The default search path (used when the environment does not contain the variable PATH) shows some variation across systems. It generally includes /bin and /usr/bin (in that order) and may also include the current working directory. On some other systems, the current working is included after /bin and /usr/bin, as an anti-Trojan-horse measure. The glibc implementation long followed the traditional default where the current working directory is included at the start of the search path. However, some code refactoring during the development of glibc 2.24 caused the current working directory to be dropped altogether from the default search path. This accidental behavior change is considered mildly beneficial, and won’t be reverted.

The behavior of execlp() and execvp() when errors occur while attempting to execute the file is historic practice, but has not traditionally been documented and is not specified by the POSIX standard. BSD (and possibly other systems) do an automatic sleep and retry if ETXTBSY is encountered. Linux treats it as a hard error and returns immediately.

Traditionally, the functions execlp() and execvp() ignored all errors except for the ones described above and ENOMEM and E2BIG, upon which they returned. They now return if any error other than the ones described above occurs.

Before glibc 2.24, execl() and execle() employed realloc(3) internally and were consequently not async-signal-safe, in violation of the requirements of POSIX.1. This was fixed in glibc 2.24.

Architecture-specific details

On sparc and sparc64, execv() is provided as a system call by the kernel (with the prototype shown above) for compatibility with SunOS. This function is not employed by the execv() wrapper function on those architectures.

See Also

Colophon

This page is part of release 5.03 of the Linux man-pages project. A description of the project, information about reporting bugs, and the latest version of this page, can be found at https://www.kernel.org/doc/man-pages/.

Referenced By

The man pages execl(3), execle(3), execlp(3), execv(3), execvp(3) and execvpe(3) are aliases of exec(3).

Илон Маск рекомендует:  Что такое код farcalloc
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL