Bashのジョブ制御は、停止または終了したバックグラウンドジョブをどのように処理しますか?

Bashのジョブ制御は、停止または終了したバックグラウンドジョブをどのように処理しますか?

Linuxでは、bashジョブ制御メカニズムの内部構造を研究しながら、理解に小さな問題が発生しました。次のシナリオを考えてみましょう。

スクリプトはバックグラウンドで実行されます。
user@linux:~# ./script.sh &

同じスクリプトがフォアグラウンドで同時に実行される
user@linux:~# ./script.sh

これで、フォアグラウンドでスクリプトを 2 回目の実行中に、スクリプトの最初の実行がバックグラウンドジョブとして実行されます。これで、Bashは終了するまで前景プロセスのPIDを使用してブロック待機呼び出しを実行し、適切な情報を取得します。フォアグラウンドプロセスが終了すると、bashはすべてのバックグラウンドジョブのステータスを制御し、プロンプトに戻る前に各変更を通知します。これは通常「+b」というデフォルトの動作です。

しかし、「-b」という別のモードがあります。このモードでは、すべてのバックグラウンドジョブ状態の変更がbashにすぐに通知されます。私が理解しているように、これはSIGCHLD信号をバックグラウンドプロセスに送信する方法で行われます。しかし、bashはブロック待機呼び出しを実行しても、バックグラウンドプロセスを終了し、端末にメッセージを印刷する信号にどのように反応しますか?なぜなら、シグナルはユーザーモードに戻る前にのみ処理されるようです。
bash呼び出しは、現在のフォアグラウンドが終了するまでWNOHANGオプションを使用してループで待機しますか?

また、「-b」モードで実行すると、bashは端末のフォアグラウンドプロセスグループの一部でなくても端末に書き込むことができます。 sttyを使用して「tostop」オプションを設定しても、bashはフォアグラウンドプロセスグループに属さずに端末に書き込むことができます。 bash は端末制御プロセスグループの一部なので、特別な権限を得ますか?

私の理解に問題がある部分を理解できることを願っています。

ベストアンサー1

はい、ループで一緒にbash使用してくださいwaitpid()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残念ながら設定の有無についてはあまり申し上げません。stty しなければならないこれを行うシェルに影響します。

おすすめ記事