韦东山嵌入式Liunx驱动大全一


本人学习完韦老师的视频,因此来复习巩固,写以笔记记之。
韦老师的课比较难,第一遍不知道在说什么,但是坚持看完一遍,再来复习,基本上就水到渠成了。
看完视频复习的同学观看最佳!
基于 IMX6ULL-PRO

一、同步与互斥

Linux驱动 = 驱动框架 + 硬件编程

1.1 内联汇编

内联汇编:在C函数中使用汇编代码。
有些算法需要我们手工优化,这时就需要手写汇编代码;或是有时需要调用特殊的汇编指令(比如使用ldrex/strex实现互斥访问),这都涉及内联汇编。
三种不同的方式实现加法函数
① C语言实现后的汇编很复杂,需要入栈、出栈等操作,效率不算高。
反汇编查看add函数的一系列汇编操作
在这里插入图片描述
② 使用汇编函数实现加法
单独另起一个add.S汇编文件
在这里插入图片描述
会导致最后生成文件的反汇编只有2条指令,提高了效率
在这里插入图片描述
③ 使用内联汇编
内联汇编语法:
在这里插入图片描述
①:也可以写作__asm__,表示这是一段内联汇编。
②:有3个取值:volatile、inline、goto。volatile的意思是易变的、不稳定的,用来告诉编译器不要随便优化这段代码,否则可能出问题。③:汇编指令,用双引号包含起来,每条指令 \n 分开
④:输出操作数,内联汇编执行时,输出的数据保存在这里
⑤:输入操作数,内联汇编执行前,输入的数据保存在这里
⑥:除输出操作数外,还修改了那些寄存器、内存
cc:表示汇编代码会修改“flags register”
操作数中的constraint前还可以加上一些修饰字符,比如“=r”、“+r”、“=&r”。
&:告诉编译器,给我分配一个单独的寄存器,别为了省事跟输入操作数用同一个寄存器。

变量的修改需要读出、修改、写入三个步骤,在这过程中若被别的进程抢占,都会导致同步与互斥原理的失败

1.2 原子操作的实现原理和使用

原子操作:就是这个操作不会被打断

typedef struct {
	int counter;
} atomic_t;

在这里插入图片描述
在这里插入图片描述

三条指令分别实现读出、修改、写入
ldrex指令:读入,标记addr为独占访问
strex指令: ①未被抢占时,写入,清除独占标记,返回值Ret = 0。②被抢占,发现非独占,放弃写入,Ret = 1
teq该指令通常用于比较操作数1和操作数2是否相等

(1) 原子变量使用案例

在这里插入图片描述
使用原子变量实现:只能有一个APP访问驱动程序

static atomic_t valid = ATOMIC_INIT(1);
static ssize_t gpio_key_drv_open (struct inode *node, struct file *file)
{
 if (atomic_dec_and_test(&valid)){
 	return 0;}
 	
 atomic_inc(&valid);
 return -EBUSY;
}

valid初始值为1,进入if条件语句执行减1函数后,结果为0,返回值为1,成功返回0;当程序被打断时,由于valid为0,减1后结果为-1,返回值为0,则不执行if语句,返回-EBUSY

(2) 原子位的操作

在这里插入图片描述

1.3 Linux系统下的锁

Linux内核提供了很多类型的锁,它们可以分为两类:
① 自旋锁(spinning lock):简单地说就是无法获得锁时,不会休眠,会一直循环等待。
在这里插入图片描述
② 睡眠锁(sleeping lock):无法获得锁时,当前线程就会休眠;其中又分为互斥量mutex和信号量semaphore。

(1) 自旋锁

SMP就是Symmetric Multi-Processors,对称多处理器;UP即Uni-Processor,系统只有一个单核CPU。
对于单CPU系统,自旋锁的自旋功能就去掉了:只剩下禁止抢占、禁止中断。

① spinlock在UP系统中的实现
对于spin_lock(),当前线程正在执行内核态函数时,它是有可能被别的线程抢占,在UP系统中spin_lock()就退化为preempt_disable()
对于spin_lock_irq(),在UP系统中就退化为local_irq_disable()和preempt_disable()
假设程序A要访问临界资源,可能会有中断也来访问临界资源,可能会有程序B也来访问临界资源,那么使用spin_lock_irq()来保护临界资源:先禁止中断防止中断来抢,再禁止preempt防止其他进程来抢。
②spinlock在SMP系统中的实现
在这里插入图片描述

(2) 信号量semaphore

在这里插入图片描述
初始化semaphore之后,就可以使用down函数或其他衍生版本来获取信号量,使用up函数释放信号量。
down函数的实现
如果semaphore中的count大于0,那么down函数就可以获得信号量;否则就休眠。在读取、修改count时,要使用spinlock来实现互斥。
休眠时,要把当前进程放在semaphore的wait_list链表中,别的进程释放信号量时去wait_list中把进程取出、唤醒。
在这里插入图片描述

up函数的实现
如果有其他进程在等待信号量,则count值无需调整,直接取出第1个等待信号量的进程,把信号量给它,共把它唤醒。
如果没有其他进程在等待信号量,则调整count。
在这里插入图片描述

(3) 互斥量mutex

互斥量mutex结构体,metex中的count值,1表示unlocked,0表示locked,还有一类值“负数”表示“locked,并且可能有其他程序在等待”。
在这里插入图片描述
mutex_lock函数的fastpath实现

在这里插入图片描述在这里插入图片描述

mutex_unlock函数的fastpath实现
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值