当前位置: 主页 > 电脑系统维修 > Linux操作系统内核进修之同步

Linux操作系统内核进修之同步

发布时间:02-03 19:37点击:

  [临界区和合作环境]

  叫做临界区就是拜访和操作共享数据的代码段。多个施行线程并发拜访同一度资源一般是没有保险的,为了防止正在临界区中并发拜访,coder必需该署代码原子团施行。

  假如两个施行线程有能够在于同一度临界区中同声施行,那样这就是顺序蕴含的一度bug.假如这种状况的确发作了,咱们就称它是合作环境(race conditions)。防止并发和预防合作环境称为同步(synchronization)。

  [形成并发施行的缘由]

  用户时间之因为需求同步,是由于用户顺序会被安排顺序抢占和从新安排。正在内核中有相似能够形成并发施行的缘由:

  中缀:中缀简直能够正在任几时辰异步发作,也就是随时打断以后正正在施行的代码;

  软中缀和tasklet:内核子能正在任几时辰或者安排软中缀和tasklet,打断以后正正在施行的代码;

  内核抢占:由于内核存正在抢占性,因为内核中的使命能够会被另一使命抢占;

  睡眠及与用户时间的同步:正在内核施行的历程能够会睡眠,这就会安排顺序,从而招致安排一度新的用户历程施行;

  对于称解决器:两个或者多个解决器能够同声施行代码。

  [哪些代码需求同步]

  咱们正在编写内核代码时,你要问本人上面该署成绩:

  某个数据是没有是大局的?除非以后线程外,其余线程能没有能拜访它?

  某个数据会没有会正在历程高低文和中缀高低文种共享?它是没有是要正在两个没有同的中缀解决顺序享?

  历程正在拜访数据时可没有能够被抢占?被安排的新顺序会没有会拜访同一数据?

  以后历程是没有是会睡眠(堵塞)正在某些资源上,假如是,它会让共享数据在于何种形态?

  怎么预防数据失控?

  假如某个因变量又正在另一度解决上被安排将会发作什么呢?

  如何确保代码远离并发呢?

  简而言之,简直拜访一切的内核大局变量和共享数据都需求那种方式的同步办法。

  [死锁]

  死锁的发生需求定然的环境:要一度或者多个施行线程和一度或者多个资源,每个线程都正在期待内中的一度资源,但一切的资源都曾经被占用了。所程都正在彼此期待,但它们永久没有会曾经拥有的资源,此外任何资源都无奈接续,这就象征着死锁的发作。

  Example:有两个线程和两把锁

  线程1 线程2

  失掉锁A 失掉锁B

  试图失掉锁B 试图失掉锁A

  期待锁B 期待锁A

  [原子团操作]

  原子团操作能够训令以原子团的形式施行-施行进程没有被打断。内核需要了两组原子团操作接口:一组对准于成数停止操作,另一组对准于共同的位停止操作。

  原子团成数类型

  view plain typedef struct { intcounter;} atomic_t;[自旋锁]

  自旋锁(spin lock)至多只能被一度可施行线程持有。假如一度施行线程试图失掉一度被曾经持有(即叫做的争用)的自旋锁,那样该线程就会没有断停止忙重复-缭绕-期待锁从新可用。

  spinlock构造体:

  view plain typedef struct spinlock { union { struct raw_spinlock rlock;

  #ifdef CONFIG_DEBUG_LOCK_ALLOC # define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))

  struct { u8 __padding[LOCK_PADSIZE];struct lockdep_map dep_map;};#endif };} spinlock_t;一度被争用的自旋锁是的要求它的线程正在期待锁从新可用时自旋,尤其糜费解决器工夫,这种行止是自旋锁的要端。因为自旋锁没有该当被短工夫持有。持有自旋锁的工夫最好小于实现两次高低文切换的物耗,也就是两次调用schedule()的工夫。

  自旋锁能够用来中缀解决顺序中,然而信号量没有能够,信号量会招致睡眠。

  运用锁的时分定然要有的放矢,要有对准于性。要晓得需求的是数据而没有是代码。

  [信号量]

  Linux中的信号量是一种睡眠锁。假如有一度使命试图失掉一度没有可用(曾经被占用)的信号量时,信号量会将其促进一度期待队列中,而后让其睡眠。那时解决器能重获,从而去施行其余代码。当持部分信号量可用(被)后,在于期待排队中的那个使命将被,并失掉该信号量。

  semaphore构造体:

  view plain struct semaphore { spinlock_t lock;unsigned int count;structlist_head wait_list;};运用信号量应留意的中央:

  因为争用信号量的历程正在期待锁从新变为可用时会睡眠,因为信号量适宜用来锁会被短工夫持部分状况;

  相同,锁被长工夫持有时,运用信号量就没有能太适宜了。由于睡眠、期待队列以及所破费的开支能够比锁被占用的全副工夫还要长;

  因为施行线程正在锁被争用时会睡眠,因为只能正在历程高低文中能力获可信号量锁,由于正在中缀高低文是没有能停止安排的;

  你能够正在持有信号量时去睡眠,由于当其余历程试图失掉同一信号量时没有会因而而死锁。

  正在你占用信号量的同声没有能占用自旋锁。由于正在你期待信号量时能够会睡眠,而正在持有自旋锁时是没有答应睡眠的。

  [互斥体]

  Linux最新的linux内核中,互斥体mutex是一种完成互斥的一定睡眠锁。Mutex正在内核中对于应数据构造mutex,其行止和运用计数为1的信号量相似,但操作接口更容易,完成也更高效,并且运用更强。

  mutex构造体:

  view plain struct mutex { / 1: unlocked, 0: locked, negative: locked, possible waiters / atomic_t count;spinlock_t wait_lock;struct list_head wait_list;#if defined(CONFIG_DEBUG_MUTEXES) defined(CONFIG_SMP)

  struct task_struct owner;#endif #ifdef CONFIG_DEBUG_MUTEXES const char name;void magic;#endif #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map;#endif };Mutex运用:

  任几时分中只要一度使命能够持有mutex,也就是说,mutex的运用计数永久是1;

  给mutex上锁者必需担任给其再解锁,你没有能正在一度高低文中锁定一度mutex,而正在另一度高低文中给它解锁。某个使得mutex没有适合内核同用户时间简单的同步场景。最常运用的形式是:正在同一高低文中上锁和解锁。

  递归地上锁和解锁是没有答应的。也就是说,你没有能递归地持有同一度锁,异样你也没有能再去解锁一度曾经被解开的mutex;

  Mutex没有能正在中缀或者许下半部中运用;

  Mutex只能经过API治理

  [信号量和互斥体]

  互斥锁和信号量很类似,内核中两者共处会令人混杂。所幸,它们的规范运用形式都有很容易的标准:除了mutex的这个束缚障碍你运用,要不相比信号量要优先运用mutex.当你写新代码时,只要碰到特别场所才会需求运用信号量。因而首选mutex.

  [自旋锁和互斥体]

  理解几时气用自旋锁,几时气用互斥体或者许信号量对于编写优质代码很主要,然而少数状况下,并没有需求太多的思忖,由于正在中缀高低文中只能运用自旋锁,而正在使命睡眠时只能运用互斥体。

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
电脑维修