- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Энциклопедия разработчика модулей ядра Linux - Ори Померанц
Шрифт:
Интервал:
Закладка:
/* A pointer to the inode structure for
* the file, if we need it. In our case we
* do, because we need a write function. */
NULL
/* The read function for the file. Irrelevant,
* because we put it in the inode structure above */
};
/* Module initialization and cleanup ******************* */
/* Initialize the module - register the proc file */
int init_module() {
/* Success if proc_register[_dynamic] is a success, failure otherwise */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
/* In version 2.2, proc_register assign a dynamic
* inode number automatically if it is zero in the
* structure, so there's no more need for
* proc_register_dynamic */
return proc_register(&proc_root, &Our_Proc_File);
#else
return proc_register_dynamic(&proc_root, &Our_Proc_File);
#endif
}
/* Cleanup - unregister our file from /proc */
void cleanup_module() {
proc_unregister(&proc_root, Our_Proc_File.low_ino);
}
Работа с файлами устройств (запись и IOCTL)
Файлы устройства представляют физические устройства. Многие физические устройства используются для вывода и для ввода, так должен иметься некоторый механизм для драйверов устройства в ядре, чтобы послать вывод устройству из процесса. Это выполняется, открывая файл устройства для вывода и записывая в него точно так же, как в обычный файл. В следующем примере, это выполнено функцией device_write.
Этого не всегда достаточно. Вообразите, что Вы имеете последовательный порт, связанный с модемом (даже если Вы имеете внутренний модем, он выглядит с точки зрения CPU как последовательный порт, связанный с модемом, так что Вы не должны слишком сдерживать Ваше воображение). Естественное решение использовать файл устройства, чтобы передавать модему команды модема или данные, которые будут посланы через телефонную линию и читать из модема ответы для команд или данные, полученные через телефонную линию. Однако, это оставляет открытым вопрос о том что делать, когда Вы должны работать с последовательным портом непосредственно, например настроить скорость обмена данными с портом.
Ответ в Unix должен использовать специальную функцию, названную ioctl (сокращение от input output control). Каждое устройство может иметь собственные команды ioctl, которые могут читать ioctl (для передачи данных от процесса ядру), записывать ioctl (чтобы возвратить информацию процессу)[4], выполнять оба действия или ни одно из них. Функция ioctl вызывается с тремя параметрами: описатель файла соответствующий файлу устройства, ioctl номер, и параметра, который имеет тип long, так что Вы можете использовать приведение, чтобы передать что-нибудь.[5]
Ioctl номер кодирует главный номер устройства, тип ioctl команды и тип параметра. Этот ioctl номер обычно создается макрообращением (_IO, _IOR, _IOW или _IOWR: в зависимости от типа) в файле заголовка. Этот файл заголовка должен быть присоединен командой #include программой, которая использует ioctl и модулем (так что они могут генерировать соответствующие ioctl). В примере ниже, файл заголовка chardev.h и программа, которая использует это ioctl.c.
Если Вы хотите использовать ioctl в ваших собственных модулях, самое лучшее получить официальное ioctl назначение, так, если Вы случайно получаете ioctl кого-то другого вы будете знать, что что-то неправильно. Для большего количества информации, проконсультируйтесь в файле `Documentation/ioctl-number.txt' дерева исходников ядра.
chardev.c/* chardev.c
*
* Create an input/output character device
*/
/* Copyright (C) 1998-99 by Ori Pomerantz */
/* The necessary header files */
/* Standard in kernel modules */
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
/* For character devices */
/* The character device definitions are here */
#include <linux/fs.h>
/* A wrapper which does next to nothing at
* at present, but may help for compatibility
* with future versions of Linux */
#include <linux/wrapper.h>
/* Our own ioctl numbers */
#include "chardev.h"
/* In 2.2.3 /usr/include/linux/version.h includes a
* macro for this, but 2.0.35 doesn't - so I add it
* here if necessary. */
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
#include <asm/uaccess.h> /* for get_user and put_user */
#endif
#define SUCCESS 0
/* Device Declarations ******************************** */
/* The name for our device, as it will appear in /proc/devices */
#define DEVICE_NAME "char_dev"
/* The maximum length of the message for the device */
#define BUF_LEN 80
/* Is the device open right now? Used to prevent concurent access into the same device */
static int Device_Open = 0;
/* The message the device will give when asked */
static char Message[BUF_LEN];
/* How far did the process reading the message get?
* Useful if the message is larger than the size of the
* buffer we get to fill in device_read. */
static char *Message_Ptr;
/* This function is called whenever a process attempts to open the device file */
static int device_open(struct inode *inode, struct file *file) {
#ifdef DEBUG
printk("device_open(%p)n", file);
#endif
/* We don't want to talk to two processes at the same time */
if (Device_Open) return -EBUSY;
/* If this was a process, we would have had to be
* more careful here, because one process might have
* checked Device_Open right before the other one
* tried to increment it. However, we're in the
* kernel, so we're protected against context switches.
*
* This is NOT the right attitude to take, because we
* might be running on an SMP box, but we'll deal with
* SMP in a later chapter. */
Device_Open++;
/* Initialize the message */
Message_Ptr = Message;
MOD_INC_USE_COUNT;
return SUCCESS;
}
/* This function is called when a process closes the
* device file. It doesn't have a return value because
* it cannot fail. Regardless of what else happens, you
* should always be able to close a device (in 2.0, a 2.2
* device file could be impossible to close). */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static int device_release(struct inode *inode, struct file *file)
#else
static void device_release(struct inode *inode, struct file *file)
#endif
{
#ifdef DEBUG
printk("device_release(%p,%p)n", inode, file);
#endif
/* We're now ready for our next caller */
Device_Open--;
MOD_DEC_USE_COUNT;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
return 0;
#endif
}
/* This function is called whenever a process which
* has already opened the device file attempts to read from it. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static ssize_t device_read(
struct file *file,
char *buffer, /* The buffer to fill with the data */
size_t length, /* The length of the buffer */
loff_t *offset) /* offset to the file */
#else
static int device_read(
struct inode *inode, struct file *file,
char *buffer, /* The buffer to fill with the data */
int length) /* The length of the buffer (mustn't write beyond that!) */
#endif
{
/* Number of bytes actually written to the buffer */
int bytes_read = 0;
#ifdef DEBUG
printk("device_read(%p,%p,%d)n", file, buffer, length);
#endif
/* If we're at the end of the message, return 0 (which signifies end of file) */
if (*Message_Ptr == 0) return 0;
/* Actually put the data into the buffer */
while (length && *Message_Ptr) {
/* Because the buffer is in the user data segment,
* not the kernel data segment, assignment wouldn't
* work. Instead, we have to use put_user which
* copies data from the kernel data segment to the
* user data segment. */
put_user(*(Message_Ptr++), buffer++);
length--;
bytes_read++;
}
#ifdef DEBUG
printk("Read %d bytes, %d leftn", bytes_read, length);
#endif
/* Read functions are supposed to return the number
* of bytes actually inserted into the buffer */
return bytes_read;
}
/* This function is called when somebody tries to write into our device file. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static ssize_t device_write(struct file *file, const char *buffer, size_t length, loff_t *offset)
#else
static int device_write(struct inode *inode, struct file *file, const char *buffer, int length)
#endif
{
int i;
#ifdef DEBUG
printk("device_write(%p,%s,%d)", file, buffer, length);
#endif
for(i=0; i<length && i<BUF_LEN; i++)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
get_user(Message[i], buffer+i);
#else
Message[i] = get_user(buffer+i);
#endif
Message_Ptr = Message;
/* Again, return the number of input characters used */
return i;
}
/* This function is called whenever a process tries to
* do an ioctl on our device file. We get two extra
* parameters (additional to the inode and file
* structures, which all device functions get): the number
* of the ioctl called and the parameter given to the ioctl function.
*
* If the ioctl is write or read/write (meaning output