linux驱动----内核同步机制

本文详细介绍了Linux内核中实现同步的几种关键机制,包括信号量的定义、作用、API以及如何在进程间和线程间使用;原子操作的概念及其在内核中的应用;以及自旋锁的原理、优缺点和相关函数。这些机制对于保证系统稳定性和并发控制至关重要。
摘要由CSDN通过智能技术生成

一、为什么要有同步机制

        在操作系统引入了进程概念,进程成为调度实体后,系统就具备了并发执行多个进程的能力,但也导致了系统中各个进程之间的资源竞争和共享。对于这些交错路径执行的内核路径,如不采取必要的同步措施,将会对一些关键数据结构进行交错访问和修改,从而导致这些数据结构状态的不一致,进而导致系统崩溃。因此,为了确保系统高效稳定有序地运行,linux必须要采用同步机制。

二、内核同步机制的手段

信号量;原子操作;自旋锁;异步通知

三、信号量

3.1 信号量的作用

        信号量本质上就是一个可以操作的数,这个数可以进行加或者是减的操作,加的时候相当于信号的释放,减的时候相当于信号的消耗,当信号量消耗到0的时候  表示资源已经被消耗完,除非当别的程序释放了信号量。

        在IPC通讯里边,主要用于进程间的同步与互斥;

        在多线程中,主要用于线程间的同步与互斥;

        在内核中,主要用于内核的同步与互斥;

3.2 信号量相关的API

信号量的创建:

静态创建:

        #define DEFINE_SEMAPHORE(name) \

        struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)

                name:信号量的核心结构体的名字

         静态创建的时候会默认的将信号量的值设置成1

动态创建:

函数的功能:动态的创建一个信号量

函数的头文件:<linux/semaphore.h>

函数的原型:void sema_init(struct semaphore *sem, int val)

函数的参数:

        struct semaphore *sem:信号量的核心结构体

        int val:信号量的初值

函数的返回值:无

++++++++++++++++++++++++++++++++++++++++++++++++++++++++

信号量的核心结构体

struct semaphore {

        raw_spinlock_t  lock;   //自旋锁

        unsigned int count;     //信号量的值,当信号量的值为正数的时候 ,表示信号量可用

                                           当信号量的值为0的时候表示信号量不可以用

        struct list_head wait_list;

};

++++++++++++++++++++++++++++++++++++++++++++++++++++++++

信号量的操作

头文件:<inux/semaphore.h>

信号量的消耗 (P操作)

void down(struct semaphore *sem);

阻塞的消耗一个信号量,当信号量消耗不成功,就会陷入阻塞,直到有其他的程序释放了信号

int down_interruptible(struct semaphore *sem);

阻塞的请求一个信号量,当成功请求到信号后马上返回,

当请求失败时会陷入阻塞,直到有其他的程序释放了信号或者是产生了中断

int down_trylock(struct semaphore *sem);

非阻塞的消耗一个信号量,假如信号量消耗成功  返回0,假如信号量消耗失败  返回1

信号量的释放 (V操作)

void up(struct semaphore *sem);

释放信号量,对信号量的成员count进行加1

四、原子操作

4.1 什么叫做原子操作

原子操作---在linux操作系统里,叫做不可分割操作;

原子操作:就是赋值,这个赋值跟我们之前所学的赋值又有些不一样,原子操作的赋值是不可被打断的,也就是说用原子操作进行赋值,必然会赋值成功,不会被打断。

4.2 原子操作相关的结构体

typedef struct {

        int counter;  //原子操作的对象

} atomic_t;

4.3 原子操作相关的API

头文件:#include <asm/types.h>

设置原子的值: atomic_set(v, i):

参数

        v:原子的结构体的指针

        i:你要给原子赋的值

++++++++++++++++++++++++++++++++++++++++++++++

读取原子的值:int atomic_read(const atomic_t *v);

        const atomic_t *v:原子的核心结构体指针

+++++++++++++++++++++++++++++++++++++++++++++++

原子值进行加操作:atomic_add(int i, atomic_t * v);

参数:      

        i:要给原子值加上的数值

        v:原子的核心结构体指针

++++++++++++++++++++++++++++++++++++++++++++++++

原子值的减操作:atomic_sub(int i, atomic_t * v);

参数: 

        i:要减去的值

        v:原子的核心结构体指针

+++++++++++++++++++++++++++++++++++++++++++++++++

原子的自加: atomic_inc(atomic_t * v);

+++++++++++++++++++++++++++++++++++++++++++++++++

原子的自减:atomic_dec(atomic_t * v);

+++++++++++++++++++++++++++++++++++++++++++++++++

判断原子值是否为1:atomic_dec_and_test(atomic_t * v)

返回值:

        如果为1,则返回真

        否则返回0

五、自旋锁

5.1 自旋锁、互斥锁

在内核里也有互斥锁

初始化锁:mutex_init();

上锁:mutex_lock();

        mutex_trylock();

解锁:mutex_unlock();

在内核里互斥锁的用法跟在多线程编程里使用的方法是一样的

++++++++++++++++++++++++++++++++++++++++++++++++++++++++

自旋锁是嵌入里比较常用的一种底层锁,下面是优缺点:

缺点:占用的资源比较多,类似于while(1)会不停的询问条件是否能满足;

优点:反应比互斥锁要及时;

5.2 自旋锁相关的API

函数功能:初始化一个自旋锁的核心结构体

函数的头文件:linux/spinlock.h

函数的原型:spin_lock_init(spinlock_t *lock)

函数的参数:

        spinlock_t *lock:自旋锁的核心结构体的指针,需要声明一个这样的结构体

函数的返回值:无

++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:阻塞的申请一个自旋锁

函数的头文件:linux/spinlock.h

函数的原型:void spin_lock(spinlock_t *lock)

函数的参数:spinlock_t *lock:自旋锁的核心结构体的指针

函数的返回值:无

++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:非阻塞的请求一个自旋锁

函数的头文件:linux/spinlock.h

函数的原型:int spin_trylock(spinlock_t *lock)

函数的参数:spinlock_t *lock:自旋锁的核心结构体的指针

函数的返回值:

        成功 返回0

        失败  返回非0

++++++++++++++++++++++++++++++++++++++++++++++++++++++++

函数的功能:释放一个自旋锁

函数的头文件:linux/spinlock.h

函数的原型:void spin_unlock(spinlock_t *lock);

函数的参数:spinlock_t *lock:自旋锁的核心结构体的指针

函数的返回值:无

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小白菜123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值