如有什么错误大家要告诉我,一起学习:
#########################################
# 在内核函数中,尽量不要定义太大的局部变量
# 内核为每个进程在内核中分配一个 2页的内核栈(咱们这就是8K)
# 如果变量太大,会把栈的东西填满,栈里面放着进程很重要的东西, struct task_info 在这里面包含 struct task_struct
# 可以使用 malloc,分配的内粗是在堆里,不影响栈的
###########################################
1、设备类型:
字符设备:能够按照字节流有序的访问的设备
不能 seek,能seek就不是有序的访问了
块设备:只能按照规定的块大小取访问的设备
网络设备:通过网络协议栈访问的设备;
网络设备不对应文件,在 /dev 下不对应节点
选择:
大多数是字符设备;SD卡、硬盘、nand 等是块设备;网卡是网络设备
设备驱动:
向下操作硬件,向上给user提供接口
2、字符设备:led设备、wdt设备(消费电子中看门狗驱动一般用不到,工控领域中一般会用到[打开,关闭,定时])、pwm(timer)设备,在 /dev 下挂载文件,打开关闭操作文件进行相应的操作
/dev/led
open /dev/led
write 123 ---> /dev/led on 点灯
write 456 ---> /dev/led off 关灯
字符设备的核心头文件 < linux/cdev.h >
设备号:
每一个设备都会有一个设备号,是唯一的
主设备号:表示一类设备
次设备号:表示一类设备中的某个设备
主设备号找驱动,次设备号找设备
用户态创建设备节点:
mknod led c 10 20
mknod led1 c 10 20
mknod led2 c 10 20
每一个字符设备都会对应一个结构体 struct cdev,向添加就必须自己添加这么一个结构体
此结构体对应一个或多个结构体:
struct cdev {
struct kobject kobj; //设备模型核心,与C++里的基类相似,用于组织设备;内核操作,
struct module *owner; //一般不用初始化,初始化写成 THIS_MODULE 就行
const struct file_operations *ops;
//该设备的操作集 open release write read ioctl(万能的io操作,看怎么配置)
硬件相关的操作都在此操作集中
struct list_head list;
dev_t dev; //该设备的设备号,主设备号、次设备号都在这一个变量里
主次设备号在哪一位不需记,更改内核版本可能会变
获得主设备号:MAJOR(dev)
获得次设备号:MINOR(dev)
unsigned int count; //对应的设备节点个数;可多个设备节点对应一个结构体
第一个设备号是 10 20, count 是节点是,第二个设备号是 10 21, 根据count的个数一次加;主设备号不变
};
创建一个设备号 MKDEV(major, minor) 参数自己填,到此处不能保证设备号不重复
保证不重复的方法:(上面申请完了要告诉内核,使用下面的方法)
存放全部设备的设备号 cat /proc/device, 可查阅哪个设备号没用
自己规定设备号:(需要先查看哪个设备号不用,否则会出错)
register_chrdev_region() 注册设备号
unregister_chrdev_region() 注销设备号
内核给分配设备:(内核动态分配,就不需要MKDEV申请了)
alloc_chrdev_region() 分配一个设备号
unregister_chrdev_region() 注销一个设备号
申请设备步骤:(注意与设备号的区别,这是设备)
struct chev led_dev = {xxx};
cdev_init 初始化字符设备
cdev_add 把字符设备注册到内核
cdev_del 把字符设备从内核中注销
3、代码参考 <path>/05cdev/01dummy
字符设备驱动05cdev/01dummy中测试方法:
在当前目录下创建一个节点 mknod mdev c 251 0
然后write的argv[1]传入绝对路径写
write ./mdev hello 6
read ./mdev
#########################################
# 在内核函数中,尽量不要定义太大的局部变量
# 内核为每个进程在内核中分配一个 2页的内核栈(咱们这就是8K)
# 如果变量太大,会把栈的东西填满,栈里面放着进程很重要的东西, struct task_info 在这里面包含 struct task_struct
# 可以使用 malloc,分配的内粗是在堆里,不影响栈的
###########################################
1、设备类型:
字符设备:能够按照字节流有序的访问的设备
不能 seek,能seek就不是有序的访问了
块设备:只能按照规定的块大小取访问的设备
网络设备:通过网络协议栈访问的设备;
网络设备不对应文件,在 /dev 下不对应节点
选择:
大多数是字符设备;SD卡、硬盘、nand 等是块设备;网卡是网络设备
设备驱动:
向下操作硬件,向上给user提供接口
2、字符设备:led设备、wdt设备(消费电子中看门狗驱动一般用不到,工控领域中一般会用到[打开,关闭,定时])、pwm(timer)设备,在 /dev 下挂载文件,打开关闭操作文件进行相应的操作
/dev/led
open /dev/led
write 123 ---> /dev/led on 点灯
write 456 ---> /dev/led off 关灯
字符设备的核心头文件 < linux/cdev.h >
设备号:
每一个设备都会有一个设备号,是唯一的
主设备号:表示一类设备
次设备号:表示一类设备中的某个设备
主设备号找驱动,次设备号找设备
用户态创建设备节点:
mknod led c 10 20
mknod led1 c 10 20
mknod led2 c 10 20
每一个字符设备都会对应一个结构体 struct cdev,向添加就必须自己添加这么一个结构体
此结构体对应一个或多个结构体:
struct cdev {
struct kobject kobj; //设备模型核心,与C++里的基类相似,用于组织设备;内核操作,
struct module *owner; //一般不用初始化,初始化写成 THIS_MODULE 就行
const struct file_operations *ops;
//该设备的操作集 open release write read ioctl(万能的io操作,看怎么配置)
硬件相关的操作都在此操作集中
struct list_head list;
dev_t dev; //该设备的设备号,主设备号、次设备号都在这一个变量里
主次设备号在哪一位不需记,更改内核版本可能会变
获得主设备号:MAJOR(dev)
获得次设备号:MINOR(dev)
unsigned int count; //对应的设备节点个数;可多个设备节点对应一个结构体
第一个设备号是 10 20, count 是节点是,第二个设备号是 10 21, 根据count的个数一次加;主设备号不变
};
创建一个设备号 MKDEV(major, minor) 参数自己填,到此处不能保证设备号不重复
保证不重复的方法:(上面申请完了要告诉内核,使用下面的方法)
存放全部设备的设备号 cat /proc/device, 可查阅哪个设备号没用
自己规定设备号:(需要先查看哪个设备号不用,否则会出错)
register_chrdev_region() 注册设备号
unregister_chrdev_region() 注销设备号
内核给分配设备:(内核动态分配,就不需要MKDEV申请了)
alloc_chrdev_region() 分配一个设备号
unregister_chrdev_region() 注销一个设备号
申请设备步骤:(注意与设备号的区别,这是设备)
struct chev led_dev = {xxx};
cdev_init 初始化字符设备
cdev_add 把字符设备注册到内核
cdev_del 把字符设备从内核中注销
3、代码参考 <path>/05cdev/01dummy
字符设备驱动05cdev/01dummy中测试方法:
在当前目录下创建一个节点 mknod mdev c 251 0
然后write的argv[1]传入绝对路径写
write ./mdev hello 6
read ./mdev