Вход/Регистрация
Разработка приложений в среде Linux. Второе издание
вернуться

Троан Эрик В.

Шрифт:

При разработку программы написанный код работает в режиме пользователя (user mode). Драйверы устройств и файловые системы, наоборот, работают в режиме ядра (kernel mode). В пользовательском режиме программы тщательно защищены от повреждений, вызванных их взаимодействием друг с другом или остальной частью системы. Код, работающий в режиме ядра, имеет полный доступ к компьютеру и может делать или же разрушать все, что угодно.

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

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

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

9.2.1. Ограничения системных вызовов

Режим ядра защищен от влияния режима пользователя. Одна из таких защит состоит в том, что тип данных, передаваемых между режимами ядра и пользователя, ограничен, легко верифицируется и следует строгим соглашениям.

• Длина каждого аргумента, передаваемого из режима пользователя в режим ядра, практически всегда соответствует размеру слов, используемых машиной для представления указателей. Этого размера достаточно как для передачи указателей, так и длинных целых. Переменные типа

char
и
short
перед передачей расширяются до большего типа.

• Тип возвращаемого значения ограничен размером слова со знаком. Первые несколько сотен небольших отрицательных целых чисел зарезервированы в качестве кодов ошибок, и в пределах системных вызовов имеют одинаковое значение. Это значит, что системные вызовы, возвращающие указатель, не могут вернуть некоторые указатели, соответствующие адресам в верхней области доступной виртуальной памяти. К счастью, эти адреса находятся в зарезервированном пространстве и в любом случае никогда не возвращаются, потому возвращаемые слова со знаком могут быть без проблем преобразованы в указатели.

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

9.2.2. Коды возврата системных вызов

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

errno
[15] . В большинстве случаев все, что вам необходимо при проверке ошибки — посмотреть, отрицательный ли код возврата. Коды ошибок определены в
<errno.h>
, и
errno
можно сравнить с любым номером ошибки из этого файла, после чего обработать ее специальным образом.

15

Для многопоточных приложений библиотека хранит код ошибки там, где функция

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

Переменная

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

perror

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

if ((file = open(DB_PATH, O_RDONLY)) < 0) {

 perror("не удается открыть файл базы данных");

}

Функция

perror
выведет сообщение, описывающее возникшую ошибку, а также объяснение того, что код собирался делать:

не удается открыть файл базы данных: No such file or directory

Обычно неплохо делать свои аргументы для

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

strerror

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

perror
.

  • Читать дальше
  • 1
  • ...
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: