return -EBUSY;
}
dev_state->dev_open = 1;
dev_state->byte_read = 0;
dev_state->byte_write = 0;
MOD_INC_USE_COUNT;
return 0;
}
Младший номер устройства мы получаем с помощью вызова MINOR (inode->i_rdev). Если устройство уже открыто, мы выводим сообщение: Devise is busy. В противном случае устанавливаем флаг открытия устройства, обнуляем byte_read и byte_write, а также увеличиваем счетчик использования данного модуля (MOD_INC_USE_COUNT).
Функция закрытия устройства сбрасывает флаг dev_open и уменьшает счетчик использования устройства.
Листинг 28.8. Функция закрытия устройства
static int device_close(struct inode *inode, struct file *fp) {
struct device_state *dev_state;
printk('My module: try to close device with minor number %d
',
MINOR(inode->i_rdev));
dev_state = &state[MINOR(inode->i_rdev)];
if (!dev_state->dev_open) {
printk('Device is not open
');
return 0;
}
dev_state->dev_open=0;
MOD_DEC_USE_COUNT;
return 0;
}
Теперь нам нужно указать ядру, какие функции нужно использовать для открытия и закрытия устройства:
struct file_operations FO = {
open: device_open,
release: device_close
};
Полный код модуля устройства device вместе с функциями открытия и закрытия устройства, а также структурой file_operations приведен в следующем листинге:
Листинг 28.9. Модуль устройства device (module.с)
#define MODULE
#define __KERNEL__
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h> // регистрация устройств
#include <linux/ioport.h> // работа с портами ввода/вывода
#include <linux/sched.h> // резервирование прерывания
// Имя нашего устройства
#define DEV_NAME 'device'
// Порты ввода-вывода нашего устройства
#define PORT_START 0x2000
#define PORT_QTY 10
// Память нашего устройства
#define MEM_START 0x20000000
#define MEM_QTY 0x20
// Номер прерывания для нашего устройства
#define IRQ_NUM 9
MODULE_AUTHOR('Denis Kolisnichenko [email protected]');
MODULE_DESCRIPTION('Linux kernel module');
// Старший номер файла устройства
static int Major;
// Структура file_operations - пока пустая,
// но вскоре мы ее напишем
struct file_operations FO {
open: device_open,
release: device_close
};
// Структура для хранения состояния устройства
struct device_state {
int dev_open; // 1 - устройство открыто, 0 — закрыто
ssize_t byte_read; // Количество прочитанных байтов
// из устройства
ssize_t byte_write; // Количество записанных байтов
};
// Массив для хранения информации о состоянии устройств
static struct device_state state[2];
// Обработчик прерывания
void irq_handler(int irq, void *dev_id, struct pt_regs
*regs) {
return;
}
int init_module() {
// Регистрируем устройство
printk('My module: starting...
') ;
Major = register_chrdev(0, DEV_NAME, &F0);
if (Major < 0) {
// Устройство не зарегистрировано
printk('My module: registration failed
');
return Major;
}
printk('My module: device registered, major number = %d
',
Major);
// Резервирование портов ввода-вывода