嵌入式linux 并发与竞争

原子操作

         linux内核定义了叫做atomic_t的结构体来完成整型数据的原子操作,在使用中原子变量来代替整型变量。

        atomic_t lock; 定义lock变量,本身是一个整型变量,内核中提供了大量原子操作的API函数

1,先初始化原子变量

        atomic_t   lock = ATOMIC_INIT(0);    lock 初始化为0

        atomic_set(&lock, 10);                        lock初始化为10

2,对原子变量进行操作,来锁住变量

        上面的API函数表就可以对原子变量进行操作

3,释放原子变量

        由于在使用原子操作的时候我们可以减1,所以放释放的时候我们需要对原子变量进行加1

自旋锁

        原子操作只能对整型变量或者位进行保护,但是,在实际使用环境中怎么可能只有整型或者位这么简单的临界区(共享资源),例如设备结构体就需要被保护,原子操作就无法使用了。

        当一个线程访问某个共享资源的时候,首先需要获得相应的锁,锁只能被一个线程所持有,只要这个线程不释放锁,那么其他线程就不能获得此锁。

        自旋锁不能长时间持有,因为其他线程也要访问的时候,会一直等待你释放自旋锁,这样会浪费资源,降低系统性能。

        被自旋锁保护的临界区一定不能调用任何能够引起休眠的API函数,否则的话可能会引起死锁现象的发生。因为一旦休眠,这个线程就会自动释放CPU使用权,从而线程B开始运行,线程B也想要获得锁,但是锁已经被线程A所使用了,又因为内核抢占被禁止了,线程B无法被调度出去,线程A也就无法运行,锁就没办法释放,就会导致死锁。

        spinlock_t     lock;        //定义自旋锁

         中断也会引起死锁的发生,在线程A获得锁之后被中断抢走CPU使用权的时候,中断也想要获得锁,但是锁被线程A占用了,中断会一直申请锁,但是线程A又没办法释放,死锁就发生了,对于这种情况需要先禁止本地中断,Linux 内核提供了相应的 API 函数。

1,初始化自旋锁

spin_lock_init(&gpioled.lock);

2,获取自旋锁

//flags代表中断状态,当被中断抢走时,中断结束会保存当前的状态
spin_lock_irqsave(&dev->lock, flags);

3,释放自旋锁

spin_unlock_irqrestore(&dev->lock, flags);

信号量

        Linux 内核也提供了信号量机制,信号量常常用于控制对共享资源的访问。相较于自旋锁,信号量可以使线程进入休眠状态。

  • 因为信号量可以使等待资源线程进入休眠状态,因此适用于那些占用资源比较久的场合
  • 信号量不能用于中断,以为信号量会引起休眠,中断不能休眠。
  • 如果共享资源的持有时间比较短,那么局不适合使用信号量了,因为频繁的休眠,切换线程引起的开销远大于信号量带来的那点优势。

        信号量有个信号量值,相当于一栋楼里面有10个房间(线程),这个10也就想当于信号量值为10,当每进一个人的话,信号量值就会减1,当房子都被占用的话,信号量值为0,也就不允许其他人再进去了,只有当其他人出来的时候才可以再进去。

        struct    semaphore   sem;          /* 信号量 */

1,初始化信号量

sema_init(&gpioled.sem, 1);        //只能一个线程访问

2,获取信号量

down(&gpioled.sem);            //不能被中断打断

3,释放信号量

up(&dev->sem);		/* 释放信号量,信号量值加1 */

互斥体

        将信号量值设为1就可以使用信号量进行互斥访问了,虽然可以通过信号量进行互斥访问,但是linux提供了一个比信号量更加专业的机制来进行互斥,他就是互斥体--mutex。

  • mutex可以导致休眠,因此不能再中断中使用mutex,中断中只能使用自旋锁。
  • 和信号量一样,mutex保护的临界区可以调用引起阻塞的API函数
  • 因为一次只能一个线程可以持有mutex,因此,必须由mutex的持有者释放mutex。

        struct    mutex    lock;        /* 互斥体 */

 1,初始化互斥体

mutex_init(&gpioled.lock);

2,获取互斥体

mutex_lock(&gpioled.lock);	/* 不能被信号打断 */

3,释放互斥体

mutex_unlock(&dev->lock);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值