什麼決定了可執行檔是否可以同時在不同的獨立進程中運作?

什麼決定了可執行檔是否可以同時在不同的獨立進程中運作?

我已經發布一個問題關於如何在wine下在多個進程中獨立運行一個可執行檔(一個PDF檢視器)(獨立意味著它們之間沒有通信,它不是並行計算)。我聽說有些公司的PDF編輯器(檢視器的增強版)不能做到這一點。

問題

  • 所以我想知道是什麼使得可執行檔能夠或不能在多個進程中獨立運行?
  • 它是由程式本身或某些程式庫實現的嗎?
  • 作業系統不能實現這一點嗎?

答案1

這幾乎肯定是由程式本身實現的,而且作業系統可能不可能強制執行除了最基本的程式之外的所有程式。

但是,如果您知道程式確定其已運行的方式,並且該方式是您可以影響的,那麼您確實可以獲得可執行檔來啟動新進程(或不啟動)。

有些應用程式使這變得特別容易,例如 Emacs。運行 Emacs 的標準方法是為每次呼叫啟動一個新進程。但您也可以在伺服器模式下明確運行 Emacs,然後emacsclient明確運行以告訴現有伺服器存取新檔案。

作為一個相反的範例,Firefox 提供了一個強制啟動新進程的命令列選項-no-remote,而預設設定是在可能的情況下與已執行的進程進行互動。

許多簡單的本土應用程式將透過簡單地查詢ps.這可以透過多種方式規避。工業強度軟體的問題在於,用戶幾乎永遠不知道特定應用程式如何決定它是否已在使用。即使在 Unix 上,您可以檢查與可執行文件互動的所有開啟文件,也不能保證您可以找出哪個文件(如果有的話)負責記錄應用程式正在運行的事實。

答案2

進程是程序的一個實例。一個程式可以被實例化多次,即可以創建多個進程並載入相同的可執行程式碼。我想引用一句了解 Linux 內核作者:丹尼爾‧P‧博維 (Daniel P. Bovet) 與馬可‧塞薩蒂 (Marco Cesati):

區分程序和進程很重要;多個行程可以執行同一個程式同時,而同一個行程可以執行多個程序依序地

基本上,這意味著雖然程式可以跑步在某些情況下,單一實例一次只能載入一個可執行程式碼。所以,從那裡開始,我們可以說沒有什麼防止程式運行到多個實例中,因為絕對沒有理由禁止它。當然,這些進程除了執行程式碼之外不會共享任何東西。記憶體頁、檔案描述符(可能涉及相同的檔案)等等......從一個進程到另一個進程完全獨立。

當談到類 Unix 系統時,另一點對我來說似乎很重要(同一本書):

類別Unix作業系統採用行程/核心模型每個進程都有一種錯覺,認為它是機器上唯一的進程,並且它具有對作業系統服務的獨佔存取權。

事實上,這就是 Unix 系統具有多處理/多道程式設計的原因,或者至少,這是該功能所基於的策略。因此,由於這個事實,進程無法天生就知道運行完全相同程式碼的另一個進程正在等待或在另一個 CPU 上工作。

然而,每個進程都知道一件事:系統由核心運行,並且核心的服務在進程在 CPU 上工作的所有時間內都由進程使用。由於這一點,一個進程可以詢問關於作為同一可執行檔的實例運行的其他進程的核心。我想到的第一個解決方案是讀取/proc虛擬檔案系統。該檔案系統的作用就像用戶/應用程式和核心之間的介面(因為這些檔案代表核心結構和資料)。在此檔案系統中,每個進程都有一個目錄(以其 PID 命名),在該目錄中,您將找到一個名為exe.例如,這是我的bash進程目錄,PID 22343:

lrwxrwxrwx /proc/22343/exe -> /bin/bash*

現在,透過瀏覽檔案系統,您將能夠找到運行相同可執行程式碼的進程,即連結exe針對相同可執行檔的進程。

然而,由於所有 Unix 系統的實現方式並不/proc相同,開發人員的目標是使用更便攜的解決方案,該解決方案依賴於幾乎所有 Unix 系統都理解的東西:常規文件。這就是.pid文件通常放在這裡的目的。

大多數時候,您會在/run.例如:

-rw-r--r-- /run/acpid.pid
-rw-r--r-- /run/atd.pid
-rw-r--r-- /run/crond.pid

這些檔案由它們所屬的應用程式創建,並用作程式實例是否正在運行的標記。通常,該檔案的內容僅由正在執行的進程的 PID 組成。在本例中,我有一個acpid正在運行的進程,PID 為 1503,這正是 PID 檔案中的內容。

現在,由於同一程式的所有進程共享相同的執行程式碼,因此它們共享它們的常數(至少是它們的值)。因此,如果每個實例都知道在哪裡查找 PID 文件,那麼編寫單一實例程式就非常容易了:

if (the pid file exists) then
    send a signal to the running process or just bring it on the foreground
    exit since the work is going to be handled by the already-running process
else
    actually start the program, the first instance
endif

在第一種情況下使用訊號是我見過最多的行為,但是,如果您的應用程式使用一些更複雜的IPC(套接字、訊息佇列等),您可以使用它來通知它使用者已請求某些內容它需要做。

相關內容