.. SPDX-License-Identifier: GPL-2.0 .. include:: ../disclaimer-zh_CN.rst :Original: Documentation/locking/mutex-design.rst :翻译: ĺ”č‰şčź Tang Yizhou <tangyeechou@gmail.com> ================ 通用互斥é”ĺ系统 ================ :ĺťç¨ż: Ingo Molnar <mingo@redhat.com> :ć›´ć–°: Davidlohr Bueso <davidlohr@hp.com> 什äąćŻäş’ć–Ąé”? -------------- 在Linuxĺ†…ć ¸ä¸ďĽŚäş’ć–Ąé”ďĽmutex)指的ćŻä¸€ä¸Şç‰ąć®Šçš„ĺŠ é”原čŻďĽŚĺ®ĺś¨ĺ…±äş«ĺ†…ĺ系统上 强ĺ¶äżťčŻĺşŹĺ—化,而不仅仅ćŻćŚ‡ĺś¨ĺ¦ćśŻç•Ść–类似的ç†č®şć•™ç§‘书ä¸ĺ‡şçŽ°çš„é€šç”¨ćśŻčŻâ€śç›¸äş’ 排斥”。互斥é”ćŻä¸€ç§Ťçťˇçś é”,ĺ®çš„行为类似于二进ĺ¶äżˇĺŹ·é‡ŹďĽsemaphores),在 2006年被引入时[1],作为ĺŽč€…的替代ĺ“。这种新的数据结构ćŹäľ›äş†č®¸ĺ¤šäĽç‚ąďĽŚĺڅ㋬㛴 简单的接口,以及在当时更少的代ç 量ďĽč§çĽşé™·ďĽ‰ă€‚ [1] https://lwn.net/Articles/164802/ 实现 ---- äş’ć–Ąé”由“struct mutex”表示,在include/linux/mutex.hä¸ĺ®šäą‰ďĽŚĺą¶ĺś¨ kernel/locking/mutex.cä¸ĺ®žçŽ°ă€‚čż™äş›é”使用一个原ĺĺŹé‡ŹďĽ->owner)来跟踪 ĺ®ä»¬ç”źĺ‘˝ĺ‘¨ćśźĺ†…çš„é”状ć€ă€‚ĺ—段owner实际上包ĺ«çš„ćŻćڇĺ‘当前é”所有者的 `struct task_struct *` 指é’ďĽŚĺ› ć¤ĺ¦‚ćžść— äşşćŚćś‰é”,ĺ™ĺ®çš„值为空ďĽNULL)。 由于task_struct的指é’至少按L1_CACHE_BYTES对é˝ďĽŚä˝Žä˝ŤďĽ3)被用来ĺ储额外 的状ć€ďĽäľ‹ĺ¦‚,ç‰ĺľ…者ĺ—表非空)。在其最基本的形式ä¸ďĽŚĺ®čżĺŚ…ć‹¬ä¸€ä¸Şç‰ĺľ…éźĺ—ĺ’Ś 一个确保对其序ĺ—化访问的自旋é”。ć¤ĺ¤–,CONFIG_MUTEX_SPIN_ON_OWNER=yçš„ 系统使用一个自旋MCSé”ďĽ->osq,译注:MCSćŻä¸¤ä¸ŞäşşĺŤçš„ĺ并缩写),在下文的 ďĽii)ä¸ćŹŹčż°ă€‚ 准备获得一把自旋é”时,有三种可č˝ç»Źčż‡çš„路径,取决于é”的状ć€ďĽš (i) 快速路径:试图通过č°ç”¨cmpxchg()修改é”的所有者为当前任务,以ć¤ĺŽźĺ化地 获取é”ă€‚čż™ĺŹŞĺś¨ć— ç«žäş‰çš„ć…况下有ć•ďĽcmpxchg()检查值ćŻĺ¦ä¸ş0,所以3ä¸ŞçŠ¶ć€ ćŻ”ç‰ąĺż…éˇ»ä¸ş0)。如果é”处在竞争状ć€ďĽŚä»Łç 进入下一个可č˝çš„路径。 (ii) ä¸é€źč·Żĺľ„:也就ćŻäąč§‚自旋,当é”的所有者ćŁĺś¨čżčˇŚĺą¶ä¸”没有其ĺ®äĽĺ…çş§ć›´é«çš„ 任务ďĽneed_resched,需č¦é‡Ťć–°č°ĺş¦ďĽ‰ĺ‡†ĺ¤‡čżčˇŚć—¶ďĽŚĺ˝“前任务试图自旋来获得 é”。原ç†ćŻďĽŚĺ¦‚ćžśé”的所有者ćŁĺś¨čżčˇŚďĽŚĺ®ĺľĺŹŻč˝ä¸Ťäą…就会释放é”。互斥é”自旋体 使用MCSé”排éźďĽŚčż™ć ·ĺŹŞćś‰ä¸€ä¸Şč‡Şć—‹ä˝“ĺŹŻä»Ąç«žäş‰äş’ć–Ąé”。 MCSé”ďĽç”±Mellor-Crummeyĺ’ŚScottćŹĺ‡şďĽ‰ćŻä¸€ä¸Şç®€ĺŤ•的自旋é”,ĺ®ĺ…·ćś‰ä¸€äş› ç†ćłçš„特性,比如公平,以及每个CPU在试图获得é”时在一个本地ĺŹé‡Źä¸Šč‡Şć—‹ă€‚ ĺ®éżĺ…Ťäş†ĺ¸¸č§çš„“检测-设置”自旋é”实现导致的ďĽCPUć ¸é—´ďĽ‰çĽ“ĺ行回弹 ďĽcacheline bouncing)这种ć‚贵的开销。一个类MCSé”ćŻä¸şĺ®žçŽ°çťˇçś é”çš„ äąč§‚自旋而专门定ĺ¶çš„。这种定ĺ¶MCSé”的一个重č¦ç‰ąć€§ćŻďĽŚĺ®ćś‰ä¸€ä¸Şé˘ťĺ¤–的属性, 当自旋体需č¦é‡Ťć–°č°ĺş¦ć—¶ďĽŚĺ®ä»¬č˝ĺ¤źé€€ĺ‡şMCS自旋é”éźĺ—。这进一ćĄćś‰ĺŠ©äşŽéżĺ…Ť 以下场景:需č¦é‡Ťć–°č°ĺş¦çš„MCS自旋体将继ç»č‡Şć—‹ç‰ĺľ…自旋体所有者,即将获得 MCSé”时却直接进入慢速路径。 (iii) 慢速路径:最ĺŽçš„ć‰‹ć®µďĽŚĺ¦‚ćžśä»Ťç„¶ć— ćł•čŽ·ĺľ—é”ďĽŚčŻĄä»»ĺŠˇäĽšč˘«ć·»ĺŠ ĺ°ç‰ĺľ…éźĺ—ä¸ďĽŚ äĽ‘çś ç›´ĺ°č˘«č§Łé”路径唤醒。在通常ć…况下,ĺ®ä»ĄTASK_UNINTERRUPTIBLEçŠ¶ć€ é»ĺˇžă€‚ č™˝ç„¶ä»Žĺ˝˘ĺĽŹä¸Šçś‹ďĽŚĺ†…ć ¸äş’ć–Ąé”ćŻĺŹŻçťˇçś çš„é”,路径(ii)使ĺ®ĺ®žé™…上ć为混ĺ类型。通过 简单地不ä¸ć–一个任务并忙着ç‰ĺľ…ĺ‡ ä¸Şĺ‘¨ćśźďĽŚč€Śä¸ŤćŻç«‹ĺŤłçťˇçś ,这种é”已经被认为ćľč‘— 改善一些工作负载的性č˝ă€‚注意,这种技术也被用于读写信号量ďĽrw-semaphores)。 čŻäą‰ ---- äş’ć–Ąé”ĺ系统检查并强ĺ¶ć‰§čˇŚä»Ąä¸‹č§„ĺ™: - 每次只有一个任务可以ćŚćś‰čŻĄäş’ć–Ąé”。 - 只有é”的所有者可以解é”该互斥é”。 - 不ĺ…许多次解é”。 - 不ĺ…č®¸é€’ĺ˝’ĺŠ é”/č§Łé”。 - äş’ć–Ąé”只č˝é€ščż‡API进行ĺťĺ§‹ĺŚ–ďĽč§ä¸‹ć–‡ďĽ‰ă€‚ - 一个任务不č˝ĺś¨ćŚćś‰äş’ć–Ąé”çš„ć…况下退出。 - ćŚćś‰é”的内ĺ区域不得被释放。 - 被ćŚćś‰çš„é”不č˝č˘«é‡Ťć–°ĺťĺ§‹ĺŚ–ă€‚ - äş’ć–Ąé”不č˝ç”¨äşŽçˇ¬ä»¶ć–软件ä¸ć–上下文,如小任务ďĽtasklet)和定时器。 当CONFIG DEBUG_MUTEXES被ĺŻç”¨ć—¶ďĽŚčż™äş›čŻäą‰ĺ°†č˘«ĺ®Śĺ…¨ĺĽşĺ¶ć‰§čˇŚă€‚ć¤ĺ¤–ďĽŚäş’ć–Ąé” č°čŻ•ä»Łç čżĺ®žçŽ°äş†ä¸€äş›ĺ…¶ĺ®ç‰ąć€§ďĽŚä˝żé”çš„č°čŻ•ć›´ĺ®ąć“ă€ć›´ĺż«é€źďĽš - 当打印ĺ°č°čŻ•čľ“ĺ‡şć—¶ďĽŚć€»ćŻä˝żç”¨äş’ć–Ąé”的符号ĺŤç§°ă€‚ - ĺŠ é”点跟踪,函数ĺŤç¬¦ĺŹ·ĺŚ–ćźĄć‰ľďĽŚçł»ç»źćŚćś‰çš„ĺ…¨é¨é”çš„ĺ—表,打印出ĺ®ä»¬ă€‚ - 所有者跟踪。 - 检测自ć‘递归的é”并打印所有相关信ćŻă€‚ - 检测多任务环形依赖ć»é”,并打印所有受影响的é”和任务ďĽĺą¶ä¸”只é™äşŽčż™äş›ä»»ĺŠˇďĽ‰ă€‚ 接口 ---- éť™ć€ĺ®šäą‰äş’ć–Ąé”:: DEFINE_MUTEX(name); 动ć€ĺťĺ§‹ĺŚ–äş’ć–Ąé”:: mutex_init(mutex); 以不可ä¸ć–方式ďĽuninterruptible)获取互斥é”:: void mutex_lock(struct mutex *lock); void mutex_lock_nested(struct mutex *lock, unsigned int subclass); int mutex_trylock(struct mutex *lock); 以可ä¸ć–方式ďĽinterruptible)获取互斥é”:: int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass); int mutex_lock_interruptible(struct mutex *lock); 当原ĺĺŹé‡Źĺ‡Źä¸ş0时,以可ä¸ć–方式ďĽinterruptible)获取互斥é”:: int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock); 释放互斥é”:: void mutex_unlock(struct mutex *lock); 检测ćŻĺ¦ĺ·˛ç»ŹčŽ·ĺŹ–äş’ć–Ąé”:: int mutex_is_locked(struct mutex *lock); 缺陷 ---- 与ĺ®ćś€ĺťçš„设计和目的不ĺŚďĽŚ'struct mutex' ćŻĺ†…ć ¸ä¸ćś€ĺ¤§çš„é”之一。例如:在 x86-64上ĺ®ćŻ32ĺ—节,而 'struct semaphore' ćŻ24ĺ—节,rw_semaphorećŻ 40ĺ—节。更大的结构体大小意味着更多的CPU缓ĺ和内ĺĺŤ ç”¨ă€‚ ä˝•ć—¶ä˝żç”¨äş’ć–Ąé” -------------- 总ćŻäĽĺ…选择互斥é”而不ćŻä»»ä˝•ĺ…¶ĺ®é”原čŻďĽŚé™¤éťžäş’ć–Ąé”çš„ä¸Ąć ĽčŻäą‰ä¸Ťĺ适,和/ć–临界区 é»ć˘é”被共享。