Разработка модуля для ядра Linux 2.6.38

Автор: Пользователь скрыл имя, 03 Октября 2011 в 19:49, курсовая работа

Краткое описание

Модуль - это некий код, который может быть загружен или выгружен ядром по мере необходимости[1]. Модули расширяют функциональные возможности ядра без необходимости перезагрузки системы. Например, одна из разновидностей модулей ядра, драйверы устройств, позволяют ядру взаимодействовать с аппаратурой компьютера. При отсутствии поддержки модулей пришлось бы писать монолитные ядра и добавлять новые возможности прямо в ядро. При этом, после добавления в ядро новых возможностей, пришлось бы перезагружать систему.

Оглавление

Задание 4

Особенности реализации модуля ядра 5

Методы 5

Вывод информации 5

Пространство пользователя и пространство ядра 5

Сборка 6

Загрузка и выгрузка ядра 6

Файлы символьных устройств 7

Структура file_operations 7

Регистрация устройства 8

Отключение устройства 8

Создание файла устройства 8

Работа пользовательского приложения с модулем ядра 9

Разработка модуля ядра 10

Разработка простейшего модуля ядра 10

Создание прототипов функций 10

Реализация функций 11

Организация обмена данных с пространством пользователя 11

Реализация политики безопасности 12

Организация работы с модулем ядра 14

Заключение 15

Библиографический список 16

Приложение 17

Структура file_operations для ядра Linux 2.6.38 17

Код модуля ядра 18

Файлы: 1 файл

Модуль ядра.docx

— 72.24 Кб (Скачать)

     Как можно заметить с данными, адрес  которых передается в функцию, можно  работать только с помощью методов  get_user и put_user.

Реализация  политики безопасности

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

      Для предотвращения использования модуля двумя и более пользовательскими  приложениями введем счетчик подключений. Счетчик будет увеличиваться на 1 при вызове метода open и уменьшаться на единицу при вызове метода close. При этом если счетчик больше нуля необходимо запретить подключение и вернуть ошибку.

  1. static int device_open(struct inode *inodestruct file *file)
  2. {
  3.   
  4. if (Device_Open)
  5.  
  6.   return -EBUSY;
  7.  
  8.  
  9. Device_Open++;
  10.   
  11. return SUCCESS;
  12. }
  13.  
  14. static int device_release(struct inode *inodestruct file *file)
  15. {
  16.  
  17. Device_Open--;
  18.   
  19. return SUCCESS;
  20. }

     Для предотвращения выгрузки модуля во время  использования существуют стандартные  механизмы. Все что необходимо сделать это вызвать методы try_get_module во время начала использования модуля и put_module в конце использования. Если произойдет ошибка при вызове этих методов, модуль может быть никогда не выгружен.

  1. static int device_open(struct inode *inodestruct file *file)
  2. {
  3.   
  4. if (Device_Open)
  5.  
  6.   return -EBUSY;
  7.  
  8.  
  9. Device_Open++;
  10.  
  11. try_module_get(THIS_MODULE);
  12.   
  13. return SUCCESS;
  14. }
  15.  
  16. static int device_release(struct inode *inodestruct file *file)
  17. {
  18.  
  19. Device_Open--;
  20.  
  21.  
  22. module_put(THIS_MODULE);
  23.   
  24. return SUCCESS;
  25. }

Организация работы с модулем  ядра

      Не  смотря на то что модуль полностью готов и скомпилирован мы не можем его использовать пока не будет создан файл устройства. Для его создания вызовем в консоли стандартную утилиту mknod. Подробно данный процесс описан в главе «Создание файла устройства».

 

Заключение

      В ходе данной работы был разработан модуль для ядра Linux 2.6.38 и пользовательское приложение для демонстрации возможностей работы модуля ядра. Были изучены основы создания модулей и особенности работы с файлами устройств.

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

 

