实现一个简单的Linux字符设备驱动


步骤1:  编写驱动程序

  1. #include <linux/module.h>   
  2. #include <linux/init.h>   
  3. #include <linux/kernel.h>   
  4. #include <linux/cdev.h>   
  5. #include <linux/fs.h>   
  6. #include <linux/kdev_t.h>   
  7. #include <asm/uaccess.h>   
  8. #include <linux/device.h>   
  9. #define DEVICE_NAME "cdev_zhangwei"   
  10. int number_of_devices = 1;    
  11. struct cdev mydev;  
  12. dev_t dev = 0;  
  13. char data[128] = "/0"// the data of my device   
  14. struct class *myclass;  
  15. static int mydev_open(struct inode *inode, struct file *file)  
  16. {  
  17.     pr_info("mydev driver open!/n");  
  18.     return 0;  
  19. }  
  20. static int mydev_release(struct inode *inode, struct file *file)  
  21. {  
  22.     pr_info("mydev driver released!/n");  
  23.     return 0;  
  24. }  
  25. ssize_t mydev_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)  
  26. {  
  27.     ssize_t ret = 0;  
  28.     pr_info("mydev_write!/n");  
  29.     pr_info("writing %d bytes/n", count);  
  30.     if (count > 127)   
  31.         return -ENOMEM;  
  32.     if (count < 0)   
  33.         return -EINVAL;  
  34.     if (copy_from_user(data, buf, count)) {  
  35.         ret = -EFAULT;  
  36.     }  
  37.     else {  
  38.         data[127] = ''/0'';  
  39.         pr_info("kernel received: %s/n", data);  
  40.         ret = count;  
  41.     }  
  42.     return ret;  
  43. }  
  44. static ssize_t mydev_read(struct file* filp, char* buf, size_t len,loff_t* off)  
  45. {  
  46.     if( copy_to_user(buf,data,len) )  
  47.     {  
  48.         return -EFAULT;  
  49.     }  
  50.       
  51.     return len;  
  52. }  
  53. struct file_operations mydev_fops = {   
  54.     .owner = THIS_MODULE,  
  55.     .open = mydev_open,  
  56.     .read = mydev_read,  
  57.     .write = mydev_write,  
  58.     .release = mydev_release  
  59.       
  60. };  
  61. static int __init mydev_init(void)  
  62. {  
  63.     int result, error;  
  64.     result = register_chrdev(0, DEVICE_NAME, &mydev_fops);  
  65.         pr_info("udev_cdev: get major number: %d/n", result);  
  66.     dev = MKDEV(result, 0);  
  67.     myclass = class_create(THIS_MODULE, "mydev_class");  
  68.     device_create(myclass, NULL, dev, NULL, DEVICE_NAME);  
  69.     return 0;  
  70. }  
  71. static void __exit mydev_exit(void)  
  72. {  
  73.     cdev_del(&mydev);  
  74.     unregister_chrdev_region(dev, number_of_devices);  
  75.     device_destroy(myclass, dev);  
  76.     class_destroy(myclass);  
  77.     pr_info("Goodbye cdev!/n");  
  78. }  
  79. module_init(mydev_init);  
  80. module_exit(mydev_exit);  
  81. MODULE_LICENSE("GPL");  
  82. MODULE_DESCRIPTION("Simple cdev udev driver test");  

步骤2: 编译,形成ko文件,然后利用insmod命令插入内核。  (最好利用makefile进行编译,网上有文章专门有介绍)

步骤3:创建设备节点: mknod /dev/your_name  c  主设备号  次设备号

次设备号这里填0, 主设备号可以利用 cat /proc/devices 查看 

步骤4:编写用户程序(测试咱们的驱动是否可行), 如以下代码,这个嘛,简单的用gcc命令编译就好了

  1. #include <stdio.h>  
  2. #include <sys/types.h>  
  3. #include <unistd.h>  
  4. #include <stdlib.h>  
  5. #include <fcntl.h>   
  6. int main (void)   
  7. {  
  8.     int fd,len;   
  9.     pid_t pid;  
  10.     char buff[] = "This is from userspace zhangwei fight it!";  
  11.     char buff_read[100] ;  
  12.     fd = open ("/dev/cdev_zhangwei", O_RDWR);  
  13.     if (fd < 0) {  
  14.         perror("open failed");  
  15.         exit(0);  
  16.     }  
  17.     pid = fork();  
  18.     if(pid>0)  
  19.     {  
  20.         len =  write (fd, buff, sizeof(buff));    
  21.         printf ("son Write returns %d/n",len );  
  22.     }  
  23.     else // parent   
  24.     {  
  25.         //waitpid(pid);   
  26.         printf ("read returns %d/n", read(fd,buff_read,len) );  
  27.         printf("buff_read = %s/n",buff_read);  
  28.     }  
  29.     close (fd);  
  30.     return 0;  
  31. }  

到了这里,对字符设备驱动就有一个直观的印象了。

相关内容