Bash

如果作為 init 呼叫,為什麼不能 bash 映射 ^C 到 intr 信號?

  • March 27, 2022

如果我將 bash 作為呼叫的第一個程序(即作為 init),結果它將顯示以下內容:

init: cannot set terminal process group (-1): Inappropriate ioctl for device
init: no job control in this shell

並且沒有信號(例如^C,^Z)起作用。

通過閱讀bash-5.1.12的源碼,問題出在job.c4501行的表達式:

(t = tcgetpgrp (shell_tty)) == -1

錯誤值為ENOTTY,表示呼叫程序沒有控制終端。

為什麼 Bash 在作為 init 呼叫時沒有控制終端?

控制終端由(實際上最初由,然後 getty execute )bash準備(打開)。因此,如果直接呼叫為 init skiping ,它會在上面拋出這個問題,因為控制終端在處理信號方面起著特殊的作用。login``getty``login``bash``login

根據源碼login.c(in ), inutil-linux的呼叫過程大致如下:bash``login

  1. main() 呼叫 fork_session()
/*
* Detach the controlling terminal, fork, and create a new session
* and reinitialize syslog stuff.
*/
fork_session(&cxt);
  1. 分叉一個新程序。(在fork_session()功能中)
child_pid = fork();
  1. 使新流程成為會話負責人。 為了獲得控制終端,該程序必須先成為會話領導者。(在fork_session()功能中)
/* start new session */
setsid();
  1. **獲取會話負責人的控制 tty。**會話領導者通過opentty 獲取控制終端。(在fork_session()功能中)
/* make sure we have a controlling tty */
open_tty(cxt->tty_path);
  1. 在新程序中執行登錄 shell。(返回main()
/* if the shell field has a space: treat it like a shell script */
if (strchr(pwd->pw_shell, ' ')) {
  char *buff;

  xasprintf(&buff, "exec %s", pwd->pw_shell);
  child_argv[child_argc++] = "/bin/sh";
  child_argv[child_argc++] = "-sh";
  child_argv[child_argc++] = "-c";
  child_argv[child_argc++] = buff;
} else {
  char tbuf[PATH_MAX + 2], *p;

  tbuf[0] = '-';
  xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ?
              p + 1 : pwd->pw_shell), sizeof(tbuf) - 1);

  child_argv[child_argc++] = pwd->pw_shell;
  child_argv[child_argc++] = xstrdup(tbuf);
}

child_argv[child_argc++] = NULL;

/* http://www.linux-pam.org/Linux-PAM-html/adg-interface-by-app-expected.html#adg-pam_end */
(void) pam_end(cxt.pamh, PAM_SUCCESS|PAM_DATA_SILENT);

execvp(child_argv[0], child_argv + 1);

更多關於控制終端概念的連結:

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