可重入
編輯在計算中,如果多個調用可以在多個處理器或單處理器系統上安全地并發運行,則計算機程序或子例程被稱為可重入,其中可重入過程可以在其執行過程中被中斷,然后安全地再次調用(重新 -entered) 在其先前的調用完成執行之前。 中斷可能是由內部操作(例如跳轉或調用)或外部操作(例如中斷或信號)引起的,這與遞歸不同,在遞歸中,新調用只能由內部調用引起。
該定義源自多道程序設計環境,在該環境中,多個進程可能同時處于活動狀態,并且控制流可能會被中斷中斷并轉移到中斷服務例程 (ISR) 或處理程序子例程。 處理程序使用的任何可能在觸發中斷時執行的子程序都應該是可重入的。 同樣,訪問共享數據的兩個處理器共享的代碼應該是可重入的。 通常,可通過操作系統內核訪問的子例程是不可重入的。 因此,中斷服務程序在它們可以執行的操作上是有限的; 例如,它們通常無法訪問文件系統,有時甚至無法分配內存。
這種重入的定義不同于多線程環境中的線程安全。 可重入子例程可以實現線程安全,但僅可重入可能不足以在所有情況下都是線程安全的。 相反,線程安全代碼不一定是可重入的。
用于可重入程序的其他術語包括可共享代碼。 可重入子例程有時在參考資料中標記為信號安全。 可重入程序通常是純程序。
背景
編輯可重入性與冪等性不同,在冪等性中,函數可以被調用不止一次,但生成的輸出與只被調用一次完全相同。 一般來說,一個函數根據一些輸入數據產生輸出數據(盡管通常兩者都是可選的)。 任何功能都可以隨時訪問共享數據。 如果任何功能都可以更改數據(并且沒有人跟蹤這些更改),則無法向共享數據的那些人保證該數據與之前的任何時間相同。
數據有一個特性叫做作用域,它描述了數據在程序中的什么地方可以被使用。 數據范圍是全局的(在任何函數的范圍之外并且具有不確定的范圍)或局部的(每次調用函數時創建并在退出時銷毀)。
本地數據不被任何例程共享,無論是否重新進入; 因此,它不影響重新進入。 全局數據在函數外部定義,可以被多個函數訪問,可以是全局變量的形式(所有函數之間共享的數據),也可以是靜態變量(同一函數的所有調用共享的數據)。 在面向對象的編程中,全局數據在類的范圍內定義并且可以是私有的,使其只能被該類的函數訪問。 還有實例變量的概念,其中類變量綁定到類實例。 由于這些原因,在面向對象的編程中,這種區別通常保留給類外部可訪問的數據(公共),以及獨立于類實例的數據(靜態)。
可重入不同于線程安全,但與線程安全密切相關。 函數可以是線程安全的,但仍然不可重入。 例如,一個函數可以用互斥鎖包裹起來(這避免了多線程環境中的問題),但是,如果在中斷服務例程中使用該函數,它可能會餓死等待第一次執行以釋放互斥鎖。 避免混淆的關鍵是可重入是指只有一個線程在執行。 這是一個從不存在多任務操作系統的時代開始的概念。
重入規則
編輯可重入代碼不能在沒有同步的情況下保存任何靜態或全局非常量數據。可重入函數可以使用全局數據。 例如,可重入中斷服務例程可以獲取一塊硬件狀態(例如,串行端口讀取緩沖區),這不僅是全局的,而且是易變的。 不過,不建議典型地使用靜態變量和全局數據,在某種意義上,除了同步的代碼部分,在這些變量中只應使用原子讀-修改-寫指令(對于一個 在執行此類指令期間中斷或發出信號)。 請注意,在 C 中,即使是讀或寫也不能保證是原子的; 它可能被分成幾個讀或寫。
內容由匿名用戶提供,本內容不代表www.gelinmeiz.com立場,內容投訴舉報請聯系www.gelinmeiz.com客服。如若轉載,請注明出處:http://www.gelinmeiz.com/198041/