.. SPDX-License-Identifier: GPL-2.0 .. _tw_volatile_considered_harmful: .. include:: ../disclaimer-zh_TW.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> 胡皓文 Hu Haowen <src.res.211@gmail.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] https://lwn.net/Articles/233481/ [2] https://lwn.net/Articles/233482/ è‡´è¬ ---- 最åˆç”±Randy Dunlap推動並作åˆæ¥ç ”究 ç”±Jonathan Corbet撰寫 åƒè€ƒSatyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila, H. Peter Anvin,Philipp Hahnå’ŒStefan Richterçš„æ„見改善了本檔。