Використання спеціальних файлів 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Використання спеціальних файлів



Доступ до спеціального файла розглянемо на прикладі пристрою /dev/random, який можна використати як генератор випадкових чисел:

Unsigned int randval;

int randfd = open("/dev/random". 0_RD0NLY):

read(randfd, (char *)&randval, sizeof(randval));

printf(“випадкове значення: %u\n", randval);

Зазначимо, що, якщо спробувати зчитати великий обсяг даних із цього при­строю, операція читання може бути заблокована доти, поки користувач не вико­нає додаткових інтерактивних дій із системою (пересуне мишу, введе символи із клавіатури тощо), додаючи джерело випадковості. Якщо така затримка непри­йнятна, можна використати пристрій /dev/urandom, операція читання з якого не може бути заблокована.

 

2.

 

Драйвер звичайно складається із коду ініціалізації, реалізації файлових опе­рацій і оброблювачів переривань. Якщо драйвер не використовує введення-виве-дення, кероване перериваннями, а застосовує опитування пристрою, оброблювачі переривань у ньому можуть не реалізуватись. Далі припускатимемо, що буде ви­користане введення-виведення на базі переривань.

Код ініціалізації виконують під час завантаження ядра (а також під час заван­таження у пам'ять модуля із кодом драйвера, якщо він реалізований як модуль ядра). Він складається з однієї функції - і nit О. У ній відбувається реєстрація драйвера у системі (вибір номера драйвера, реєстрація оброблювачів переривань тощо). Зазначимо, що спеціальні файли мають створюватись окремо із режиму користувача утилітою mknod.

Код реалізації файлових операцій зводиться до набору функцій, що реалізу­ють реакцію на виконання основних системних викликів файлового введення-ви­ведення. Набір цих функцій розрізняють для блокових і символьних драйверів.

1. Для символьних можна реалізувати реакцію на виконання таких викликів, як openO, close(), read(), write(), 1 seek (), select () (для організації підтримки пові­домлення), mmap().

2. Для блокових важливим є те, що реалізовані в них функції реакції на операції читання і записування викликають не прямо, а після того, як керування про­йшло через буферний кеш (за наявності відповідного блоку в кеші операції його читання або записування можуть зовсім не викликатися). Читання і за­писування тут за традицією реалізовані у рамках однієї функції, позначеної в UNIX як strategy(), а в Linux - request ().

Окремо слід виділити реалізацію реакції на універсальний системний виклик ioctl (), для якого треба продумати набір команд і необхідні структури даних.

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

 

 

3.

Приклад алгоритму обробки запиту введення-виведення в UNIX (не вра­ховуючи особливості функціонування пристрою).

1. Процес користувача виконує системний виклик read() для спеціального файла пристрою, перед цим підготувавши буфер у своєму адресному просторі та пе­редавши його адресу в цей системний виклик.

2. Відбувається перехід у привілейований режим для виконання коду драйвера пристрою. Як відомо, кожному процесові у привілейованому режимі доступна вся область даних ядра, тому цей перехід не спричиняє перемикання контек­сту — система продовжує виконувати той самий процес.

3. На підставі інформації, що зберігається в індексному дескрипторі спеціально­го файла, викликається функція, зареєстрована як реалізація файлової опера­ції read О для відповідного драйвера.

4. Ця функція виконує необхідні підготовчі операції (наприклад, розміщує бу­фер у пам'яті ядра для збереження даних, отриманих від пристрою), відсилає контролеру пристрою запит на виконання операції читання та переходить у режим очікування (призупиняючи цим процес, що виконав операцію читан­ня); для цього зазвичай використовують функцію sleep on().

5. Контролер читає дані із пристрою, можливо, заповнюючи буфер, наданий реа­лізацією реакції на read(). Коли читання завершене, він генерує переривання.

6. Апаратне забезпечення активізує верхню половину оброблювача переривання. Код верхньої половини ставить у чергу на виконання код нижньої половини.

7. Код нижньої половини заповнює даними буфер, якщо він не був заповнений контролером, виконує інші необхідні дії для завершення операції введення і поновлює виконання процесу, що очікує.

8. Після поновлення керування знову потрапляє в код реакції на read() — цього разу у фрагмент, що слідує за викликом функції sleep оп(). Цей код копіює дані із буфера ядра у буфер режиму користувача (код оброблювача цього зробити не може, оскільки він не має доступу до даних режиму користувача), після чо­го виконання системного виклику завершується. 9. Керування повертають у процес користувача.

 

 

4.

Базовим компонентом підсистеми введення-виведення Windows ХР є менеджер введення-виведення (I/O Manager). який розв'язує одну із найваж­ливіших задач - передає дані між рівнями підсистеми.



Поделиться:


Последнее изменение этой страницы: 2017-02-05; просмотров: 162; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.224.246.203 (0.006 с.)