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

您所在的位置:网站首页 A9摄像头软件大全 韦东山嵌入式Liunx驱动大全一

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

2024-07-17 11:39| 来源: 网络整理| 查看: 265

文章目录 一、同步与互斥1.1 内联汇编1.2 原子操作的实现原理和使用(1) 原子变量使用案例(2) 原子位的操作 1.3 Linux系统下的锁(1) 自旋锁(2) 信号量semaphore(3) 互斥量mutex 本人学习完韦老师的视频,因此来复习巩固,写以笔记记之。 韦老师的课比较难,第一遍不知道在说什么,但是坚持看完一遍,再来复习,基本上就水到渠成了。 看完视频复习的同学观看最佳! 基于 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实现 在这里插入图片描述 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3