.. _cn_volatile_considered_harmful: .. include:: ../disclaimer-zh_CN.rst :Original: :ref:`Documentation/process/volatile-considered-harmful.rst <volatile_considered_harmful>` 如果想评论或更新本文的内容,请直接è”ç³»åŽŸæ–‡æ¡£çš„ç»´æŠ¤è€…ã€‚å¦‚æžœä½ ä½¿ç”¨è‹±æ–‡ 交æµæœ‰å›°éš¾çš„è¯ï¼Œä¹Ÿå¯ä»¥å‘ä¸æ–‡ç‰ˆç»´æŠ¤è€…求助。如果本翻译更新ä¸åŠæ—¶æˆ–者翻 译å˜åœ¨é—®é¢˜ï¼Œè¯·è”ç³»ä¸æ–‡ç‰ˆç»´æŠ¤è€…:: 英文版维护者: Jonathan Corbet <corbet@lwn.net> ä¸æ–‡ç‰ˆç»´æŠ¤è€…: ä¼é¹ Bryan Wu <bryan.wu@analog.com> ä¸æ–‡ç‰ˆç¿»è¯‘者: ä¼é¹ Bryan Wu <bryan.wu@analog.com> ä¸æ–‡ç‰ˆæ ¡è¯‘者: å¼ æ±‰è¾‰ Eugene Teo <eugeneteo@kernel.sg> æ¨ç‘ž Dave Young <hidave.darkstar@gmail.com> 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> 为什么ä¸åº”该使用“volatileâ€ç±»åž‹ ============================== C程åºå‘˜é€šå¸¸è®¤ä¸ºvolatile表示æŸä¸ªå˜é‡å¯ä»¥åœ¨å½“å‰æ‰§è¡Œçš„线程之外被改å˜ï¼›å› æ¤ï¼Œåœ¨å†…æ ¸ ä¸ç”¨åˆ°å…±äº«æ•°æ®ç»“构时,常常会有C程åºå‘˜å–œæ¬¢ä½¿ç”¨volatile这类å˜é‡ã€‚æ¢å¥è¯è¯´ï¼Œä»–ä»¬ç» å¸¸ä¼šæŠŠvolatile类型看æˆæŸç§ç®€æ˜“的原åå˜é‡ï¼Œå½“然它们ä¸æ˜¯ã€‚åœ¨å†…æ ¸ä¸ä½¿ç”¨volatileå‡ ä¹Žæ€»æ˜¯é”™è¯¯çš„ï¼›æœ¬æ–‡æ¡£å°†è§£é‡Šä¸ºä»€ä¹ˆè¿™æ ·ã€‚ ç†è§£volatile的关键是知é“它的目的是用æ¥æ¶ˆé™¤ä¼˜åŒ–,实际上很少有人真æ£éœ€è¦è¿™æ ·çš„应 ç”¨ã€‚åœ¨å†…æ ¸ä¸ï¼Œç¨‹åºå‘˜å¿…须防æ¢æ„外的并å‘è®¿é—®ç ´å共享的数æ®ç»“构,这其实是一个完全 ä¸åŒçš„任务。用æ¥é˜²æ¢æ„外并å‘访问的ä¿æŠ¤æŽªæ–½ï¼Œå¯ä»¥æ›´åŠ 高效的é¿å…大多数优化相关的 问题。 åƒvolatileä¸€æ ·ï¼Œå†…æ ¸æ供了很多原è¯æ¥ä¿è¯å¹¶å‘访问时的数æ®å®‰å…¨ï¼ˆè‡ªæ—‹é”, 互斥é‡,内 å˜å±éšœç‰ç‰ï¼‰ï¼ŒåŒæ ·å¯ä»¥é˜²æ¢æ„外的优化。如果å¯ä»¥æ£ç¡®ä½¿ç”¨è¿™äº›å†…æ ¸åŽŸè¯ï¼Œé‚£ä¹ˆå°±æ²¡æœ‰ å¿…è¦å†ä½¿ç”¨volatile。如果ä»ç„¶å¿…须使用volatileï¼Œé‚£ä¹ˆå‡ ä¹Žå¯ä»¥è‚¯å®šåœ¨ä»£ç çš„æŸå¤„有一 个bug。在æ£ç¡®è®¾è®¡çš„å†…æ ¸ä»£ç ä¸ï¼Œvolatile能带æ¥çš„仅仅是使事情å˜æ…¢ã€‚ æ€è€ƒä¸€ä¸‹è¿™æ®µå…¸åž‹çš„å†…æ ¸ä»£ç :: spin_lock(&the_lock); do_something_on(&shared_data); do_something_else_with(&shared_data); spin_unlock(&the_lock); 如果所有的代ç 都éµå¾ªåŠ é”规则,当æŒæœ‰the_lock的时候,ä¸å¯èƒ½æ„外的改å˜shared_dataçš„ 值。任何å¯èƒ½è®¿é—®è¯¥æ•°æ®çš„其他代ç 都会在这个é”上ç‰å¾…。自旋é”原è¯è·Ÿå†…å˜å±éšœä¸€æ ·â€”— 它 们显å¼çš„用æ¥ä¹¦å†™æˆè¿™æ · —— æ„味ç€æ•°æ®è®¿é—®ä¸ä¼šè·¨è¶Šå®ƒä»¬è€Œè¢«ä¼˜åŒ–。所以本æ¥ç¼–译器认为 它知é“在shared_data里é¢å°†æœ‰ä»€ä¹ˆï¼Œä½†æ˜¯å› 为spin_lock()调用跟内å˜å±éšœä¸€æ ·ï¼Œä¼šå¼ºåˆ¶ç¼– 译器忘记它所知é“的一切。那么在访问这些数æ®æ—¶ä¸ä¼šæœ‰ä¼˜åŒ–的问题。 如果shared_data被声å为volatile,é”æ“作将ä»ç„¶æ˜¯å¿…须的。就算我们知é“没有其他人æ£åœ¨ 使用它,编译器也将被阻æ¢ä¼˜åŒ–对临界区内shared_data的访问。在é”有效的åŒæ—¶ï¼Œ shared_dataä¸æ˜¯volatile的。在处ç†å…±äº«æ•°æ®çš„时候,适当的é”æ“作å¯ä»¥ä¸å†éœ€è¦ volatile —— 并且是有潜在å±å®³çš„。 volatileçš„å˜å‚¨ç±»åž‹æœ€åˆæ˜¯ä¸ºé‚£äº›å†…å˜æ˜ å°„çš„I/O寄å˜å™¨è€Œå®šä¹‰ã€‚åœ¨å†…æ ¸é‡Œï¼Œå¯„å˜å™¨è®¿é—®ä¹Ÿåº” 该被é”ä¿æŠ¤ï¼Œä½†æ˜¯äººä»¬ä¹Ÿä¸å¸Œæœ›ç¼–译器“优化â€ä¸´ç•ŒåŒºå†…的寄å˜å™¨è®¿é—®ã€‚å†…æ ¸é‡ŒI/O的内å˜è®¿é—® 是通过访问函数完æˆçš„ï¼›ä¸èµžæˆé€šè¿‡æŒ‡é’ˆå¯¹I/O内å˜çš„直接访问,并且ä¸æ˜¯åœ¨æ‰€æœ‰ä½“系架构上 都能工作。那些访问函数æ£æ˜¯ä¸ºäº†é˜²æ¢æ„å¤–ä¼˜åŒ–è€Œå†™çš„ï¼Œå› æ¤ï¼Œå†è¯´ä¸€æ¬¡ï¼Œvolatileç±»åž‹ä¸ æ˜¯å¿…éœ€çš„ã€‚ å¦ä¸€ç§å¼•èµ·ç”¨æˆ·å¯èƒ½ä½¿ç”¨volatile的情况是当处ç†å™¨æ£å¿™ç€ç‰å¾…一个å˜é‡çš„值。æ£ç¡®æ‰§è¡Œä¸€ 个忙ç‰å¾…的方法是:: while (my_variable != what_i_want) cpu_relax(); cpu_relax()调用会é™ä½ŽCPU的能é‡æ¶ˆè€—或者让ä½äºŽè¶…线程åŒå¤„ç†å™¨ï¼›å®ƒä¹Ÿä½œä¸ºå†…å˜å±éšœä¸€æ ·å‡º 现,所以,å†ä¸€æ¬¡ï¼Œvolatileä¸æ˜¯å¿…需的。当然,忙ç‰å¾…一开始就是一ç§å常规的åšæ³•ã€‚ åœ¨å†…æ ¸ä¸ï¼Œä¸€äº›ç¨€å°‘的情况下volatileä»ç„¶æ˜¯æœ‰æ„义的: - 在一些体系架构的系统上,å…许直接的I/0内å˜è®¿é—®ï¼Œé‚£ä¹ˆå‰é¢æ到的访问函数å¯ä»¥ä½¿ç”¨ volatile。基本上,æ¯ä¸€ä¸ªè®¿é—®å‡½æ•°è°ƒç”¨å®ƒè‡ªå·±éƒ½æ˜¯ä¸€ä¸ªå°çš„临界区域并且ä¿è¯äº†æŒ‰ç…§ 程åºå‘˜æœŸæœ›çš„é‚£æ ·å‘生访问æ“作。 - æŸäº›ä¼šæ”¹å˜å†…å˜çš„内è”汇编代ç 虽然没有什么其他明显的附作用,但是有被GCCåˆ é™¤çš„å¯ èƒ½æ€§ã€‚åœ¨æ±‡ç¼–å£°æ˜Žä¸åŠ 上volatile关键å—å¯ä»¥é˜²æ¢è¿™ç§åˆ 除æ“作。 - Jiffieså˜é‡æ˜¯ä¸€ç§ç‰¹æ®Šæƒ…况,虽然æ¯æ¬¡å¼•ç”¨å®ƒçš„时候都å¯ä»¥æœ‰ä¸åŒçš„值,但读jiffies å˜é‡æ—¶ä¸éœ€è¦ä»»ä½•ç‰¹æ®Šçš„åŠ é”ä¿æŠ¤ã€‚所以jiffieså˜é‡å¯ä»¥ä½¿ç”¨volatile,但是ä¸èµžæˆ 其他跟jiffies相åŒç±»åž‹å˜é‡ä½¿ç”¨volatile。Jiffies被认为是一ç§â€œæ„šè ¢çš„é—留物" (Linusçš„è¯ï¼‰å› 为解决这个问题比ä¿æŒçŽ°çŠ¶è¦éº»çƒ¦çš„多。 - 由于æŸäº›I/0设备å¯èƒ½ä¼šä¿®æ”¹è¿žç»ä¸€è‡´çš„内å˜,所以有时,指å‘è¿žç»ä¸€è‡´å†…å˜çš„æ•°æ®ç»“æž„ 的指针需è¦æ£ç¡®çš„使用volatile。网络适é…器使用的环状缓å˜åŒºæ£æ˜¯è¿™ç±»æƒ…形的一个例 å,其ä¸é€‚é…器用改å˜æŒ‡é’ˆæ¥è¡¨ç¤ºå“ªäº›æ述符已ç»å¤„ç†è¿‡äº†ã€‚ 对于大多代ç ï¼Œä¸Šè¿°å‡ ç§å¯ä»¥ä½¿ç”¨volatile的情况都ä¸é€‚用。所以,使用volatileæ˜¯ä¸€ç§ bug并且需è¦å¯¹è¿™æ ·çš„代ç é¢å¤–仔细检查。那些试图使用volatileçš„å¼€å‘人员需è¦é€€ä¸€æ¥æƒ³æƒ³ 他们真æ£æƒ³å®žçŽ°çš„是什么。 éžå¸¸æ¬¢è¿Žåˆ 除volatileå˜é‡çš„è¡¥ä¸ ï¼ åªè¦è¯æ˜Žè¿™äº›è¡¥ä¸å®Œæ•´çš„考虑了并å‘问题。 注释 ---- [1] http://lwn.net/Articles/233481/ [2] http://lwn.net/Articles/233482/ 致谢 ---- 最åˆç”±Randy Dunlap推动并作åˆæ¥ç ”究 ç”±Jonathan Corbet撰写 å‚考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila, H. Peter Anvin,Philipp Hahnå’ŒStefan Richterçš„æ„è§æ”¹å–„了本档。