嵌入式内核及驱动开发之学习笔记(二) 实现应用控制驱动
Linux系统根据驱动程序实现的模型框架将设备驱动分成字符设备驱动、块设备驱动、网络设备驱动三大类。这里简单理解一下概念
- 字符设备:设备按字节流处理数据,通常用的串口设备、键盘设备都是这种。
- 块设备:设备按块单位对数据处理,通常是存储设备。
- 网络设备:顾名思义,建立在socket接口上的设备。
字符设备驱动框架
    作为字符设备驱动要素:
         1,必须有一个设备号,用在众多到设备驱动中进行区分
         2,用户必须知道设备驱动对应到设备节点(设备文件)
         3,对设备操作其实就是对文件操作,应用空间操作open,read,write的时候,实际在驱动代码有对应到open, read,write
linux把所有到设备都看成文件,用户对字符设备进行操作实际上就是对驱动进行操作,实际上就是操作对应的设备文件!
而设备号是内核层区别设备的一个标识,我们通过驱动代码程序实现下面 应用程序到设备驱动的控制过程。
应用层程序 --> 设备结点 --> 设备号 --> 设备驱动 --> 硬件
实现一简易的框架。首先是驱动程序的实现
当用户装载完驱动模块,程序会执行 chr_drv_init 这个回调函数,向系统申请一个主设备号(表示程序为哪一类设备服务),创建设备结点(产生/dev/chr2,linux系统能识别这个设备文件);当用户卸载驱动模块后,程序执行 chr_drv_exit 这个回调函数,将之前申请的设备结点和设备号回收。
结构体类型 file_operations 定义了很多对应用层的接口,这些成员变量都是函数指针。我们将这些指针指向自己定义的函数入口。再去实现我们的函数功能。
  
   - 
    
     
    
    
     
      //chr_drv.c
     
    
- 
    
     
    
    
     
      #include <linux/init.h>
     
    
- 
    
     
    
    
     
      #include <linux/module.h>
     
    
- 
    
     
    
    
     
      #include <linux/fs.h>
     
    
- 
    
     
    
    
     
      #include <linux/device.h>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      static unsigned int dev_major = 250;
     
    
- 
    
     
    
    
     
      static struct class *devcls;
     
    
- 
    
     
    
    
     
      static struct device *dev;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      ssize_t chr_drv_read(struct file *filp, char __user *buf, size_t count, loff_t *fpos);
     
    
- 
    
     
    
    
     
      ssize_t chr_drv_write(struct file *filp, const char __user *buf, size_t count, loff_t *fpos);
     
    
- 
    
     
    
    
     
      int chr_drv_open(struct inode *inode, struct file *filp);
     
    
- 
    
     
    
    
     
      int chr_drv_close(struct inode *inode, struct file *filp);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      const struct file_operations my_fops = {
     
    
- 
    
     
    
    
     
      	.open = chr_drv_open,
     
    
- 
    
     
    
    
     
      	.read = chr_drv_read,
     
    
- 
    
     
    
    
     
      	.write = chr_drv_write,
     
    
- 
    
     
    
    
     
      	.release = chr_drv_close,
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      static int __init chr_drv_init(void)
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	printk("-------%s-------------\n", __FUNCTION__);
     
    
- 
    
     
    
    
     	
     
    
- 
    
     
    
    
     	//向系统申请设备号
     
    
- 
    
     
    
    
     	int ret;
     
    
- 
    
     
    
    
     
      	ret = register_chrdev(dev_major, "chr_dev_test", &my_fops);
     
    
- 
    
     
    
    
     	if(ret == 0){
     
    
- 
    
     
    
    
     		printk("register ok\n");
     
    
- 
    
     
    
    
     
      	}else{
     
    
- 
    
     
    
    
     		printk("register failed\n");
     
    
- 
    
     
    
    
     		return -EINVAL;
     
    
- 
    
     
    
    
     
      	}
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	//创建设备结点
     
    
- 
    
     
    
    
     
      	devcls = class_create(THIS_MODULE, "chr_cls");
     
    
- 
    
     
    
    
     
      	dev = device_create(devcls, NULL, MKDEV(dev_major, 0), NULL, "chr2");
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	return 0;
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      static void __exit chr_drv_exit(void)
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     	printk("-------%s-------------\n", __FUNCTION__);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	//销毁这个设备结点
     
    
- 
    
     
    
    
     	device_destroy(devcls,  MKDEV(dev_major, 0));
     
    
- 
    
     
    
    
     	class_destroy(devcls);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
     
    
- 
    
     
    
    
     	//释放这个设备号
     
    
- 
    
     
    
    
     	unregister_chrdev(dev_major, "chr_dev_test");
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      module_init(chr_drv_init);
     
    
- 
    
     
    
    
     
      module_exit(chr_drv_exit);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      MODULE_LICENSE("GPL");
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // read(fd, buf, size);
     
    
- 
    
     
    
    
     
      ssize_t chr_drv_read(struct file *filp, char __user *buf, size_t count, loff_t *fpos)
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     	printk("-------%s-------\n", __FUNCTION__);
     
    
- 
    
     
    
    
     	
     
    
- 
    
     
    
    
     	return 0;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
     
      ssize_t chr_drv_write(struct file *filp, const char __user *buf, size_t count, loff_t *fpos)
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     	printk("-------%s-------\n", __FUNCTION__);
     
    
- 
    
     
    
    
     	
     
    
- 
    
     
    
    
     	return 0;
     
    
- 
    
     
    
    
     	
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
     
      int chr_drv_open(struct inode *inode, struct file *filp)
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     	printk("-------%s-------\n", __FUNCTION__);
     
    
- 
    
     
    
    
     	return 0;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      int chr_drv_close(struct inode *inode, struct file *filp)
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     	printk("-------%s-------\n", __FUNCTION__);
     
    
- 
    
     
    
    
     	return 0;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      }
     
    
 
