.. 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缓å˜å’Œå†…å˜å 用。 ä½•æ—¶ä½¿ç”¨äº’æ–¥é” -------------- 总是优先选择互斥é”è€Œä¸æ˜¯ä»»ä½•其它é”原è¯ï¼Œé™¤éžäº’æ–¥é”çš„ä¸¥æ ¼è¯ä¹‰ä¸åˆé€‚,和/或临界区 阻æ¢é”被共享。