Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Материалы / ВВОД_вывод_сокет.doc
Скачиваний:
25
Добавлен:
01.05.2014
Размер:
201.22 Кб
Скачать

Int fildes;

char *buf;

int size;

Функция read выполняет чтение из файла с дескриптором fildes в пользовательский буфер buf указанного в параметре size количества байт. Функция возвращает число фактически прочитанных байт. Если файл является специальным файлом устройства или каналом и если в вызове функции open был установлен бит O_NDELAY, функция read в случае отсутствия доступных для чтения данных возвратит управление немедленно.

write

write(fd,buf,count)

int fd,count;

char *buf;

Функция write выполняет запись указанного в count количества байт данных, начиная с адреса buf, в файл с дескриптором fd.

ioctl

ioctl(fildes,cmd,arg)

int fildes,cmd;

Функция ioctl выполняет набор специальных операций по отношению к открытому устройству, дескриптор которого указан в параметре fildes. Тип команды, выполняемой по отношению к устройству, описывается параметром cmd, а параметр arg является аргументом команды.

Система поддерживает «программные устройства», с каждым из которых не связано ни одно конкретное физическое устройство. Например, как устройство трактуется физическая память, чтобы позволить процессу обращаться к ней извне, пусть даже память не является периферийным устройством. Команда ps обращается к информационным структурам ядра в физической памяти, чтобы сообщить статистику процессов.

1.Взаимодействие драйверов с программной и аппаратной средой

В системе UNIX имеется два типа устройств - устройства ввода-вывода блоками и устройства неструктурированного или посимвольного ввода-вывода. Устройства ввода-вывода блоками, такие как диски, для остальной части системы выглядят как запоминающие устройства с произвольной выборкой; к устройствам посимвольного ввода-вывода относятся все другие устройства, в том числе терминалы и сетевое оборудование. Пользователь взаимодействует с устройствами через посредничество файловой системы. Каждое устройство имеет имя, похожее на имя файла, и пользователь обращается к нему как к файлу. Специальный файл устройства имеет индекс и занимает место в иерархии каталогов файловой системы. Файл устройства отличается от других файлов типом файла, хранящимся в его индексе, либо «блочный», либо «символьный специальный», в зависимости от устройства, которое этот файл представляет. Если устройство имеет как блочный, так и символьный интерфейс, его представляют два файла: специальный файл устройства ввода-вывода блоками и специальный файл устройства посимвольного ввода-вывода. Системные функции для обычных файлов, такие как open, close, read и write, имеют то же значение и для устройств, в чем мы убедимся позже. Системная функция ioctl предоставляет процессам возможность управлять устройствами посимвольного ввода-вывода, но не применима в отношении к файлам обычного типа. (И наоборот, системная функция fcntl обеспечивает контроль над действиями, производимыми на уровне дескриптора файла, но не на уровне устройства. В других реализациях функция ioctl применима для файлов всех типов).

Подсистема управления вводом-выводом

-------------------------------------------------------------¬

¦ open close ¦

¦ open close read write ioctl read write ¦

¦ mount umount ¦

L--+-----+----+-----+-----+------------+-----+-----+-----+----

¦ ¦ ¦ ¦ ¦ ¦ ¦ --+-----+---¬

¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ функции ¦

¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ работы с ¦

¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ буферным ¦

¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ кешем ¦

¦ ¦ ¦ ¦ ¦ ¦ ¦ L-----T------

¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦

---+-----+----+-----+-----+-¬ -+-----+---------+-----¬

¦ Таблица ключей устройств ¦ ¦ Таблица ключей уст- ¦

¦ посимвольного ввода-вывода¦ ¦ ройств ввода-вывода ¦

¦ ¦ ¦ блоками ¦

L--T-----T----T-----T-----T-- L--T------T--------T----

¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦

¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦

---+-----+----+-----+-----+-¬ ---+------+--------+---¬

¦open close read write ioctl¦ Точки ¦ open close strategy ¦