Библиографический список

  1. Михаэль Кофлер Linux. Полное руководство. – СПб.: Питер, 2011. – 800с.
  2. Роберт Лав Разработка ядра Linux. – М.: Вильямс, 2008. – 448с.
  3. Ори Померанц Ядро Linux. Программирование модулей. – М.: КУДИЦ-Образ, 2002. – 112с.
  4. В. Б. Иванов Прикладное программирование на С/С++. С нуля до мультимедийных и сетевых приложений. – М.: Солон-пресс, 2008. – 240с.
  5. Arnold Robbins Bash Pocket Reference. O'Reilly Media, 2010. – 132с.

  

Приложение

Структура file_operations для ядра Linux 2.6.38

  1. struct file_operations {
  2. struct module *owner;
  3. loff_t (*llseek) (struct file *, loff_tint);
  4. ssize_t (*read) (struct file *char __user *, size_tloff_*);
  5. ssize_t (*write) (struct file *, const char __user *, size_tloff_t *);
  6. ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned longloff_t);
  7. ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned longloff_t);
  8. int (*readdir) (struct file *, void *, filldir_t);
  9. unsigned int (*poll) (struct file *, struct poll_table_struct *);
  10. long (*unlocked_ioctl) (struct file *, unsigned intunsigned long);
  11. long (*compat_ioctl) (struct file *, unsigned intunsigned long);
  12. int (*mmap) (struct file *, struct vm_area_struct *);
  13. int (*open) (struct inode *, struct file *);
  14. int (*flush) (struct file *, fl_owner_t id);
  15. int (*release) (struct inode *struct file *);
  16. int (*fsync) (struct file *, int datasync);
  17. int (*aio_fsync) (struct kiocb *, int datasync);
  18. int (*fasync) (intstruct fil*, int);
  19. int (*lock) (struct file *, intstruct file_lock *);
  20. ssize_t (*sendpage) (struct file *, struct page *, intsize_tloff_t *, int);
  21. unsigned long (*get_unmapped_area)(struct file *, unsigned longunsigned longunsigned longunsigned long);
  22. int (*check_flags)(int);
  23. int (*flock) (struct file *, intstruct file_lock *);
  24. ssize_t (*splice_write)(struct pipe_inode_info *, struct fil*, loff_t *, size_tunsigned int);
  25. ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_tunsigned int);
  26. int (*setlease)(struct file *, longstruct file_lock **);
  27. long (*fallocate)(struct file *fileint modeloff_t offset,loff_t len);
  28. };

 

