Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform Страница 9
- Категория: Компьютеры и Интернет / Программное обеспечение
- Автор: Роб Кёртен
- Год выпуска: -
- ISBN: -
- Издательство: -
- Страниц: 87
- Добавлено: 2019-06-19 14:38:07
Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform краткое содержание
Прочтите описание перед тем, как прочитать онлайн книгу «Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform» бесплатно полную версию:Книга "Введение в QNX/Neutrino 2» откроет перед вами в мельчайших подробностях все секреты ОСРВ нового поколения от компании QNX Software Systems Ltd (QSSL) — QNX/Neutrino 2. Книга написана в непринужденной манере, легким для чтения и понимания стилем, и поможет любому, от начинающих программистов до опытных системотехников, получить необходимые начальные знания для проектирования надежных систем реального времени, от встраиваемых управляющих приложений до распределенных сетевых вычислительных системВ книге подробно описаны основные составляющие ОС QNX/Neutrino и их взаимосвязи. В частности, уделено особое внимание следующим темам:• обмен сообщениями: принципы функционирования и основы применения;• процессы и потоки: базовые концепции, предостережения и рекомендации;• таймеры: организация периодических событий в программах;• администраторы ресурсов: все, что относится к программированию драйверов устройств;• прерывания: рекомендации по эффективной обработке.В книге представлено множество проверенных примеров кода, подробных разъяснений и рисунков, которые помогут вам детально вникнуть в и излагаемый материал. Примеры кода и обновления к ним также можно найти на веб-сайте автора данной книги, www.parse.com.
Роб Кёртен - Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform читать онлайн бесплатно
Список аргументов здесь — список аргументов командной строки, передаваемых программе.
Заметьте, что в библиотеке языка Си функции spawnlp(), spawnvp() и spawnlpe() все вызывают функцию spawnvpe(), которая, в свою очередь, вызывает POSIX-функцию spawnp(). Функции spawnle(), spawnv() и spawnl() все в конечном счете вызывают функцию spawnve(), которая затем вызывает POSIX-функцию spawn(). И, наконец, POSIX-функция spawnp() вызывает POSIX-функцию spawn(). Таким образом, в основе всех возможностей семейства spawn() лежит сам вызов spawn().
Рассмотрим теперь различные варианты функций spawn() и exec() более подробно так, чтобы вы смогли получить навык свободного использования различных суффиксов. Затем мы перейдем непосредственно к рассмотрению вызова функции spawn().
Суффикс «l»Например, если я хочу вызвать команду ls с аргументами -t, -r, и -l (означает — «сортировать выходные данные по времени в обратном порядке и показывать выходные данные в длинном формате»), я мог бы определить это в программе так:
/* Вызвать ls и продолжить выполнение */
spawnl(P_WAIT, "/bin/ls", "/bin/ls", "-t", "-r", "-l",
NULL);
/* Заменить себя на ls */
execl(P_WAIT, "/bin/ls", "/bin/ls", "-t", "-r", "-l",
NULL);
Или, вариант с применением суффикса v:
char *argv[] = {
"/bin/ls",
"-t",
"-r",
"-l",
NULL
};
/* Вызвать ls и продолжить выполнение */
spawnv(P_WAIT, "/bin/ls", argv);
/* Заменить себя на ls */
execv(P_WAIT, "/bin/ls", "/bin/ls", argv);
Почему именно такой выбор? Он дан для удобства восприятия. У вас может быть синтаксический анализатор, уже встроенный в вашу программу, и может быть удобно сразу оперировать массивами строк. В этом случае я бы рекомендовал применять варианты с суффиксом «v». Или вам может понадобиться запрограммировать вызов программы, когда вам известно, где он находится и какие имеет параметры. В этом случае, зачем вам утруждать себя созданием массива строк, когда вы знаете точно, какие нужны аргументы? Просто передайте их варианту функции с суффиксом «l».
Отметим, что мы передаем реальное имя пути программы (/bin/ls), а затем имя программы еще раз в качестве первого аргумента. Это делается для поддержки программ, которые ведут себя по-разному в зависимости от того, под каким именем они были вызваны.
Например, GNU-утилиты компрессии и декомпрессии (gzip и gunzip) фактически привязаны к одному и тому же исполняемому модулю. Когда исполняемый модуль стартует, он анализирует аргумент argv[0] (передаваемый функции main()) и принимает решение, следует ли выполнять компрессию или декомпрессию.
Суффикс «е»Варианты с суффиксом «е» передают программе окружение. Окружение — это только своего рода «контекст», в котором работает программа. Например, у вас может быть программа проверки орфографии, у которой есть эталонный словарь. Вместо описания каждый раз в командной строке местоположения словаря вы могли бы сделать это в окружении:
$ export DICTIONARY=/home/rk/.dict
$ spellcheck document.1
Команда export предписывает командному интерпретатору создать новую переменную окружения (в нашем случае DICTIONARY) и присвоить ей значение (/home/rk/.dict).
Если вы когда-либо хотели бы использовать различные словари, вы были бы должны изменить среду до выполнения программы. Это просто сделать из оболочки:
$ export DICTIONARY=/home/rk1.altdict
$ spellcheck document.1
Но как сделать это из ваших собственных программ? Для того чтобы применять «e»-версии функций spawn() и exec(), вам следует определить массив строк, представляющих собой окружение:
char *env[] = {
"DICTIONARY=/home/rk/.altdict",
NULL
};
// Запуск проверки в отдельном процессе:
spawnle(P_WAIT, "/usr/bin/spellcheck",
"/usr/bin/spellcheck", "documents.1", NULL, env);
// Запуск проверки вместо себя:
execle("/usr/bin/spellcheck", "/usr/bin/spellcheck",
"document.1", NULL, env);
Суффикс «p»Версии с суффиксом «p» будут искать исполняемый модуль программы в списке каталогов, приведенном в переменной окружения PATH. Вы, вероятно, отметили, что во всех примерах местоположение исполняемых модулей строго определено — /bin/ls и /usr/bin/spellcheck. А как быть с другими исполняемыми модулями? Если вы не хотите сразу определить точный путь к нужной программе, было бы лучше сделать так, чтобы места поиска исполняемых модулей вашей программе сообщил пользователь. Стандартная системная переменная PATH для этого и предназначена. Ниже приведено ее значение для минимальной системы:
PATH=/proc/boot:/bin
Это сообщает командному интерпретатору, что когда я набираю команду, он в первую очередь должен просмотреть каталог /proc/boot/, и если не сможет найти команду там, то должна просмотреть каталог бинарных файлов /bin. Переменная PATH представляет собой разделяемый двоеточиями список каталогов для поиска команд. К переменной PATH вы можете добавлять столько элементов, сколько пожелаете, но имейте в виду, что при поиске файла будут проанализированы все элементы (в приведенной последовательности).
Если вы не знаете путь к выполнимой программе, вы можете использовать варианты с суффиксом «p».
Например:
// Использование явного пути:
execl("/bin/ls", "/bin/ls", "-l", "-t", "-r", NULL);
// Поиск пути в PATH:
execp("ls", "ls", "-l", "-t", "-r", NULL) ;
Если функция execl() не сможет найти ls в /bin, она завершится с ошибкой. Функция execlp() просмотрит все каталоги, указанные в PATH, в поисках ls, и завершится с ошибкой только в том случае, если не сможет найти ls ни в одном из этих каталогов. Это также прекрасная вещь для многоплатформенной поддержки — вашей программе не обязательно знать имена каталогов, принятых на разных машинах, она просто выполнит поиск.
А что произойдет, если сделать так?
execlp("/bin/ls", "ls", "-l", "-t", "-r", NULL);
Выполняет ли этот вызов поиск в окружении? Нет. Вы явно указали execlp() имя пути, что отменяет правило поиска в PATH. Если ls не будет найдена в /bin (а здесь это будет именно так), то никаких других попыток поиска не выполняется — эта ситуация подобна варианту с использованием функции execl()).
Опасно ли смешивать явный путь с простым именем команды (например, указывать путь как /bin/ls, а имя — как ls вместо /bin/ls)? Обычно нет, потому что:
• значительное число программ так или иначе игнорирует argv[0];
• те программы, поведение которых зависит от их имени, обычно вызывают функцию basename(), которая удаляет каталоговую часть argv[0] и возвращает только имя.
Единственная обоснованная причина использования полного имени пути в качестве первого параметра заключается в том, что программа может выводить диагностические сообщения, содержащие этот первый параметр, который немедленно укажет вам, откуда она была вызвана. Это может быть важно, если копии программы располагаются в нескольких каталогах из перечисленных в PATH.
Функции семейства spawn() имеют дополнительный параметр; во всех приведенных выше примерах я всегда указывал P_WAIT. Имеются четыре флага, которые вы можете придать функции spawn(), чтобы изменить ее поведение:
P_WAIT Вызывающий процесс (ваша программа) будет блокирован до тех пор, пока вновь созданный процесс не отработает и не завершится. P_NOWAIT Вызывающая программа не будет блокирована на время выполнения вновь созданной. Это позволяет вам запустить программу в фоновом режиме и продолжать выполнение, пока она делает свое дело. P_NOWAITO Аналогично P_NOWAIT за исключением того, что устанавливается флаг SPAWN_NOZOMBIE. Это означает, что вы не должны беспокоить себя вызовом функции waitpid() для очистки кода завершения процесса. P_OVERLAY Этот флаг превращает вызов функции spawn() в соответствующей вызов exec()! Ваша программа преобразуется в указанную программу без изменения идентификатора процесса ID. Вообще-то, если вы хотите сделать именно так, то, наверное, будет более корректно использовать вызов exec(), поскольку это избавит будущих читателей ваших исходных текстов от необходимости искать P_OVERLAY в справочном руководстве по библиотеке языка Си! Просто spawn()Как мы упомянули выше, все функции семейства spawn(), в конечном счете, вызывают базовую функцию spawn(). Ниже приведен прототип функции spawn():
Жалоба
Напишите нам, и мы в срочном порядке примем меры.