[Перевод] Заметки о Unix: небольшая странность семейства вызовов exec*()
-exec
команды find
и ненароком упомянул о «семействе системных вызовов exec()
». Это — странное выражение, обычно о Unix-вызовах так не говорят, так как они, как правило, не объединяются в некие «семейства». Но в данном случае речь идёт о целом наборе схожих механизмов. Перечислим их: execv() execve() execvp() execvpe()
execl() execlp() execle()
(Этот список выглядит именно так в Linux и в OpenBSD; подобный список, составленный для FreeBSD, включал бы в себя
execvP()
, а не execvpe()
. В POSIX-версии подобного списка нет вызова execvpe()
, но есть вызов fexecve()
, который я не вполне готов включить в семейство вызовов exec()
.)
Одна из этих команд не похожа на другие. На самом деле, во всём этом списке, включающем в себя, как минимум, шесть exec()
-функций, лишь execve()
относится к системным вызовам; остальные exec*()
-функции — это просто библиотечные функции, в основе которых лежит execve()
. То, что существуют удобные библиотечные функции, основанные на системном вызове (или на нескольких вызовах), не является чем-то необычным; так, например, устроено всё то, что имеет отношение к stdio
. Но всё это выглядит несколько странно из-за того, что имена функций весьма близки друг к другу. У меня хорошая память на имена libc
-функций Unix, но я, вероятно, в большинстве случаев, не смог бы выделить из вышеприведённого списка настоящий системный вызов exec()
.
(Сейчас-то я, конечно, хорошо помню о том, что execve()
— это системный вызов, который, в большинстве Unix-дистрибутивов, лежит в основе exec*()
-функций.)
Такое множество функций со схожими именами существует со времён V7 Unix, где документация по execl()
, execv()
, execle()
и execve()
размещена в справочном файле exec (2). В V7, по состоянию на сегодняшний день, базовым системным вызовом является execve()
, хотя ему назначено другое имя. Даже в V6 execl()
и execv()
описаны в единственном справочном файле exec (2).
(Соответствующий системный вызов V6 был назван exec
и принимал лишь программу, которую нужно выполнить, и argv
. Когда в V7 появилось такое понятие, как «окружение», там сохранился системный вызов exec
из V6, который, в качестве дополнительного аргумента, принимал envp
.)
P.S. В некоторых дистрибутивах Unix есть базовые системные вызовы, которые, по сути, являются разновидностями одного и того же вызова. Такая ситуация сложилась из-за того, что API системных вызовов развивался и совершенствовался достаточно длительное время. Например, подобное могло произойти при добавлении в систему 64-битных вариантов вызовов, которые раньше были 32-битными. Правда, обычно в сознании людей присутствуют лишь самые свежие версии системных вызовов; они не представлены некими семействами разновидностей какого-то вызова и в этом смысле не похожи на семейство exec()
.
Встречались ли вы с какими-то странностями, касающимися именования сущностей в Unix?