【1】复习
1. read copy_to_user
2. write copy_from_user
3. ioctl 命令码 --->>> 驱动switch ... case
_IO
_IOR
_IOW
_IOWR
4. ioremap iounmap
【2】作业
1.
设备文件
--->>> 设备0 --->>> 设备号(major minor)
驱动 --->>> 设备1
--->>> 设备2
在创建设备文件的时候会区分次设备号 --->>> 创建inode结构体
inode结构体成员变量中应该有设备号相关的信息
打开设备文件的时候 --->>> open("filename",...);
2. LED驱动
1. 查看原理图 --->>> led --->>> cpu(GPIO引脚)
红 --->>> GPIOA28
2. 查看芯片数据手册 --->>> s5p6818
[1].GPIOAOUT 0xC001A000
[28] 0 低电平 1 高电平
[2].GPIOAOUTENB 0xC001A004
[28] 1 output
[3].GPIOAALTFN 0xC001A024
[25:24] 00 GPIO
/*********************************
*功能:读addr地址里的数据(32bit)
*参数:
* @addr 虚拟地址
*返回值:读到的数据
*****************************/
readl(addr)
/*********************************
*功能:写数据(32bit)到addr地址里
*参数:
* @b 值
* @addr 虚拟地址
*返回值:读到的数据
*****************************/
writel(b,addr)
【一】、简化版的字符设备驱动
1. register_chrdev
/**********************************************************************
*功能:注册字符设备驱动
*参数:
* @major 主设备号(major == 0:自动分配 否则注册主设备号)
* @name 设备驱动名
* @fops 操作方法集指针
*返回值:如果major==0,成功返回分配到的主设备号,失败返回负数错误码
* 如果major >0,成功返回0,失败返回负数错误码
*********************************************************************/
int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
2. unregister_chrdev
/****************************************************************
*功能:注销字符设备驱动
*参数:
* @major 主设备号
* @name 设备名
*返回值:void
****************************************************************/
void unregister_chrdev(unsigned int major, const char *name)
【二】、内核中分配内存的函数
应用层:
malloc
内核层:
1. kmalloc
/**********************************************************
*功能:在内核空间分配内存的函数
*参数:
* @size 分配内存空间的大小
* @flags 分配内存的标志
* GFP_KERNEL 分配过程可以被打断
* GFP_ATOMIC 分配一次完成
*返回值:成功返回分配到的空间地址,失败返回NULL
*特点:内配的内存空间相对来说较小,128K。分配在低端内存中
*在虚拟内存上连续,在物理地址上也是连续的
*********************************************************/
void *kmalloc(size_t size, gfp_t flags)
void *kzalloc(size_t size, gfp_t flags) //清零
void kfree(const void *block)
2. vmalloc
/*****************************************************
*功能:在内核空间分配内存
*参数:
* @size 分配内存空间的大小
*返回值:成功返回分配到的空间地址,失败返回NULL
*特点:分配的内存空间相对较大
*在虚拟内存上连续,在物理内存上不一定连续
*****************************************************/
void *vmalloc(unsigned long size)
void *vmalloc(unsigned long size) //清零
void vfree(const void *addr)
3. __get_free_page & __get_free_pages
/********************************************************************
*功能:分配内存
*参数:
* @gfp_mask
* @order 分配2的order次方页
*******************************************************************/
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
get_order(n) //获取order值,n 分配内存空间大小(字节)
【三】、并发与竟态
并发:多个执行单元同时被执行
执行单元:进程、线程、SMP(对称多处理器)
临界区
多个执行单元可以访问到的代码区
共享(临界)资源
多个执行单元可以访问到的软件资源和硬件资源
并发可能导致竟态
产生竟态的原因:
1. 进程和抢占它的进程
2. 进程和中断
3. SMP
解决:
同步和互斥机制
同步: 顺序性
互斥: 排他性
应用层:线程 --->>> 同步互斥
信号量
互斥锁
条件变量
进程 --->>> 进程间通信方式
内核中解决竟态的方法:
中断屏蔽
============================
自旋锁
原子操作
信号量
互斥体
【四】、中断屏蔽
中断屏蔽是屏蔽中断,由 进程和中断 导致的竟态就可以解决
屏蔽中断 local_irq_disable()
临界区 --->>> 要求临界区执行时间足够短
使能中断 local_irq_enable()
对于有对称多处理器产生的竟态是无法解决的
【五】、自旋锁
锁机制 --->>> 互斥
初始化自旋锁
上锁
临界区
解锁
特点:
1. 自旋锁上锁成功会屏蔽进程抢占
2. 自旋锁获取锁失败自旋(100%占用cpu)
使用自旋锁保护的临界区要求:
1. 执行时间足够短
2. 不能有进程调度相关函数
自旋锁使用:
<linux/spinlock.h>
/********************************************
*功能:初始化自旋锁
*参数:
* @_lock 结构体指针
*******************************************/
spin_lock_init(spinlock_t *_lock)
/************************************************
*功能: 自旋锁上锁
*参数:
* @lock
***********************************************/
void spin_lock(spinlock_t *lock)
/************************************************
*功能: 自旋锁解锁
*参数:
* @lock
***********************************************/
void spin_unlock(spinlock_t *lock)