bash 的作業控制如何處理停止或終止的後台作業?
在研究Linux下bash的作業控制機制的內部時,我遇到了一些理解問題。讓我們假設以下場景:
腳本在後台執行
user@linux:~# ./script.sh &
同時在前台執行相同的腳本
user@linux:~# ./script.sh
現在,在前台第二次執行腳本期間,腳本的第一次執行作為後台作業執行。Bash 現在使用前台程序的 PID 執行阻塞等待呼叫,直到它終止,然後它獲取相應的資訊。前台程序終止後,bash 控制所有後台作業的狀態,並在返回提示之前通知每個更改。這通常是稱為“+b”的預設行為。
但是還有另一種模式稱為“-b”。在這種模式下,bash 會立即通知每個後台作業狀態的變化。據我了解,這是通過後台程序發送信號 SIGCHLD 來完成的。但是 bash 如何對終止後台程序的信號做出反應並向終端列印一條消息,儘管它執行了一個阻塞等待呼叫。因為在我看來,信號只在返回使用者模式之前被處理。
bash 呼叫是否在循環中使用 WNOHANG 選項等待,直到目前前台終止?
此外,當在“-b”模式下執行時,bash 可以寫入終端,儘管它不屬於終端的前台程序組。即使我使用 stty 設置選項“tostop”,bash 也可以寫入終端,而不是前台程序組的一部分。bash 是否獲得任何特殊權限,因為它是終端控制程序組的一部分。
我希望,我能弄清楚我的理解問題在哪裡。
是的,在循環中
bash
使用waitpid()
with 。WNOHANG
你可以在中看到這個waitchld()``jobs.c
:static int waitchld (wpid, block) pid_t wpid; int block; {
…
do { /* We don't want to be notified about jobs stopping if job control is not active. XXX - was interactive_shell instead of job_control */ waitpid_flags = (job_control && subshell_environment == 0) ? (WUNTRACED|wcontinued) : 0; if (sigchld || block == 0) waitpid_flags |= WNOHANG;
…
if (block == 1 && queue_sigchld == 0 && (waitpid_flags & WNOHANG) == 0) { internal_warning (_("waitchld: turning on WNOHANG to avoid indefinite block")); waitpid_flags |= WNOHANG; } pid = WAITPID (-1, &status, waitpid_flags);
…
/* We have successfully recorded the useful information about this process that has just changed state. If we notify asynchronously, and the job that this process belongs to is no longer running, then notify the user of that fact now. */ if (asynchronous_notification && interactive) notify_of_job_status (); return (children_exited); }
該
notify_of_job_status()
函式只是寫入bash
程序的標準錯誤流。不幸的是,我不能說設置
tostop
withstty
是否會影響您在其中執行此操作的 shell。