現在、私はシェルを作っていて、実行するフォアグラウンドプロセスでうまく動作します。今私はバックグラウンドプロセスとジョブコントロールを実装しなければなりません。私はそれにどのようにアプローチすべきかについて正直に混乱しています。私はバックグラウンドでプロセスを実行したい場合、私は彼らのpgidを設定し、単にそれらを待つことはありませんが、私はそれらを収穫しようとするときに壁を打つ必要があることを理解...シェルでバックグラウンドプロセスを獲得するSIGCHLDのシグナルハンドラを作成するには?
私は2つの構造:そして
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;
重要な部分は、ジョブは、プロセス構造体のリンクリストで構成されていることで、私のバックグラウンドジョブのすべてが起こって表しジョブ構造体のグローバルリストがあることを処理します。
シェルアルゴリズムは一種の標準です。
シェル:
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を送信できることを意味します。厄介な点は、特定のジョブのすべてのプロセスが終了した場合、そのジョブをグローバルジョブリストから削除する必要があるということです。私はシグナルハンドラ中にfinsihesを実行しているforgroundプロセスがオフチャンスであるため、ここで私のSIGCHLDハンドラでwaitpid(-1、&ステータス、WNOHANG)のループを呼び出すことはできません。
これは、すべてのジョブのすべてのプロセスでwaitpid()を実行しなければならないことを意味します。これは、SIGCHLDを取得するとただちに非fgプロセスで待機するようになっていますか?
私は本当にコードを必要としませんが、これを行う良い方法についての説明です。
"シグナルハンドラ中に実行されているフォアグラウンドプロセスが現在実行中であることを示します。フォアグラウンドプロセスが終了したらどうなりますか?ちょうどそれを処理します。バックグラウンドリストには含まれないので、バックグラウンドプロセスではありません。 – kaylum
シグナルハンドラ中にプロセスが終了しても、 'sigaction'を使ってマスクすることができ、isrの後に他のプロセスシグナルハンドラを処理することができます – Anjaneyulu
遅い応答には残念です。しかし、kaylum、forgroundプロセスがforkの親がそれを待つ前にsighandlerで終了したら、forkpidがforkの後でforgroundプロセスのためにやっていることが永遠に止まるでしょうか? – ParadoxicalEnigma