转载:一个简单的linux驱动示例

        本文参考百度文库“linux驱动开发入门”点击打开链接和转载博文:点击打开链接

一、基本知识        

        Linux设备驱动分为:字符设备、块设备和网络设备。原理图如下:




二、示例

示例主要转载自博客园的博客,见上。只是我采用的的Linux内核版本比那篇博文的新,有小许改动,粘贴代码如下:

内核版本:

ry@ubuntu:/$ uname -a
Linux ubuntu 3.16.0-30-generic #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

文件:hello_mod.c

  1. /* 
  2.  * ===================================================================================== 
  3.  * 
  4.  *       Filename:  hello.c 
  5.  * 
  6.  *    Description:  hello_mod 
  7.  * 
  8.  *        Version:  1.0 
  9.  *        Created:  01/28/2011 05:07:55 PM 
  10.  *       Revision:  none 
  11.  *       Compiler:  gcc 
  12.  * 
  13.  *         Author:  Tishion (shion), [email protected] 
  14.  *        Company:  LIM 
  15.  * 
  16.  * ===================================================================================== 
  17.  */  
  18.   
  19. #include <linux/module.h>  
  20. #include <linux/init.h>  
  21. #include <linux/kernel.h>  
  22. #include <linux/fs.h>  
  23. #include <linux/uaccess.h>  
  24. #include <linux/semaphore.h>  
  25. #include <linux/cdev.h>  
  26. #include <linux/device.h>  
  27. #include <linux/ioctl.h>  
  28. #include <linux/slab.h>  
  29. #include <linux/errno.h>  
  30. #include <linux/string.h>  
  31. #include “hello_mod_ioctl.h”  
  32.   
  33. #define MAJOR_NUM 250  
  34. #define MINOR_NUM 0  
  35. #define IN_BUF_LEN 256  
  36. #define OUT_BUF_LEN 512  
  37.   
  38. MODULE_AUTHOR(”Tishion”);  
  39. MODULE_DESCRIPTION(”Hello_mod driver by tishion”);  
  40.   
  41. static struct class * hello_class;  
  42. static struct cdev hello_cdev;  
  43. static dev_t devnum = 0;  
  44. static char * modname = “hello_mod”;  
  45. static char * devicename = “hello”;  
  46. static char * classname = “hello_class”;  
  47.   
  48. static int open_count = 0;  
  49. static struct semaphore sem;  
  50. static DEFINE_SPINLOCK(spin);  
  51. static char * inbuffer = NULL;  
  52. static char * outbuffer = NULL;  
  53. static lang_t langtype;  
  54.   
  55. static int hello_mod_open(struct inode *, struct file *);  
  56. static int hello_mod_release(struct inode *, struct file *);  
  57. static ssize_t hello_mod_read(struct file *, char *, size_t, loff_t *);  
  58. static ssize_t hello_mod_write(struct file *, const char *, size_t, loff_t *);  
  59. static long hello_mod_ioctl(struct file *, unsigned int, unsigned long);  
  60.   
  61. struct file_operations hello_mod_fops =   
  62. {  
  63.     .owner = THIS_MODULE,  
  64.     .open = hello_mod_open,  
  65.     .read = hello_mod_read,  
  66.     .write = hello_mod_write,  
  67.     .unlocked_ioctl = hello_mod_ioctl,  
  68.     .release = hello_mod_release,  
  69. };  
  70.   
  71. static int hello_mod_open(struct inode *inode, struct file *pfile)  
  72. {  
  73.     printk(”+hello_mod_open()!/n”);  
  74.     spin_lock(&spin);  
  75.     if(open_count)  
  76.     {  
  77.         spin_unlock(&spin);  
  78.         return -EBUSY;  
  79.     }  
  80.     open_count++;  
  81.     spin_unlock(&spin);  
  82.     printk(”-hello_mod_open()!/n”);  
  83.     return 0;  
  84. }  
  85. static int hello_mod_release(struct inode *inode, struct file *pfile)  
  86. {  
  87.     printk(”+hello_mod_release()!/n”);  
  88.     open_count–;  
  89.     printk(”-hello_mod_release()!/n”);  
  90.     return 0;  
  91. }  
  92. static ssize_t hello_mod_read(struct file *pfile, char *user_buf, size_t len, loff_t *off)  
  93. {  
  94.     printk(”+hello_mod_read()!/n”);  
  95.   
  96.     if(down_interruptible(&sem))  
  97.     {  
  98.         return -ERESTARTSYS;   
  99.     }  
  100.     memset(outbuffer, 0, OUT_BUF_LEN);  
  101.     printk(”    +switch()/n”);  
  102.     switch(langtype)  
  103.     {  
  104.         case english:  
  105.             printk(”        >in case: english/n”);  
  106.             sprintf(outbuffer, ”Hello! %s.”, inbuffer);  
  107.             break;  
  108.         case chinese:  
  109.             printk(”        >in case: chinese/n”);  
  110.             sprintf(outbuffer, ”你好! %s.”, inbuffer);  
  111.             break;  
  112.         case pinyin:  
  113.             printk(”        >in case: pinyin/n”);  
  114.             sprintf(outbuffer, ”ni hao! %s.”, inbuffer);  
  115.             break;  
  116.         default:  
  117.             printk(”        >in case: default/n”);  
  118.             break;  
  119.     }  
  120.     printk(”    -switch()/n”);  
  121.     if(copy_to_user(user_buf, outbuffer, len))  
  122.     {  
  123.         up(&sem);  
  124.         return -EFAULT;  
  125.     }  
  126.     up(&sem);  
  127.     printk(”-hello_mod_read()!/n”);  
  128.     return 0;  
  129. }  
  130. static ssize_t hello_mod_write(struct file *pfile, const char *user_buf, size_t len, loff_t *off)  
  131. {  
  132.     printk(”+hello_mod_write()!/n”);  
  133.     if(down_interruptible(&sem))  
  134.     {  
  135.         return -ERESTARTSYS;  
  136.     }  
  137.     if(len > IN_BUF_LEN)  
  138.     {  
  139.         printk(”Out of input buffer/n”);  
  140.         return -ERESTARTSYS;  
  141.     }  
  142.     if(copy_from_user(inbuffer, user_buf, len))  
  143.     {  
  144.         up(&sem);  
  145.         return -EFAULT;  
  146.     }  
  147.     up(&sem);      
  148.     printk(”-hello_mod_write()!/n”);  
  149.     return 0;  
  150. }  
  151. static long hello_mod_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)  
  152. {  
  153.     int err = 0;  
  154.     printk(”+hello_mod_ioctl()!/n”);  
  155.     printk(”    +switch()/n”);  
  156.     switch(cmd)  
  157.     {  
  158.         case HELLO_IOCTL_RESETLANG:  
  159.             printk(”        >in case: HELLO_IOCTL_RESETLANG/n”);  
  160.             langtype = english;  
  161.             break;  
  162.         case HELLO_IOCTL_GETLANG:  
  163.             printk(”        >in case: HELLO_IOCTL_GETLANG/n”);  
  164.             err = copy_to_user((int *)arg, &langtype, sizeof(int));  
  165.             break;  
  166.         case HELLO_IOCTL_SETLANG:  
  167.             printk(”        >in case: HELLO_IOCTL_SETLANG/n”);  
  168.             err = copy_from_user(&langtype,(int *)arg, sizeof(int));  
  169.             break;  
  170.         default:  
  171.             printk(”        >in case: default/n”);  
  172.             err = ENOTSUPP;  
  173.             break;  
  174.     }  
  175.     printk(”    -switch()/n”);  
  176.     printk(”-hello_mod_ioctl()!/n”);  
  177.     return err;  
  178. }  
  179. static int __init hello_mod_init(void)  
  180. {  
  181.     int result;  
  182.     printk(”+hello_mod_init()!/n”);  
  183.     devnum = MKDEV(MAJOR_NUM, MINOR_NUM);  
  184.     result = register_chrdev_region(devnum, 1, modname);  
  185.   
  186.     if(result < 0)  
  187.     {  
  188.         printk(”hello_mod : can’t get major number!/n”);  
  189.         return result;  
  190.     }      
  191.   
  192.     cdev_init(&hello_cdev, &hello_mod_fops);  
  193.     hello_cdev.owner = THIS_MODULE;  
  194.     hello_cdev.ops = &hello_mod_fops;  
  195.     result = cdev_add(&hello_cdev, devnum, 1);  
  196.     if(result)  
  197.         printk(”Failed at cdev_add()”);  
  198.     hello_class = class_create(THIS_MODULE, classname);  
  199.     if(IS_ERR(hello_class))  
  200.     {  
  201.         printk(”Failed at class_create().Please exec [mknod] before operate the device/n”);  
  202.     }  
  203.     else  
  204.     {  
  205.         device_create(hello_class, NULL, devnum,NULL, devicename);  
  206.     }  
  207.   
  208.     open_count = 0;  
  209.     langtype = english;  
  210.     inbuffer = (char *)kmalloc(IN_BUF_LEN, GFP_KERNEL);  
  211.     outbuffer = (char *)kmalloc(OUT_BUF_LEN, GFP_KERNEL);  
  212.     sema_init(&sem, 1);  
  213.     printk(”-hello_mod_init()!/n”);  
  214.     return 0;  
  215. }  
  216.   
  217. static void __exit hello_mod_exit(void)  
  218. {  
  219.     printk(”+hello_mod_exit!/n”);  
  220.     kfree(inbuffer);  
  221.     kfree(outbuffer);  
  222.     cdev_del(&hello_cdev);  
  223.     device_destroy(hello_class, devnum);  
  224.     class_destroy(hello_class);  
  225.     unregister_chrdev_region(devnum, 1);  
  226.     printk(”-hello_mod_exit!/n”);  
  227.     return ;  
  228. }  
  229.   
  230. module_init(hello_mod_init);  
  231. module_exit(hello_mod_exit);  
  232. MODULE_LICENSE(”GPL”);  
/*
 * =====================================================================================
 *
 *       Filename:  hello.c
 *
 *    Description:  hello_mod
 *
 *        Version:  1.0
 *        Created:  01/28/2011 05:07:55 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Tishion (shion), [email protected]
 *        Company:  LIM
 *
 * =====================================================================================
 */





猜你喜欢

转载自blog.csdn.net/congqianwozhidao/article/details/80298748