#c #process #popen #execl
#c #процесс #popen #execl
Вопрос:
Я изучаю реализацию Apple popen()
at https://opensource.apple.com/source/Libc/Libc-167/gen.subproj/popen.c.auto.html и заметил , что они делают execl(_PATH_BSHELL, "sh", "-c", command, NULL)
вместо execl(_PATH_BSHELL, command, NULL)
этого .
Почему вы хотите (или должны) выполнить исполняемый файл, например a.out
, via sh -c
, а не только сам исполняемый файл?
Если вы sh -c a.out
выполняете вместо самого a.out
себя, становится ли фактический a.out
процесс в конечном итоге «внучатым» процессом, а не дочерним процессом?
Ответ №1:
Почему вы хотите (или должны) выполнить исполняемый файл, например
a.out
, viash -c
, а не только сам исполняемый файл?
popen()
предназначен для выполнения команд оболочки, которые включают синтаксис оболочки, такой как >
перенаправление, |
каналы и amp;amp;
цепочка команд. Ему необходимо передать строку, sh -c
чтобы поддерживать эти конструкции. Если бы это было не так, эти синтаксические функции были бы переданы дословно рассматриваемой программе в качестве аргументов.
Например, popen("make clean amp;amp; make")
должен вызвать два make
вызова. Без sh -c
него вызывался make
бы один раз с тремя аргументами, как если бы кто-то набрал
$ make clean 'amp;amp;' make
на терминале.
Если вы
sh -c a.out
выполняете вместо самогоa.out
себя, становится ли фактическийa.out
процесс в конечном итоге «внучатым» процессом, а не дочерним процессом?
Да, это правильно. Между sh
текущим процессом и a.out
.
Комментарии:
1. Это последнее зависит от того, что
sh
есть. Например, если это bash или zsh, он будет выполняться без разветвления (если команда достаточно проста), поэтому в конечном итоге он станет дочерним. Dash этого не делает, поэтому, если вы используете систему, где sh — это dash, она будет работать так, как вы укажете.
Ответ №2:
что они делают
execl(_PATH_BSHELL, "sh", "-c", command, NULL)
вместоexecl(_PATH_BSHELL, command, NULL)
Последний НЕ выполнялся command
бы напрямую, но _PATH_BSHELL
( /bin/sh
) с его $0
значением command
и без аргументов, что приводит к тому, что оболочка ожидает команды от своего stdin.
Кроме того, этот синтаксис зависит от NULL
определения явного указателя (например ((void*)0)
, ), а не только 0
, что нигде не гарантируется. Хотя они могут делать это в своей реализации (потому что они контролируют все заголовки), это не то, что вы должны делать в коде приложения.
И нет, execl(command, command, (void*)NULL)
он бы тоже не выполнялся command
напрямую, если command
только это не а) полный путь и б) в исполняемом формате (двоичный файл или скрипт, начинающийся с she-bang #!
— последнее является нестандартным расширением). Если command
нужно было искать простое имя команды PATH
(например pwd
, или a.out
) или исполняемый скрипт, не начинающийся с she-bang, вы должны были использовать execlp
вместо execl
.
exec[lv]p[e]
Функции выполняют некоторые вещи, которые выполняет оболочка (например, просмотр PATH
), но не все из них (например, выполнение нескольких команд или расширение переменных): вот почему функции любят system(3)
или popen(3)
передают команду /bin/sh -c
. Обратите внимание, что с обоими это /bin/sh
, а не с оболочкой входа пользователя или $SHELL
из используемой среды.
Если вы
sh -c a.out
выполняете вместо самогоa.out
себя, становится ли фактическийa.out
процесс в конечном итоге «внучатым» процессом, а не дочерним процессом?
Только с некоторыми оболочками, такими как dash
. Не с bash
помощью , ksh93
, mksh
, zsh
, yash
, busybox
, и т. Д., Который будет выполняться a.out
напрямую, а не разветвляться и ждать его.