Шрифт:
Рассмотрим некоторые из функций, которые QNX/Neutrino обеспечивает для запуска других процессов (или подмены одного процесса другим):
• system;
• семейство функций exec;
• семейство функций spawn;
• fork;
• vfork.
Какую из этих функций применять, зависит от двух требований: переносимости и функциональности. Как обычно, между этими двумя требованиями возможен компромисс.
Обычно при всех запросах на создание нового процесса происходит следующее. Поток в первоначальном процессе вызывает одну из вышеприведенных функций. В конечном итоге, функция заставит администратор процессов создать адресное пространство для нового процесса. Затем ядро выполнит запуск потока в новом процессе. Этот поток выполнит несколько инструкций и вызовет функцию main. (Конечно, в случае вызова функции fork или vfork новый поток начнет выполнение в новом процессе с возврата из fork или vfork, соответственно — как иметь с этим дело, мы вкратце рассмотрим ниже).
Функция system — самая простая функция; она получает на вход одну командную строку, такую же, которую вы набрали бы в ответ на подсказку командного интерпретатора, и выполняет ее.
Фактически, для обработки команды, которую вы желаете выполнить, функция system запускает копию командного интерпретатора.
Редактор, который я использую при написании данной книги, использует вызов system. При редактировании мне может понадобиться выйти в командный интерпретатор, проверить некоторые фрагменты программ, и затем снова вернуться в редактор. Все это необходимо сделать, не потеряв позицию курсора в тексте. В этом редакторе я, к примеру, могу дать команду «:!pwd» для отображения текущего рабочего каталога. Редактор при этом выполнит следующий код:
Подходит ли функция system для всех дел в Поднебесной? Конечно же, нет. Однако, ее применение может быть очень полезно для множества задач, требующих создания процессов.
Давайте рассмотрим ряд других функций создания процессов.
Следующие функции создания процессов, которые следует рассмотреть, принадлежат к семействам exec и spawn. Прежде, чем мы обратимся к подробностям их применения, рассмотрим суть различий между этими двумя группами функций.
Семейство функций exec подменяет текущий процесс другим. Я подразумеваю под этим то, что когда процесс вызывает функцию семейства exec, этот процесс прекращает выполнение текущей программы и начинает выполнять другую. Идентификатор процесса (PID) при этом не меняется, просто процесс преобразуется в другую программу. Что произойдет с потоками в данном процессе? Мы вернемся к этой теме после того, как рассмотрим функцию fork.
С другой стороны, семейство функций spawn так не делает. Вызов функции семейства spawn создает другой процесс (с новым идентификатором), который соответствует программе, указанной в аргументах функции.
Spawn | POSIX | Exec | POSIX |
---|---|---|---|
spawn | Да | ||
spawnl | Нет | execl | Да |
spawnle | Нет | execle | Да |
spawnlp | Нет | execlp | Да |
spawnlpe | Нет | execlpe | Нет |
spawnp | Да | ||
spawnv | Нет | execv | Да |
spawnve | Нет | execve | Да |
spawnvp | Нет | execvp | Да |
spawnvpe | Нет | execvpe | Нет |
Рассмотрим различные варианты функций exec и spawn. В таблице, представленной ниже, вы увидите, что некоторые функции из них предусмотрены POSIX, а некоторые — нет. Конечно, для максимальной переносимости, следует использовать только POSIX-совместимые функции.
При том, что названия функций могут показаться малопонятными, в их суффиксах есть логика.
Суффикс: | Смысл: |
l (нижний регистр «L») | Список аргументов определяется через список параметров, заданный непосредственно в самом вызове и завершаемый нулевым аргументом NULL. |
е | Указывается окружение. |
p | Если не указано полное имя пути программы, для ее поиска используется переменная окружения PATH. |
v | Список аргументов определяется через указатель на вектор (массив) аргументов. |