¦ ¦ входа ¦ ¦

¦ Драйвер ¦ для ¦ Драйвер ¦

¦ ¦ драй- ¦ ¦

¦программа обработки преры- ¦ веров ¦ программа обработки ¦

¦ ваний от устройства ¦ ¦прерываний от устройств¦

L------------+--------------- L-----------+-----------

¦ ¦

---------+----------¬ ----------+---------¬

¦ Вектор прерывания ¦ ¦ Вектор прерывания ¦

L--------T----------- L---------T----------

¦ ¦

L-------------------T-----------------

¦

Прерывания от устройств

Рисунок 1. Точки входа для драйверов

Интерфейс «ядро - драйвер» описывается в таблице ключей устройств ввода-вывода блоками и в таблице ключей устройств посимвольного ввода-вывода (Рисунок 1). Каждый тип устройства имеет в таблице точки входа, которые при выполнении системных функций адресуют ядро к соответствующему драйверу. Функции open и close, вызываемые файлом устройства, «пропускаются» через таблицы ключей устройств в соответствии с типом файла. Функции mount и umount так же вызывают выполнение процедур открытия и закрытия устройств, но для устройств ввода-вывода блоками. Функции read и write, вызываемые устройствами ввода-вывода блоками и файлами в смонтированных файловых системах, запускают алгоритмы работы с буферным кешем, инициирующие реализацию стратегической процедуры работы с устройствами.

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

mknod/dev/tty13c2 13

«/dev/tty13» - имя файла устройства, «c» указывает, что тип файла - «символьный специальный» («b», соответственно, блочный), «2» -старший номер устройства, «13» - младший номер устройства. Старший номер устройства показывает его тип, которому соответствует точка входа в таблице ключей устройств, младший номер устройства - это порядковый номер единицы устройства данного типа.

------------------------------------------------¬

¦ таблица ключей устройств ввода-вывода блоками ¦

+-------T--------T---------T--------------------+

¦ вход ¦ open ¦ close ¦ strategy ¦

+-------+--------+---------+--------------------+

¦ 0 ¦ gdopen ¦ gdclose ¦ gdstrategy ¦

+-------+--------+---------+--------------------+

¦ 1 ¦ gtopen ¦ gtclose ¦ gtstrategy ¦

L-------+--------+---------+---------------------

-----------------------------------------------------------------¬

¦ таблица ключей устройств посимвольного ввода-вывода ¦

+------T-----------T-----------T---------T-----------T-----------+

¦ вход ¦ open ¦ close ¦ read ¦ write ¦ ioctl ¦

+------+-----------+-----------+---------+-----------+-----------+

¦ 0 ¦ conopen ¦ conclose ¦ conread ¦ conwrite ¦ conioctl ¦

+------+-----------+-----------+---------+-----------+-----------+

¦ 1 ¦ dzbopen ¦ dzbclose ¦ dzbread ¦ dzbwrite ¦ dzbioctl ¦

+------+-----------+-----------+---------+-----------+-----------+

¦ 2 ¦ syopen ¦ nulldev ¦ syread ¦ sywrite ¦ syioctl ¦

+------+-----------+-----------+---------+-----------+-----------+

¦ 3 ¦ nulldev ¦ nulldev ¦ mmread ¦ mmwrite ¦ nodev ¦

+------+-----------+-----------+---------+-----------+-----------+

¦ 4 ¦ gdopen ¦ gdclose ¦ gdread ¦ gdwrite ¦ nodev ¦

+------+-----------+-----------+---------+-----------+-----------+

¦ 5 ¦ gtopen ¦ gtclose ¦ gtread ¦ gtwrite ¦ nodev ¦

L------+-----------+-----------+---------+-----------+------------

Рисунок 10.2. Пример заполнения таблиц ключей устройств ввода-

вывода блоками и символами

Если процесс открывает специальный блочный файл с именем «/dev/dsk1» и кодом 0, ядро запускает программу gdopen в точке 0 таблицы ключей устройств блочного ввода-вывода (Рисунок 10.2); если процесс читает специальный символьный файл с именем «/dev/mem» и кодом 3,ядро запускает программу mmread в точке 3 таблицы ключей устройств посимвольного ввода-вывода. Программа nulldev - это «пустая» программа, используемая в тех случаях, когда отсутствует необходимость в конкретной функции драйвера. С одним старшим номером устройства может быть связано множество периферийных устройств; младший номер устройства позволяет отличить их одно от другого. Не нужно создавать специальные файлы устройств при каждой загрузке системы; их только нужно корректировать, если изменилась конфигурация системы, например, если к установленной конфигурации были добавлены устройства.

На Рисунке приведена программа, использующая функцию ioctl для сохранения текущих установок терминала для файла с дескриптором 0, что соответствует значению дескриптора файла стандартного ввода. Функция ioctl с командой TCGETA приказывает

┌────────────────────────────────────────────────────────────────┐

#include <signal.h> │

#include <termio.h> │

struct termio savetty; │

main() │

{ │

extern sigcatch(); │

struct termio newtty; │

int nrd; │

char buf[32]; │

signal(SIGINT,sigcatch); │

if (ioctl(0,TCGETA,&savetty) == -1) │

{ │

printf("ioctl завершилась неудачно: нет терминала\n"); │

exit(); │

} │

newtty = savetty; │

newtty.c_lflag &= ~ICANON;/* выход из канонического режима */│

newtty.c_lflag &= ~ECHO; /* отключение эхо-сопровождения*/ │

newtty.c_cc[VMIN] = 5; /* минимум 5 символов */ │

newtty.c_cc[VTIME] = 100; /* интервал 10 секунд */ │

if (ioctl(0,TCSETAF,&newtty) == -1) │

{ │

printf("не могу перевести тер-л в режим без обработки\n");│

exit(); │

} │

for(;;) │

{ │

nrd = read(0,buf,sizeof(buf)); │

buf[nrd] = 0; │

printf("чтение %d символов '%s'\n",nrd,buf); │

} │

} │

sigcatch() │

{ │

ioctl(0,TCSETAF,&savetty); │

exit(); │

} │

└────────────────────────────────────────────────────────────────┘

Рисунок 10.17. Режим без обработки - чтение 5-символьных блоков

драйверу извлечь установки и сохранить их в структуре с именем savetty в адресном пространстве задачи. Эта команда часто используется для того, чтобы определить, является ли файл терминалом или нет, поскольку она ничего не изменяет в системе: если она завершается неудачно, процессы предполагают, что файл не является терминалом. Здесь же, процесс вторично вызывает функцию ioctl для того, чтобы перевести терминал в режим без обработки: он отключает эхо-сопровождение ввода символов и готовится к выполнению операций чтения с терминала по получении с терминала 5 символов, как минимум, или по прохождении 10 секунд с момента ввода первой порции символов. Когда процесс получает сигнал о прерывании, он восстанавливает первоначальные параметры терминала и завершается.

┌────────────────────────────────────────────────────────────────┐

#include <fcntl.h> │

│ │

main() │

{ │

register int i,n; │

int fd; │

char buf[256]; │

│ │

/* открытие терминала только для чтения с опцией "no delay" */ │

if((fd = open("/dev/tty",O_RDONLY│O_NDELAY)) == -1) │

exit(); │

│ │

n = 1; │

for(;;) /* всегда */ │

{ │

for(i = 0; i < n; i++) │

if(read(fd,buf,sizeof(buf)) > 0) │

{ │

printf("чтение с номера %d\n",i); │

} │

else │

/* ничего не прочитано; возврат вследствие "no delay" */ │

} │

} │

└────────────────────────────────────────────────────────────────┘

Рисунок 10.18. Опрос терминала

Соседние файлы в папке Материалы