51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 2810|回复: 1

Linux 字符设备驱动开发--内存读写操作

[复制链接]

该用户从未签到

发表于 2018-3-1 13:58:13 | 显示全部楼层 |阅读模式
学习Linux的累计时间已经有两年多了,工作关系,学习的过程总是断断续续的,现在整理一下,
下面要分享的是一个简单的linux驱动程序,将内存当作一个虚拟的设备去读写,没有什么实际的
用处,像hello wold!程序一样,我们简单体会一下linux驱动程序的特点,Linux设备驱动程序开
发第三版是一本不错的参考书,讲的比较详细,值得入手,话不多说了,简单讲一下步骤:

1、我电脑上的Linux系统是Ubuntu14.04。

2、 新建一个duxie.c文件作为驱动程序源文件,一个ce.c作为应用层的测试程序,一个Makefile文
件用来编译驱动程序产生*.ko文件。

3、下面贴出代码:

  1. /**************************************************************
  2.     duxie.c  
  3.     It can be compiled for x86 PC #include <linux/module.h>
  4. #include <linux/init.h>
  5. #include <linux/kernel.h> /* printk() */
  6.     author:
  7.     date:   
  8. ***************************************************************/
  9.   
  10. #include <linux/module.h>
  11. #include <linux/init.h>
  12. #include <linux/kernel.h>   /* printk() */
  13.   
  14. #include <linux/errno.h>    /* error codes */
  15. #include <linux/poll.h>    /* COPY_TO_USER */
  16.   

  17. #define DEVICE_NAME    "rwd"

  18. static int rwdMajor = 0;
  19. static int MAX_BUF_LEN=1024;
  20. static char drv_buf[1024];
  21. static int WRI_LENGTH=0;

  22.   
  23.   
  24. /*************************************************************************************/
  25. static ssize_t  dx_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
  26. {  
  27.     if(count > MAX_BUF_LEN)count = MAX_BUF_LEN;
  28.     copy_from_user(drv_buf , buffer, count);
  29.     WRI_LENGTH = count;
  30.     printk("user write data to driver\n");
  31.     return count;
  32. }
  33. /*************************************************************************************/
  34. static ssize_t  dx_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
  35. {
  36.     if(count > MAX_BUF_LEN)
  37.         count=MAX_BUF_LEN;
  38.     copy_to_user(buffer, drv_buf,count);
  39.     printk("user read data from driver\n");
  40.     return count;
  41. }
  42.   
  43. static int dx_open(struct inode *inode, struct file *filp)
  44. {
  45.     printk("device open sucess!\n");
  46.     return 0;
  47. }
  48. /*************************************************************************************/
  49. static int  dx_release(struct inode *inode, struct file *filp)
  50. {
  51.     printk("device release\n");
  52.     return 0;
  53. }

  54. /*************************************************************************************/
  55. static struct file_operations pxa270_fops = {
  56.     owner:    THIS_MODULE,
  57.     write:    dx_write,     
  58.     read:    dx_read,     
  59.     open:    dx_open,
  60.     release:dx_release,
  61. };
  62. /*************************************************************************************/

  63. static int __init dx_init(void)
  64. {
  65. int ret;
  66.         ret = register_chrdev(0, DEVICE_NAME, &pxa270_fops);
  67.     if (ret < 0) {
  68.         printk(DEVICE_NAME " can't get major number\n");
  69.         return ret;
  70.     }
  71.     rwdMajor=ret;

  72.     printk("dx module major number is %d\n", ret);
  73.     return 0;
  74. }

  75. /*************************************************************************************/
  76.   
  77. void __exit  dx_exit(void)
  78. {
  79.   unregister_chrdev(rwdMajor, DEVICE_NAME);
  80. }
  81. module_exit(dx_exit);
  82. module_init(dx_init);
  83. MODULE_LICENSE("GPL");



  84. Makefile的源代码如下:

  85. [html] view plain copy
  86. ifneq ($(KERNELRELEASE),)  
  87. obj-m := duxie.o  
  88. else  
  89. KDIR := /usr/src/linux-headers-3.19.0-31-generic  
  90. all:  
  91.     make -C $(KDIR) M=$(PWD) modules     
  92. clean:  
  93.     rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*  
  94. endif  
  95. 应用层的测试程序ce.c源代码如下:


  96. #include <stdio.h>
  97. #include <stdlib.h>
  98. #include <fcntl.h>
  99. #include <unistd.h>
  100. #include <sys/ioctl.h>
  101. #include<string.h>


  102. void showbuf(char *buf);
  103. int MAX_LEN=32;

  104. int main()
  105. {
  106.     int fd;
  107.     int i;
  108.     char buf1[255];
  109.     char buf2[255];
  110.    
  111.     printf("please input a string:\n");
  112.     scanf("%s",buf1);
  113.         MAX_LEN=strlen(buf1);

  114.     fd=open("/dev/rwd",O_RDWR);
  115.     if(fd < 0){
  116.         printf("####rwd  device open fail####\n");
  117.         return (-1);
  118.     }
  119.     printf("write %d bytes data to /dev/rwd \n",MAX_LEN);
  120.     printf("%s\n",buf1);

  121.     write(fd,buf1,MAX_LEN);

  122.     printf("Read %d bytes data from /dev/rwd \n",MAX_LEN);
  123.     read(fd,buf2,MAX_LEN);
  124.     printf("%s\n",buf2);
  125.    
  126.     close(fd);
  127.     return 0;

  128. }
复制代码
具体实现的功能可以自己看一下。

4、 编译生成duxie.ko文件,用insmod duxie.ko加载驱动程序。

5、查看主设备号,可以用cat /proc/devices | grep rwd 查看主设备号。

6、该驱动程序需要手动注册,可以用mknod /dev/rwd 设备类型 主设备号 次设备号 (例如
mknod /dev/rwd c 248 0)来实现。

7,编译运行ce.c,输入一串字符串,输入什么就输出什么,这样就完成了整个驱动程序的编写、
编译、安装及测试工作。

回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-4-16 19:27 , Processed in 0.067792 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表