应用程序用来测试驱动程序的这些接口函数,实现对驱动的控制。
这里open函数定位到驱动程序的chr_drv_open函数,read函数定位到驱动程序的chr_drv_read函数(参考驱动程序中my_fops结构体的初始化)。就像文件IO函数那样使用,只不过我们驱动程序里对应的函数没有具体的实现,能看到一些打印信息。
  
   - 
    
     
    
    
     
      //chr_test.c
     
    
- 
    
     
    
    
     
      #include <stdio.h>
     
    
- 
    
     
    
    
     
      #include <string.h>
     
    
- 
    
     
    
    
     
      #include <stdlib.h>
     
    
- 
    
     
    
    
     
      #include <sys/types.h>
     
    
- 
    
     
    
    
     
      #include <sys/stat.h>
     
    
- 
    
     
    
    
     
      #include <fcntl.h>
     
    
- 
    
     
    
    
     
      #include <unistd.h>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      int main(int argc, char *argv[])
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     	int fd;
     
    
- 
    
     
    
    
     	int value = 0;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	//打开设备结点
     
    
- 
    
     
    
    
     
      	fd = open("/dev/chr2", O_RDWR);
     
    
- 
    
     
    
    
     	if(fd < 0)
     
    
- 
    
     
    
    
     
      	{
     
    
- 
    
     
    
    
     		perror("open");
     
    
- 
    
     
    
    
     		exit(1);
     
    
- 
    
     
    
    
     
      	}
     
    
- 
    
     
    
    
     	//读操作
     
    
- 
    
     
    
    
     	read(fd, &value, 4);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	while(1)
     
    
- 
    
     
    
    
     
      	{
     
    
- 
    
     
    
    
     		//写操作
     
    
- 
    
     
    
    
     
      		value = 0;
     
    
- 
    
     
    
    
     		write(fd, &value, 4);
     
    
- 
    
     
    
    
     		sleep(1);
     
    
- 
    
     
    
    
     		
     
    
- 
    
     
    
    
     		//写操作
     
    
- 
    
     
    
    
     
      		value = 1;
     
    
- 
    
     
    
    
     		write(fd, &value, 4);
     
    
- 
    
     
    
    
     		sleep(1);
     
    
- 
    
     
    
    
     		
     
    
- 
    
     
    
    
     
      	}
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	close(fd);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	return 0;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      }
     
    
 
Makefile文件负责整个工程的编译与管理
相比于之前,要多编译了chr_test.c这个文件,APP_NAME 指定目标文件名,CROSS_COMPILE 指定交叉编译工具链。下面还要修改添加一下编译规则
  
   - 
    
     
    
    
     
      ROOTFS_DIR = /nfs/rootfs
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      APP_NAME = chr_test
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      CROSS_COMPILE = /home/linux/soft/gcc-4.6.4/bin/arm-none-linux-gnueabi-
     
    
- 
    
     
    
    
     
      CC = $(CROSS_COMPILE)gcc
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      ifeq ($(KERNELRELEASE), )
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      KERNEL_DIR = /mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412
     
    
- 
    
     
    
    
     
      CUR_DIR = $(shell pwd)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      all :
     
    
- 
    
     
    
    
     
      	make -C  $(KERNEL_DIR) M=$(CUR_DIR) modules
     
    
- 
    
     
    
    
     
      	$(CC) $(APP_NAME).c  -o $(APP_NAME)
     
    
- 
    
     
    
    
     	
     
    
- 
    
     
    
    
     
      clean :
     
    
- 
    
     
    
    
     
      	make -C  $(KERNEL_DIR) M=$(CUR_DIR) clean
     
    
- 
    
     
    
    
     	
     
    
- 
    
     
    
    
     
      install:
     
    
- 
    
     
    
    
     
      	cp -raf *.ko $(APP_NAME)  $(ROOTFS_DIR)/drv_module
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      else
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      obj-m += chr_drv.o
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      endif
     
    
- 
    
     
    
    
      
     
    
 
查看实验结果
编译并移动文件到nfs根目录
  
   - 
    
     
    
    
     
      root@linux:/mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412/drivers/mydrivers/chr_drv# make
     
    
- 
    
     
    
    
     
      root@linux:/mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412/drivers/mydrivers/chr_drv# make install
     
    
 
开发板加载模块,执行应用程序
[root@farsight drv_module]# ls
 chr_drv.ko   chr_test     chr_test.ko  hello.ko     math.ko
 [root@farsight drv_module]# insmod chr_drv.ko
 [ 3036.170000] -------chr_drv_init-------------
 [ 3036.175000] register ok
 [root@farsight drv_module]# ./chr_test
 [ 3041.255000] -------chr_drv_open-------
 [ 3041.255000] -------chr_drv_read-------
 [ 3041.260000] -------chr_drv_write-------
 [ 3042.265000] -------chr_drv_write-------
 [ 3043.265000] -------chr_drv_write-------
  
文章来源: blog.csdn.net,作者:hinzer,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/feit2417/article/details/84035899
- 点赞
- 收藏
- 关注作者
 
             
           
评论(0)