簡體   English   中英

如何為SIGCHLD制作信號處理程序,以便在shell中獲得后台進程?

[英]How to make a signal handler for SIGCHLD that will reap background processes in shell?

目前我正在制作一個shell,它適用於它執行的前台進程。 現在我必須實現后台進程和作業控制,我真的很困惑我應該如何處理它。 我明白,如果我想在后台運行proccesses,我應該設置他們的pgid而不是等待它們,但是當我試圖收獲它們時我碰到了牆...

我有兩個結構:工作和流程

typedef struct job {
    int is_background_job;
    pid_t pgid;
    int job_status;
    process *p;         // List of processes to execute for this job
    struct job *next;   // If a background job, it will be in a global linked list of job structs 
} job;

typedef struct process {
    char **argv;
    process *next;      // The next process to pipe to
} process;

重要的一點是,作業由一個過程結構的鏈接列表組成,並且有一個全局的作業結構列表,代表我正在進行的所有后台作業。

shell算法是一種標准。

貝殼:

get cmd from terminal
parse cmd and create a job struct filled with processes
if job is a background job:
  add it to global background job list
fork(), setpgid, and do the piping in a while loop of the job's processes   
if job is a foreground process:
  wait on the forked processes
else:
  don't wait // since it's a background process
continue to loop and read next cmd from terminal

現在這是我的問題。 如果我有一堆正在后台執行的進程,這意味着它們中的任何一個(來自任何一個后台作業)都可以簡單地結束然后發送SIGCHLD。 令人討厭的部分是,如果某個作業的所有進程都結束,我必須從全局作業列表中刪除該作業。 我不認為我可以在我的SIGCHLD處理程序中調用waitpid(-1,&status,WNOHANG)的循環,因為在信號處理程序中,forground進程當前正在執行finsihes的可能性很小。

這是否意味着我必須在獲得SIGCHLD后立即對每個作業的每個進程進行waitpid()以便我只等待非fg進程?

我真的不需要代碼,只是解釋一個很好的方法來做到這一點。

我知道現在這已經很晚了,可能對你來說無關緊要,但我也正在研究一個shell,並試圖找出同樣的問題時遇到了你的問題。

無論如何,似乎這里的問題是讓主進程等待所有前台子進程,但是這很難對SIGCHLD處理程序中的waitpid進行調用。 我是如何做到這一點的,而不是在主進程中使用wait()調用,我只是在處理程序中獲取所有進程並從適當的列表中刪除它們(我目前有一個所有前台進程的列表和所有后台進程的列表) ,然后在主要過程中我做了:

while(foreground process list is not empty)
    pause();

pause()調用只是將進程置於睡眠狀態,直到被信號喚醒為止,在這種情況下, SIGCHLD將始終喚醒進程,以便再次檢查是否還有正在運行的前台進程需要等待。 希望這有助於某人!

編輯:剛剛意識到這可能會導致競爭條件,如果孩子在您檢查列表不為空之后立即終止,並且在您調用pause() 簡單的方法是只使用nanosleep而不是暫停,它仍然會被信號中斷,但是你可以選擇定期檢查列表大小,這樣可以避免在這種情況下的競爭條件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM