Process

從子程序的角度來看,程序的父程序有什麼意義嗎?

  • November 6, 2019

在 POSIX 中,程序通過兩個基本層次結構相互“關聯”:

  1. 父程序和子程序的層次結構。
  2. 會話和程序組的層次結構。

使用者程序通過setpgidand對後者有很大的控制權setsid,但他們對前者的控制很少——父程序 ID 在程序產生時設置,並在父程序退出時由核心更改(通常為 PID 1 ),否則它不會改變。回想起來,我一直想知道親子關係到底有多重要。

到目前為止,我的理解總結如下:

  • 從父程序的角度來看,父子關係顯然很重要,因為各種系統呼叫,如waitsetpgid,只允許在子程序上使用。
  • 會話-組-程序關係對於所有程序來說顯然很重要,無論是會話領導者還是會話中的其他程序,因為系統呼叫就像kill對整個程序組進行操作一樣,setpgid只能用於在同一個會話中加入一個組,並且所有程序SIGHUP如果會話領導者退出,則會發送會話的前台程序組中的消息。
  • 更重要的是,從父母的角度來看,這兩個層次結構顯然是相關的,因為setsid只影響新的孩子並且setpgid只能對孩子使用,但從孩子的角度來看,它們似乎本質上是無關的(因為父母程序死亡沒有任何影響)在程序的組或會話上)。

然而,顯然沒有任何理由讓子程序關心其目前父程序是什麼。因此,我有以下問題:從子程序的角度來看,目前值是否getppid()具有任何重要性,除了可能確定其生成過程是否已經退出?


用另一種方​​式提出同樣的問題,想像同一個程序以兩種不同的方式從同一個父級產生兩次:

  1. 第一個孩子以通常的方式產生,fork()緊隨其後的是exec().
  2. 第二個子程序是間接產生的:父程序呼叫fork(),然後子程序呼叫fork(),而程序呼叫exec()。然後直接的孩子退出,所以孫子是孤立的,它的 PPID 被重新分配給 PID 1。

**在這個假設的場景中,假設所有其他條件都相同,任何合理的程序是否有任何理由表現出不同的行為?**到目前為止,我的結論似乎是“否”,因為會話保持不變,程序繼承的文件描述符也是如此……但我不確定。

注意:我不認為“獲取父 PID 與它通信”是該問題的有效答案,因為孤立程序通常不能依賴將其 PPID 設置為 1(某些系統將孤立程序的 PPID 設置為其他值),因此避免競爭條件的唯一方法是在分叉getpid() 之前通過呼叫獲取父程序 ID ,然後在子程序中使用該值。

當我看到這個問題時,我很感興趣,因為我知道我以前見過 getppid ……但我不記得在哪裡。所以,我轉向了一個我認為可能使用了每個 Linux 系統呼叫的項目,然後是一些:systemd。之後在GitHub 上進行搜尋,我發現了兩種用途,描繪了一些更一般的案例(還有一些其他用途,但它們更特定於 systemd):

  • sd-notify中。在某些情況下:systemd 需要知道服務何時啟動,以便它可以繼續啟動任何依賴它的服務。這通常是通過 C 程序通過sd_notify API完成的,這是守護程序告訴 systemd 其狀態的一種方式。

當然,如果您將 shell 腳本用作服務……呼叫 C 函式並不完全可行。因此,systemd 帶有systemd-notify 命令,它是 sd_notify API 的一個小包裝。一個問題:systemd 還需要知道發送消息的 PID。對於 systemd-notify,這將是它自己的 PID,這將是一個短暫的程序 ID,它會立即消失。沒用處。

你可能已經知道我要去哪裡了:systemd-notify 使用 getppid 來獲取父程序的 PID,因為這通常是實際的服務程序。簡而言之,短暫的 CLI 應用程序可以使用 getppid 代表父程序發送消息。

一旦我發現這一點,我就會想到另一個可能使用 getppid 的 unix 工具:polkit,它是一個程序身份驗證框架,用於控制發送 D-Bus 消息或執行特權應用程序等內容。(至少,我猜你已經看到了 polkit 的身份驗證代理顯示的 GUI 密碼提示。) polkit 包含一個名為的執行檔pkexec,它的使用有點像 sudo,除了現在 polkit 用於授權。現在,polkit 需要知道請求授權的程序的 PID……是的,你明白了,pkexec 使用 getppid 來找到它

(在看的時候,我還發現polkit 的 TTY 身份驗證代理也使用它。)

  • 這個有點不那麼有趣但仍然值得注意:如果父級在設置該標誌時已經死亡,則使用 getppid 來模擬 PR_SET_PDEATHSIG 。(該標誌只是一種讓孩子在父母去世時自動發送信號如 SIGKILL 的方式。)

引用自:https://unix.stackexchange.com/questions/545244