linux字符设备及其驱动编写简介

1字符设备及其驱动

1.1字符设备简介

字符设备是一种按串行顺序来访问的设备,如触摸屏,磁带驱动器,鼠标等。


1.2字符设备驱动

字符设备驱动负责驱动字符设备,通常实现由openreadwritecloseioctl等函数。

1.3设备号

设备号分为主次设备号,主设备号标示设备与哪个驱动相连,次设备号标示同一个驱动下的具体设备。


1.4字符驱动编写相关结构

1file结构体

File结构体代表一个打开的文件(设备也对应一个文件),在系统中,每打开一个文件都在内核存在一个对应的file结构体。

它在一个文件打开时有内核创建,关闭时由内核释放。在期间传递在文件上进行操作的函数。

Structfile的指针通常命名为filp

structfile {

union{

structlist_head fu_list;

structrcu_head fu_rcuhead;

}f_u;

structpath f_path;

conststruct file_operations *f_op; /*和文件关联的操作*/

spinlock_t f_lock;

atomic_long_t f_count;

unsignedint f_flags; /*文件标志,:O_RDONLY,O_NONBLOCK*/

fmode_tf_mode; /*文件读/写模块,FMODE_READFMODE_WRITE*/

loff_t f_pos; /*当前读写位置*/

structfown_struct f_owner;

conststruct cred *f_cred;

structfile_ra_state f_ra;

u64 f_version;

void *private_data; /*文件私有数据指针*/


2inode结构

VFSinode包含文件访问权限,属主,组,大小,生成时间,访问时间,最后修改时间等信息。它是Linux管理文件系统的最基本单位,也是文件系统连接任何子目录,文件的桥梁

struct  inode {

…..

umode_ti_mode; /*inode的权限*/

uid_ti_uid; /*inode拥有都的id*/

gid_ti_gid; /*inode所属的群组id*/

dev_ti_rdev; /*若是设备文件,些字段将记录设备的设备号*/

……

}


3cdev结构体

cdev结构体用于描述字符设备,可以理解为cdev就是设备。

structcdev {

struct kobjectkobj; /*内嵌的kobject对象*/

struct module*owner; /*所属模块*/

const structfile_operations *ops; /*文件操作结构体-字符设备驱动的核心*/

。。。。。

dev_tdev; /*设备号*/

unsigned intcount;

};

dev_t:其实质为unsignedint 32位整数,其中高12位为主设备号,低20

位为次设备号。使用下列宏可以从dev_t获得主设备号和次设备号:

MAJOR(dev_tdev);

MINOR(dev_tdev);

使用下列宏可以通过主设备号和次设备号生成dev_t

MKDEV(intmajor,int minor);



4kobject结构体

5file_operations结构体

file_operations结构体专门用来绑定操作函数,如readwriteioctl等函数,

file_operations结构体中的成员函数是字符设备驱动程序设计的主体内容,这些函数实际会在应用程序进行linuxopen(),write(),read(),close()等系统调用时最终被调用,file_operations结构体目前已经比较庞大。

2字符驱动的编写

2.1字符驱动编写的要义

加载函数

卸载函数

实现file_operations成员函数

其关系图如下:

关系图如下


    1. 代码编写

  1. 加载模板

structxxx_dev_t//设备结构体

{

structcdev cdev;

...

}xxx_dev;

staticint __init xxx_init(void) /*设备驱动模块加载函数*/

{ ...

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); //注册设备

...

}

  1. 卸载模板

staticvoid __exit xxx_exit(void) /*设备驱动模块卸载函数*/

{

unregister_chrdev_region(xxx_dev_no,1);//释放占用的设备号

cdev_del(&xxx_dev.cdev);//注销设备

}

  1. file_operation成员函数实现模板

// file_operations结构体设置,该设备的所有对外接口在这里明确,此处只写出了几个常用的
staticstruct file_operations xxx_fops =
{
    .owner= THIS_MODULE,
    .open  = xxx_open,      //
打开设备
   .release =xxx_release, //
关闭设备
   .read  = xxx_read,      //
实现设备读功能
   .write = xxx_write,     //
实现设备写功能
   .ioctl = xxx_ioctl,     //
实现设备控制功能
};


字符设备驱动程序设计的主体工作是:

初始化、添加和删除cdev结构体,申请和释放设备号,以及填充file_operations结构体中的操作函数,实现file_operations结构体中的read(),write(),ioctl()等函数。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值