驱动模型

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

//设备结构体 
struct xxx_dev_t{ 
    struct cdev cdev; 
    ...
}xxx_dev;

/*打开*/
int xxx_open(struct inode *inode, struct file *filp)
{
   /******************************************************************************************
   struct inode被内核用来代表一个文件,注意和struct file的 区别,struct inode代表文件,
   struct file代表打开的文件;同一个文件可以被打开好多次,所以可以对应很多struct file,
   但是只对应一个struct inode。
   ******************************************************************************************/
   ...
 
} 

int xxx_release(struct inode *inode, struct file *filp)
{

   //release释放相当于close
   ...


}

/* 读设备*/ 
ssize_t  xxx_read(struct  file  *filp,  char  __user  *buf,  size_t  count, loff_t*f_pos)
 
{ 
    ... 
  
    copy_to_user(buf,  ...,  ...); 
	/*******************************************************************************************************
	1、设备驱动的读写函数中,filp是文件结构体指针,buf是用户空间内存的地址,该地址在内核空间不能直接读写,
	   count是要读写的字节数,f_pos是读写的位置相对于文件       开头的偏移。 
    2、由于内核空间与用户空间的内存不能直接互访,因此借助函数 copy_from_user()完成用户空间到内核空间的复制,函数 copy_to_user()完成内核空间到用户空间的复制。 
    copy_from_user()和copy_to_user()的原型如下所示:
    unsigned  long  copy_from_user(void  *to,  const  void  _ _user  *from,  unsigned long count); 
    unsigned  long  copy_to_user(void  _ _user  *to,  const  void  *from,  unsigned long count);
	**********************************************************************************************************/

    ...
 
}

/* 写设备*/
ssize_t  xxx_write(struct  file  *filp,  const  char  __user  *buf,  size_t count, loff_t *f_pos) 
{ 

	/**************************************************************************************************
	//filp:与字符设备文件关联的file结构指针, 由内核创建。
	//buff : 从设备读取到的数据,需要保存到的位置。由read系统调用提供该参数。
	//count: 请求传输的数据量,由read系统调用提供该参数。
	//offp: 文件的读写位置,由内核从file结构中取出后,传递进来。


	/*buff参数是来源于用户空间的指针,这类指针都不能被内核代码直接引用,
	必须使用专门的函数:
	 int copy_from_user(void *to, const void __user *from, int n)
	 int copy_to_user(void __user *to, const void *from, int n)*/
	************************************************************************************/
   ...  
   copy_from_user(..., buf, ...);    
   ... 
 }
 
/* ioctl函数 */
int  xxx_ioctl(struct  inode  *inode,  struct  file  *filp,  unsigned  int cmd, unsigned long arg)
 
{ 
    ...    
    switch (cmd) 
    {       
         case XXX_CMD1: 
                    ... 
                    break;  
					
         case XXX_CMD2: 
                    ...     
                    break;  
         default:     /* 不能支持的命令 */ 
                    return  - ENOTTY; 
 
    }    
    return 0;   
}


struct file_operations    xxx_fops = {   
    .owner = THIS_MODULE, 
    .open = xxx_open,
    .release = xxx_release,
    .read = xxx_read, 
    .write = xxx_write, 
    .ioctl = xxx_ioctl, 
   
   ...
 
}; 
 
//设备驱动模块加载函数 
static int __init xxx_init(void) 
{ 

	/**********************************************************************
	分配cdev:
	cdev变量的定义可以采用静态和动态两种办法
	静态分配:struct cdev mdev;
	动态分配: struct cdev *pdev = cdev_alloc();
	初始化cdev:
	struct cdev的初始化使用cdev_init函数来完成。
	cdev_init(struct cdev *cdev, const struct file_operations *fops)
	参数:
	cdev: 待初始化的cdev结构
	fops: 设备对应的操作函数集
	注册cdev:
	字符设备的注册使用cdev_add函数来完成。
	cdev_add(struct cdev *p, dev_t dev, unsigned count)
	参数:
	p: 待添加到内核的字符设备结构
	dev: 设备号
	count: 该类设备的设备个数
	***********************************************************************/
    ...  
    cdev_init(&xxx_dev.cdev, &xxx_fops);      //初始化cdev 
    xxx_dev.cdev.owner = THIS_MODULE;    
    if (xxx_major)    //获取字符设备号 

    {
   
        register_chrdev_region(xxx_dev_no, 1, DEV_NAME); 
 
   }
    else 
    { 
 
        alloc_chrdev_region(&xxx_dev_no, 0, 1, DEV_NAME); 
	} 
    ret = cdev_add(&xxx_dev.cdev, xxx_dev_no, 1); //注册设备    ... 
    
} 




 /*设备驱动模块卸载函数*/ 
static void __exit xxx_exit(void) 
{ 
 
    unregister_chrdev_region(xxx_dev_no, 1); //释放占用的设备号 
    cdev_del(&xxx_dev.cdev); //注销设备 
    ... 
 
}


module_init(xxx_init);
module_exit(xxx_exit);

MODULE_AUTHOR("XXXX");
MODULE_LICENSE("GPL");//许可证














  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值