字符设备学习总结

字符设备驱动框架

1、测试函数

1)open(),打开字符设备;

2)ioctl(),操作字符设备;

3)close(),关闭字符设备;

2、字符设备函数

1)smartchip _init(),模块加载;(insmod smartChip.ko)

A、register_chrdev_region(),申请设备号;

B、alloc_chrdev_region(),申请设备号;

C、smartchip_setup_cdev();

a、cdev_init(),初始化cdev的成员;

b、cdev_add(),注册字符设备;

2)smartchip_open(),打开设备;

3)smartchip_ioctl(),模块操作;

A、get_user(),用户空间到内核空间;

B、put_user(),内核空间到用户空间;

4)smartchip_release(),关闭设备;

5)smartchip_cleanup(),模块卸载;(rmmod smartChip.ko)

A、cdev_del(),注销字符设备;

B、unregister_chrdev_region(),释放设备号;

3、 I2C设备访问

1)smartchip_i2c_read();

A、get_fs();

B、set_fs();

C、sys_open(),打开I2C设备;

D、sys_ioctl(),操作I2C设备;

E、sys_read(),读I2C设备;

F、sys_close(),关闭I2C设备;

2)smartchip_i2c_write();

A、get_fs();

B、set_fs();

C、sys_open(),打开I2C设备;

D、sys_ioctl(),操作I2C设备;

E、sys_write(),写I2C设备;

F、sys_close(),关闭I2C设备;

 

细节:

1、cdev 结构体描述一个字符设备;

2、MKDEV(intmajor, int minor),通过主设备号和次设备号生成dev_t;

MAJOR(dev_t dev),从dev_t获得主设备号;

MINOR(dev_t dev),从dev_t获得从设备号;

3、cdev_init()函数用于初始化cdev的成员,并建立cdev和file_operations之间的连接;

cdev_add()函数向系统添加一个cdev,完成字符设备的注册;

cdev_del()函数向系统删除一个cdev,完成字符设备的注销;

register_chrdev_region()或alloc_chrdev_region()函数向系统申请设备号,前者已知起始设备的设备号,后者设备号未知,向系统动态申请未被占用的设备号;

unregister_chrdev_region()函数用于释放原先申请的设备号;

4、file_operations 结构体中的成员函数是字符设备驱动程序的主体内容,是字符设备驱动与内核的接口,是用户空间对Linux进行系统调用最终的落实者;

5、当用户空间调用Linux API函数open()打开设备文件时,设备驱动的open()函数最终被调用。驱动程序可以不实现这个函数,在这种情况下,设备的打开操作永远成功;

6、filp是文件结构体指针;

7、私有数据private_data,在open()函数中将文件的私有数据private_data指向设备结构体,然后在ioctl()函数中通过private_data访问设备结构体;

8、open()函数中的container_of()的作用是通过结构体成员的指针找到对应结构体的指针,第一个参数为结构体成员的指针,第二个参数为整个结构体的类型,第三个参数为传入的第一个参数的结构体成员的类型,container_of()返回值为整个结构体的指针;

9、内核空间与用户空间访问函数:

A、copy_from_user()完成用户空间到内核空间的拷贝,copy_to_user()完成内核空间到用户空间的拷贝,这两个函数均返回不能被复制的字节数,如果复制成功,返回值为0;

B、如果要复制的内存是简单类型,如char、int、long等,则可以使用简单的put_user()和get_user(),get_user(val,(int *) arg),用户空间到内核空间,arg是用户空间的地址;

10、I/O控制函数的cmd参数是事先定义的I/O控制命令,arg是对应于该命令的参数;

 

 

三个重要数据结构

1、file_operations结构

2、file结构:

A.file结构与用户空间程序中的FILE没有任何关联,前者是一个内核结构,不会出现在用户程序中,后者在C库中定义且不会出现在内核代码中。

B.file结构代表一个打开的文件,由内核在open时创建,并传递给该文件上进行操作的所有函数,直到最后的close函数。在文件的所有实例都被关闭之后,内核会释放这个数据结构

3、inode结构:

内核用inode结构在内部表示文件,因此它和file结构不同,后者表示打开的文件描述符。对单个文件,可能会有许多个表示文件打开的文件描述符的file结构,但它们都指向单个inode结构。

 

 

open函数

int(*open) (struct inode *inode, struct file *filp);

其中的inode参数在其i_cdev字段中包含了我们所需要的信息,即我们先前设置的cdev结构。唯一的问题是,我们通常不需要cdev结构本身,而是希望得到包含cdev结构的smartchip_dev结构。

container_of(pointer, container_type, container_field);

这个宏需要一个container_field字段的指针,即pointer,该字段包含在container_type类型的结构中,然后返回包含该字段的结构指针。

 

疑惑:

使用class_create()的目的是什么?

创建一个类,在/dev/目录下建立设备节点,然后通过device_create()创建设备节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值