Код модуля ядра

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>
  4. #include <asm/uaccess.h>
  5.  
  6. #include "chardev.h"
  7. #define SUCCESS 0
  8. #define DEVICE_NAME "char_dev"
  9. #define BUF_LEN 80
  10.  
  11. static int Device_Open 0;
  12. static int current_buffer;
  13. static int init_current_buffer(void);
  14.  
  15. static char buf0[BUF_LEN]buf1[BUF_LEN]buf2[BUF_LEN]buf_temp[BUF_LEN];
  16.  
  17. static char *Message_Ptr;
  18.  
  19. static int device_open(struct inode *inodestruct file *file)
  20. {
  21.  
  22. printk("device_open(%p)\n"file);
  23.  
  24.   
  25. if (Device_Open)
  26.  
  27.   return -EBUSY;
  28.  
  29.  
  30. Device_Open++;
  31.  
  32. Message_Ptr buf0;
  33.  
  34. try_module_get(THIS_MODULE);
  35.   
  36. return SUCCESS;
  37. }
  38.  
  39. static int device_release(struct inode *inodestruct file *file)
  40. {
  41.  
  42. printk("<1>device_release(%p,%p)\n"inodefile);
  43.  
  44.  
  45. Device_Open--;
  46.  
  47.  
  48. module_put(THIS_MODULE);
  49.   
  50. return SUCCESS;
  51. }
  52.  
  53. static ssize_t device_read(struct file *file, char __user buffersize_t lengthloff_t offset)
  54. {
  55.   
  56. int bytes_read 0;
  57.  
  58. printk("<1>device_read(%p,%p,%d)\n"filebufferlength);
  59.  
  60.   
  61. if (*Message_Ptr == 0)
  62.  
  63.   return 0;
  64.  
  65.   
  66. while (length && *Message_Ptr) {
  67.  
  68.  
  69.   put_user(*(Message_Ptr++)buffer++);
  70.  
  71.   length--;
  72.  
  73.   bytes_read++;
  74.   
  75. }
  76.  
  77.   
  78. return bytes_read;
  79. }
  80.  
  81. static ssize_t device_write(struct file *file,
  82.  
  83.           const char __user buffersize_t lengthloff_t offset)
  84. {
  85.   
  86. int i;
  87.  
  88.  
  89. printk("<1>device_write(%p,%s,%d)"filebufferlength);
  90.  
  91.   
  92. switch (current_buffer) {
  93.   
  94. case 0:
  95.  
  96.   for (0length && BUF_LENi++)
  97.  
  98.     get_user(buf0[i]buffer i);
  99.  
  100.   break;
  101.  
  102.   
  103. case 1:
  104.  
  105.   for (0length && BUF_LENi++)
  106.  
  107.     get_user(buf1[i]buffer i);
  108.  
  109.   break;
  110.  
  111.   
  112. case 2:
  113.  
  114.   for (0length && BUF_LENi++)
  115.  
  116.     get_user(buf2[i]buffer i);
  117.  
  118.   break;
  119.   
  120. }
  121.  
  122.  
  123. init_current_buffer();
  124.   
  125. return i;
  126. }
  127.  
  128. int device_ioctl(struct inode *inode,
  129.  
  130.     struct file *file,            
  131.  
  132.     unsigned int ioctl_num,        
  133.  
  134.     unsigned long ioctl_param)
  135. {
  136.  
  137. current_buffer ioctl_num;
  138.  
  139. init_current_buffer();
  140.  
  141.   printk("<1>set buf num %d\n"ioctl_num);
  142.  
  143.   
  144. return SUCCESS;
  145. }
  146.  
  147. static loff_t device_llseek(struct file *fileint loff_t)
  148. {
  149.  
  150. init_current_buffer();
  151.  
  152. Message_Ptr += loff_t;
  153.  
  154. printk("<1>set position %d\n"loff_t);
  155.  
  156.   
  157. return SUCCESS;
  158. }
  159.  
  160. struct file_operations Fops {
  161.  
  162. .read device_read,
  163.  
  164. .write device_write,
  165.  
  166. .unlocked_ioctl device_ioctl,
  167.  
  168. .open device_open,
  169.  
  170. .release device_release,
  171.  
  172. .llseek device_llseek
  173. };
  174.  
  175. int init_module()
  176. {
  177.   
  178. int ret_val;
  179.  
  180.  
  181. ret_val register_chrdev(MAJOR_NUMDEVICE_NAME, &Fops);
  182.  
  183.   
  184. if (ret_val 0) {
  185.  
  186.   printk("%s failed with %d\n",
  187.  
  188.          "Sorry, registering the character device "ret_val);
  189.  
  190.   return ret_val;
  191.   
  192. }
  193.  
  194.  
  195. printk("mknod %s c %d 0\n"DEVICE_FILE_NAMEMAJOR_NUM);
  196.  
  197.   
  198. return 0;
  199. }
  200.  
  201. static int init_current_buffer(){
  202.   
  203. int i;
  204.   
  205. switch (current_buffer) {
  206.   
  207. case 0:
  208.  
  209.   Message_Ptr buf0;
  210.  
  211.   break;
  212.  
  213.   
  214. case 1:
  215.  
  216.   Message_Ptr buf1;
  217.  
  218.   break;
  219.  
  220.   
  221. case 2:
  222.  
  223.   Message_Ptr buf2;
  224.  
  225.   break;
  226.   
  227. }
  228.  
  229. return 0;
  230.  
  231. }
  232.  
  233. void cleanup_module()
  234. {
  235.   
  236. int ret;
  237.  
  238.  
  239. unregister_chrdev(MAJOR_NUMDEVICE_NAME);
  240.  
  241. }

Информация о работе Разработка модуля для ядра Linux 2.6.38