Читать «Энциклопедия разработчика модулей ядра Linux» онлайн - страница 9

Ори Померанц

/* 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 <name> c %d <minor>\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

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

Версии ядра Linux разделены между устойчивыми версиями (n.<Четное число>.m) и версии разработки (n.<Нечетное число>.m). Версии разработки включают все новые идеи, включая те, которые будут считаться ошибкой или повторно выполнены в следующей версии. В результате Вы не можете доверять интерфейсу в том плане, что он останется тем же самым в версиях разработки. В устойчивых версиях мы можем ожидать, что интерфейс останется тем же самым независимо от версии исправления ошибок (число m).

Эта версия MPG включает поддержку для версии 2.0.x и версии ядра Linux. Так как имеются различия между ними, требуется условная трансляция в зависимости от версии. Способ сделать это сводится к тому, чтобы использовать макрокоманду LINUX_VERSION_CODE. В версии a.b.c ядра значение этой макрокоманды было бы 216a+28b+c. Чтобы получать значение для конкретной версии, мы можем использовать макрокоманду KERNEL_VERSION. Так как этот макрос не определен в 2.0.35, мы определяем его сами в случае необходимости.