Энциклопедия разработчика модулей ядра Linux - [5]

Шрифт
Интервал

> * is because the maximum length of the message

> * (assuming 32 bit integers - up to 10 digits

> * with the minus sign) is less than BUF_LEN, which

> * is 80. BE CAREFUL NOT TO OVERFLOW BUFFERS,

> * ESPECIALLY IN THE KERNEL!!! */

> Message_Ptr = Message;

> /* Make sure that the module isn't removed while

> * the file is open by incrementing the usage count

> * (the number of opened references to the module, if

> * it's not zero rmmod will fail)

> */

> MOD_INC_USE_COUNT;

> return SUCCESS;

>}


>/* This function is called when a process closes the

>* device file. It doesn't have a return value in

>* version 2.0.x because it can't fail (you must ALWAYS

>* be able to close a device). In version 2.2.x it is

>* allowed to fail - but we won't let it. */

>#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--;

> /* Decrement the usage count, otherwise once you opened the file you'll never get rid of the module. */

> MOD_DEC_USE_COUNT;

>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

> return 0;

>#endif

>}


>/* This function is called whenever a process which

>* have 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 data */

> size_t length, /* The length of the buffer */

> loff_t *offset) /* Our offset in 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;

> /* 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 left\n", 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 - unsupported in this example. */

>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

>static ssize_t device_write(struct file *file,

> const char *buffer, /* The buffer */

> size_t length, /* The length of the buffer */

> loff_t *offset) /* Our offset in the file */

>#else

>static int device_write(struct inode *inode, struct file *file, const char *buffer, int length)

>#endif

>{

> return -EINVAL;

>}


>/* Module Declarations ***************************** */

>/* The major device number for the device. This is

>* global (well, static, which in this context is global

>* within this file) because it has to be accessible * both for registration and for release. */

>static int Major;


>/* This structure will hold the functions to be

>* called when a process does something to the device

>* we created. Since a pointer to this structure is

>* kept in the devices table, it can't be local to

>* init_module. NULL is for unimplemented functions. */

>struct file_operations Fops = {

> NULL, /* seek */

> device_read, device_write,

> NULL, /* readdir */

> NULL, /* select */

> NULL, /* ioctl */

> NULL, /* mmap */

> device_open,

>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

> NULL, /* flush */

>#endif

> device_release /* a.k.a. close */

>};


>/* Initialize the module - Register the character device */

>int init_module() {

> /* Register the character device (atleast try) */

> Major = module_register_chrdev(0, DEVICE_NAME, &Fops);

> /* Negative values signify an error */

> if (Major < 0) {

>  printk("%s device failed with %d\n", "Sorry, registering the character", Major);

>  return Major;

> }

> printk("%s The major device number is %d.\n", "Registeration is a success.", Major);

> printk("If you want to talk to the device driver,\n");

> printk("you'll have to create a device file. \n");

> printk("We suggest you use:\n");

> printk("mknod c %d \n", Major);

> printk("You can try different minor numbers %s", "and see what happens.\n");

> return 0;

>}


>/* Cleanup - unregister the appropriate file from /proc */

>void cleanup_module() {

> int ret;

> /* Unregister the device */

> ret = module_unregister_chrdev(Major, DEVICE_NAME);

> /* If there's an error, report it */

> if (ret < 0) printk("Error in unregister_chrdev: %d\n", ret);

>}

Исходники для разных версий ядра Files

Системные вызовы, которые являются главным интерфейсом ядра, для процессов выглядят одинаково, независимо от версии. Новый системный вызов может быть добавлен, но старые обычно будут вести себя точно так, как и раньше. Это необходимо для обратной совместимости новая версия ядра, как предполагается, не разрывает регулярные процессы. В большинстве случаев, файлы устройства также останутся теми же самыми. С другой стороны, внутренние интерфейсы ядра могут изменяться между версиями.


Рекомендуем почитать
Графика DirectX в Delphi

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Вторая жизнь старых компьютеров

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


DirectX 8. Начинаем работу с DirectX Graphics

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.