Слайд 2
Каналы
Обеспечивают передачу информации в виде потока байтов без
сохранения границ сообщений.
Каналы бывают:
неименованные (каналы)
именованные (FIFO-файлы)
Слайд 3
Неименованные каналы
Нет имени.
Взаимодействовать при помощи неименованных каналов могут
только родственные (имеющие общего родителя или родитель и дочерний
процесс) процессы.
Слайд 4
Системные вызовы
int pipe(int fd[2]);
int pipe2(int fd[2], int flags);
O_NONBLOCK
(O_NDELAY)
O_CLOEXEC
Слайд 5
Последовательность действий
Создать канал
Создать процесс
В каждом из процессов закрыть
неиспользуемый дескриптор
По окончании работы закрыть используемый дескриптор
Слайд 6
Каналы предназначены только для передачи информации в одном
направлении.
Каждый процесс должен иметь для каждого канала только один
открытый дескриптор.
Для двустороннего обмена информацией следует использовать два канала.
Слайд 7
Правила для каналов (1)
При чтении меньшего числа байтов,
чем находится в канале, возвращается требуемое число байтов, остаток
сохраняется для последующих чтений.
Слайд 8
Правила для каналов (2)
При чтении большего числа байтов,
чем находится в канале, возвращается доступное число байтов. Необходимо
правильно обрабатывать данную ситуацию.
Слайд 9
Правила для каналов (3)
Если канал пуст и ни
один процесс не открыл его на запись, при чтении
будет прочитано ноль байтов. Если хотя бы один процесс имеет дескриптор канала, открытый на запись, то читающий процесс будет заблокирован.
Слайд 10
Правила для каналов (4)
Операция записи числа байтов меньшего
емкости канала является атомарной. Данные от нескольких процессов, пишущих
в канал, не перемешиваются.
Слайд 11
Правила для каналов (5)
Операция записи числа байтов большего
емкости канала блокирует процесс до освобождения места в канале.
Запись
в канал, не открытый ни одним процессом на чтение, приводит к посылке процессу сигнала SIGPIPE.
Слайд 12
Режим без блокировки
При создании канала или при помощи
системного вызова fcntl
файловый дескриптор может быть переведен в неблокирующий
режим. В этом случае соответствующие системные вызовы возвращают специальную ошибку EAGAIN.
Слайд 13
Именованные каналы (1)
Сначала необходимо создать файл типа FIFO.
Команда shell mkfifo или системный вызов mknod. При первом
открытии этого файла создается канал. Другие процессы, открывая файл, присоединяются к существующему каналу.
Слайд 14
Именованные каналы (2)
При открытии именованного канала в блокирующем
режиме процесс может быть переведен в состояние ожидания до
появления другого процесса, открывающего тот же самый канал для противоположной операции.
Слайд 15
Именованные каналы (3)
В режиме без блокировки одностороннее открытие
именованного канала возможно только на чтение. При попытке открытия
именованного канала на запись при отсутствующем дескрипторе на чтение приведет к ошибке ENXIO.
Слайд 16
Именованные каналы (4)
После получения файлового дескриптора работа с
именованным каналом ничем не отличается от неименованного. Канал уничтожается
после того, как последний процесс закроет файловый дескриптор.
Слайд 17
Именованные каналы (5)
Удаление файла типа FIFO не влияет
на уже работающие с данным каналом процессы.
Слайд 18
Конвейер команд
Командный интерпретатор shell использует механизм неименованных каналов
при создании конвейера команд:
$ cat myfile | wc
Слайд 19
Создание канала в конвейере команд
Слайд 21
Блокировки файлов
Обязательные
(mandatory lock)
Рекомендательные
(advisory lock)
Слайд 22
Блокировки файлов
Разделяемые
(чтение)
Монопольные
(чтение и запись)
Слайд 23
Поля структуры flock
short l_type – тип блокировки
F_RDLCK, F_WRLCK,
F_UNLCK
short l_whence – точка отсчета, как в lseek()
off_t l_start
– начало записи
off_t l_len – длина записи
pid_t l_pid – pid процесса
Слайд 24
Системный вызов fcntl
int fcntl(int fd, int flag, struct
flock * lock);
flag: F_SETLK, F_SETLKW, F_GETLK
Слайд 26
Драйверы устройств
Символьные драйверы
Блочные драйверы
Драйверы низкого уровня
Слайд 27
Символьные драйверы
Устройства с побайтовым обменом данными: модемы, терминалы,
принтеры, мышь и т.п.
Отсутствует буферный кэш.
У терминалов специальная буферизация.
(ниже)
Слайд 28
Блочные драйверы
Обмен данными с устройством фиксированными порциями (блоками).
Диски.
Используется буферный кэш.
На данных устройствах можно создавать файловые системы.
Слайд 29
Драйверы низкого уровня
Второй интерфейс блочных драйверов для обмена
данными с устройством в обход буферного кэша.
Обмен может осуществляться
порциями, не равными размеру блока, или побайтово.
Слайд 31
Программные драйверы
/dev/kmem
/dev/ksyms
/dev/mem
/dev/null
/dev/zero
/dev/full
/dev/random
Слайд 32
Архитектура драйверов
Старший номер (major number)
адресует драйвер.
Младший номер (minor
number)
передается в качестве параметра драйверу и им интерпретируется.
Слайд 33
Доступ к драйверу
Коммутатор устройств – структура, содержащая указатели
на точки входа (функции) драйвера.
Два коммутатора – для символьных
и блочных драйверов.
Слайд 34
Элемент массива коммутатора устройств (1)
struct bdevsw[]{ /* блочный
драйвер*/
int (*d_open)();
int (*d_close)();
int (*d_strategy)();
int (*d_size)();
int (*d_xhalt)();
…
} bdevsw[];
Слайд 35
Элемент массива коммутатора устройств (2)
struct bdevsw[]{ /* символьный
драйвер*/
int (*d_open)();
int (*d_close)();
int (*d_read)();
int (*d_write)();
int (*d_ioctl)();
…
} bdevsw[];
Слайд 36
Вызов функции драйвера
(*bdevsw[major].d_open) (major, minor, …);
major и minor
могут быть получены с помощью специального макроса из пременной
типа dev_t
Слайд 37
Драйвер как набор функций
Не все функции поддерживает каждый
драйвер. В этом случае используется заглушка.
Все функции имеют двух
символьный префикс, например mmopen() – функция open() драйвера kmem.
Слайд 38
Некоторые функции (1)
xxopen() – все типы драйверов.
Реинициализация физического
устройства и внутренних данных драйвера. Например, размещение дополнительных буферов.
Слайд 39
Некоторые функции (2)
xxclose() – все типы драйверов.
Вызывается, когда
число ссылок на драйвер становится равным нулю. Может вызывать
физическое отключение устройства.
Слайд 40
Некоторые функции (3)
xxread(), xxwrite() – не поддерживается блочными
драйверами.
Обеспечивает операции чтения и записи с устройством.
Слайд 41
Некоторые функции (4)
xxioctl() – не поддерживается блочными драйверами.
Обеспечивает
общий интерфейс управления устройством. Может определять набор команд управления,
передаваемых в драйвер с помощью системного вызова ioctl().
Слайд 42
Некоторые функции (5)
xxintr() – все типы драйверов.
Вызывается при
поступлении прерывания от устройства. Асинхронная функция для устройств, обслуживаемых
по прерыванию.
Слайд 43
Некоторые функции (6)
xxpoll() – все типы драйверов.
Производит опрос
устройства на предмет наличия новых данных для чтения или
готовности приема данных для записи. Асинхронная функция для устройств, не поддерживающих прерывания.
Слайд 44
Некоторые функции (7)
xxhalt() – все типы драйверов.
Останов драйвера
при останове системы или выгрузке драйвера.
Слайд 45
Некоторые функции (8)
xxstrategy() – не поддерживается символьными драйверами.
Обеспечивает
операции блочного ввода/вывода. Может обеспечивать собственную стратегию выполнения операций
целью оптимизации.
Слайд 46
Некоторые функции (9)
xxprint() – все типы драйверов.
Выводит сообщения
драйвера на консоль при загрузке или изменении состояния драйвера.
Слайд 47
Обращение к драйверу
Автоконфигурация
Ввод/вывод
Обработка прерываний
Специальные запросы ioctl()
Реинициализация/останов
Слайд 48
Три контекста вызова
Контекст задачи (по запросу процесса)
Системный контекст
(по запросу подсистемы ядра, например, страничный демон)
Контекст прерывания (обработчик
прерывания)
Слайд 49
Доступ к драйверу символьного устройства
Слайд 50
Доступ к драйверу блочного устройства
Слайд 51
Синхронная и асинхронная части драйвера
Синхронная (верхняя часть) –
по запросу процесса в контексте процесса (доступна u-area).
Асинхронная часть
(нижняя часть) – по запросу ядра (прерывания) в другом контексте.
Слайд 52
Файловый интерфейс
Используется специальный тип файловой системы devfs (specfs).
Часть функций реализуется vnode файловой системы, содержащей файл устройства,
а часть – vnode специальной файловой системы.
Слайд 54
Работа с драйвером реального устройства
Слайд 55
Клоны
Специальные устройства, работа с которыми требует создания структур
данных для каждого процесса: псевдотерминалы (pty), сетевые протоколы (ip,
icmp, arp, le, tcp, udp). Младший номер генерируется автоматически.
Слайд 57
Связь драйвера с ядром
Статические драйверы
Динамические драйверы
Слайд 58
Динамическая установка драйвера (1)
Размещение и динамическое связывание символов
драйвера
Инициализация драйвера и устройства
Добавление точек входа драйвера в коммутатор
устройств
Слайд 59
Динамическая установка драйвера (2)
Установка обработчика прерываний драйвера
Слайд 60
Доступ к блочным драйверам
Два интерфейса:
С использованием буферного кэша
Напрямую
к устройству без буферизации
Слайд 62
Буферизация при работе с символьным драйвером
Если устройство поддерживает
прерывания, то используется функция xxintr()
Если устройство не поддерживает прерывания,
то – xxpoll()
Слайд 63
Архитектура терминального доступа
Последовательный интерфейс, называемый терминальной линией.
Дисциплина линии
– предварительная обработка данных после ввода или перед выводом.
Слайд 64
Два режима работы
Канонический (в виде законченных строк с
использованием дисциплины линии)
Прозрачный (напрямую с устройством)
Слайд 65
Дисциплина линии
Построчный разбор введенных последовательностей
Обработка символов стирания и
удаления всего ввода
Отображение вводимых символов (эхо)
Расширение вывода (табуляция)
Слайд 67
Псевдотерминалы
Эмулятор терминала. Драйвер состоит из двух частей: обычный
терминальный драйвер (подчиненный slave) и управляющий (основной master).
Слайд 68
Взаимодействие процессов с использованием псевдотерминала