姓名:尤乐航 学号:19029100006 学院:电子工程学院
【嵌牛导读】linux同步方法
【嵌牛鼻子】嵌入式 Linux系统
【嵌牛提问】linux同步方法
【嵌牛正文】
5.1原子操作
内核提供了两组原子操作接口,一组针对整数进行操作,另一组针对单独的位进行操作。针对整数的原子操作只能对atomic_t类型的数据进行处理。
Linux内核通过一些手段来实现某些操作的原子性,例如
操作码前缀为lock的汇编指令,即使多cpu下也能保证其后汇编指令的原子性,lock会锁定内存总线,保证在执行汇编指令时没有其他CPU同时读写内存。多处理器中,Linux内核通过提供atomic_t类型封装了一系列原子操作,如atomic_inc(v)表示把1加到v。
5.2屏障
屏障的意思就是在指令之间插入一道屏障,让这道屏障之前和之后的指令不可能因重排而跨越这道屏障。
5.3自旋锁
自旋锁是一种广泛的同步技术,它锁住的是一块临界区,进入临界区时需要先获取自旋锁,在离开临界区时需要释放自旋锁。如果已经有其他进程获取了该锁,那么当前想要获取该锁的进程只能在临界区门口来回溜达(自旋),直到获取该锁。自旋锁类似于现实生活中的给房间的门上锁,进入房间访问资源时需要锁住门,防止其他人同时进入房间,退出房间时,再打开锁。
5.4读写锁
普通自旋锁spin_lock类的函数在进入临界区时,对临界区中的操作行为不细分。只要是访问共享资源,就执行加锁操作。但是有时候,比如某些临界区的代码只是去读这些共享的数据,并不会改写,如果采用spin_lock()函数,就意味着,任意时刻只能有一个进程可以读取这些共享数据。如果系统中有大量对这些共享资源的读操作,很明显spin_lock将会降低系统的性能。因此提出了读写自旋锁rwlock的概念。对照普通自旋锁,读写自旋锁允许多个读者进程同时进入临界区,交错访问同一个临界资源,提高了系统的并发能力,提升了系统的吞吐量。
5.5信号量
信号量和自旋锁类似,也是为了控制进程进入临界区,但是信号量和自旋锁的重大区别是:
自旋锁获取锁的过程,不会主动调用schedule()进行进程切换,而是占用cpu,拼命的自旋,类似于while耗时操作。信号量中存在一个进程等待队列,未获取锁的进程将挂到该队列中,然后主动调用schedule()切换进程,让出cpu
5.6互斥体
互斥体是一种睡眠锁,他是一种简单的睡眠锁,其行为和count 为 1 的信号量类似。(关于信号量参考:Linux 内核同步(四):信号量 semaphore)。互斥体简洁高效,但是相比信号量,有更多的限制,因此对于互斥体的使用条件更加严格:
[if !supportLists]l [endif]任何时刻,只有一个指定的任务允许持有mutex,也就是说,mutex 的计数永远是 1;
[if !supportLists]l [endif]给mutex 上锁这,必须负责给他解锁,也就是不允许在一个上下文中上锁,在另外一个上下文中解锁。这个限制注定了 mutex 无法承担内核和用户空间同步的复杂场景。常用的方式是在一个上下文中进行上锁/解锁。
[if !supportLists]l [endif]递归的调用上锁和解锁是不允许的。也就是说,不能递归的去持有同一个锁,也不能够递归的解开一个已经解开的锁。
[if !supportLists]l [endif]当持有mutex 的进程,不允许退出。
[if !supportLists]l [endif]mutex 不允许在中断上下文和软中断上下文中使用过,即便是mutex_trylock 也不行。
[if !supportLists]l [endif]mutex 只能使用内核提供的 APIs操作,不允许拷贝,手动初始化和重复初始化。