터미널의 입력이 bash 프로세스를 통해 현재 실행 중인 프로그램으로 라우팅됩니까, 아니면 터미널이 bash 프로세스에서 "연결이 끊어지고" 새 프로그램에 연결되어 bash가 가로채거나 간섭하는 것을 방지합니까?
Bash는 백그라운드에서 정지되어 프로그램 종료를 기다리고 있습니까, 아니면 뭔가를 하고 있습니까?
터미널 창을 닫을 때 bash에 신호를 보내고 포그라운드 프로세스에 신호를 보내 닫도록 합니까? 아니면 bash까지 전파되는 포그라운드 프로세스에 신호를 보내나요?
답변1
터미널의 입력이 bash 프로세스를 통해 현재 실행 중인 프로그램으로 라우팅됩니까, 아니면 터미널이 bash 프로세스에서 "연결이 끊어지고" 새 프로그램에 연결되어 bash가 가로채거나 간섭하는 것을 방지합니까?
어느 것도 아니다. 파이프나 리디렉션이 없는 간단한 포그라운드 명령을 가정하면... 사용자의 입력과 사용자로의 출력은 bash를 통해 라우팅되지 않습니다. 그러나 bash는 간섭을 차단하지 않습니다. bash는 단순히 차단되지 않습니다.노력하다간섭.
프로그램이 파일이나 터미널을 열면 읽고 쓰기 위한 파일 설명자를 받습니다. 하위 프로세스는 상위 프로세스의 열린 파일 설명자 세트 사본을 상속합니다.
터미널에 무언가를 입력하면 표준 입력을 통해 프로세스에 전달됩니다. 사용자에게 쓸 때 stdout 또는 stderr에 씁니다. Stdin, stdout 및 stderr은 모두 예측 가능한 ID를 가진 파일 설명자입니다. POSIX 표준에 따라 각각 0 1 2로 번호가 지정됩니다. 따라서 Bash가 프로그램을 실행할 때 먼저 하위 프로세스를 생성합니다.십자가그리고 하위 프로세스는 동일한 stdin, stdout 및 stderr FD를 자동으로 상속합니다. 따라서 자식은 자동으로 정확히 동일한 터미널을 읽고 씁니다.
"프로그램 실행"은 다음을 호출하여 수행됩니다.십자가그 다음에구현하다. 파이프 및 리디렉션은 대체 stdin, stdout 및 stderr을 호출하여 구현됩니다.듀프 2포크와 execve 사이.
따라서 "프로그램"은 bash와 동일한 터미널에서 직접 읽을 수 있습니다. 이것은 bash나 다른 것이 동일한 터미널에서 읽고 쓰는 것을 막지는 않습니다. Bash가 실제로 이 작업을 수행하려고 하면 혼란이 발생할 수 있습니다. 다중 프로세스 쓰기로 인해 모든 것이 예측할 수 없는 순서로 기록될 수 있습니다. 여러 프로세스에서 읽으면 일부 바이트(키 입력)가 한 프로세스로 이동하고 다른 바이트는 다른 프로세스로 이동됩니다.
Bash는 백그라운드에서 정지되어 프로그램 종료를 기다리고 있습니까, 아니면 뭔가를 하고 있습니까?
효과적으로 동결됩니다. 더 정확하게 말하면 기다리고 있다. 내가 아는 한 그것은 명시적으로 호출한다.waitpid()
또는 wait3()
(셸을 실행 중인 Unix에 따라) 하위 프로세스가 종료될 때까지 기다립니다.
터미널 창을 닫을 때 bash에 신호를 보내고 포그라운드 프로세스에 신호를 보내 닫도록 합니까? 아니면 bash까지 전파되는 포그라운드 프로세스에 신호를 보내나요?
죄송합니다. 이 동작이 바로 기억나지 않습니다. 나는 터미널 [창]을 닫으면 일반적으로 아무것도 읽거나 쓰지 않더라도 실행 중인 프로세스를 종료한다고 생각합니다.나는 그것이 EOF를 유발하는 터미널 판독을 기반으로 한다고 믿지 않습니다.. 터미널 폐쇄로 인해신호. 정답을 찾으면 답변을 수정하겠습니다.
나는 어떤 아이들이 키보드 인터럽트 키 시퀀스를 효과적으로 가로채서 bash가 키 시퀀스를 수신하지 못하도록 방지할 수 있다는 것을 알고 있습니다. 이것이 신호를 가로채는 것인지 아니면 터미널이 신호를 모두 생성하지 못하게 하는 것인지 확실하지 않습니다.
답변2
아직 묻지 않은 질문은 다음과 같습니다. 프로세스를 비동기적으로( & 사용하여) 시작하면 어떻게 되며 이것이 & 없이 명령을 입력하는 것과 다른 이유는 무엇입니까?
여기서 중요한 것은 '상속'이다. 대화형 셸이 아무 작업도 하지 않으면 프롬프트(PS1 변수)를 표시하고 표준 입력을 읽습니다. 창 관리자에는 시작할 때 쉘과 통신하기 위해 생성하는 스트림에 쓸 키 입력이 없기 때문에 정지됩니다.
명령 이름을 입력하면 쉘은 자체적으로 "포크"(복사)하고 하위 프로세스는 쉘에서 stdin, stdout, stderr을 상속합니다. 그런 다음 서브쉘은 커널에게 명령을 자체적으로 로드하라고 지시합니다("execve").
문제는 이제 창 관리자에 동일한 스트림을 읽는 두 개의 프로세스, 즉 원래 셸과 하위 명령이 있다는 것입니다. 무엇을 해야 할까요? 다음에 당신이 입력하는 내용을 누가 읽을 것인가?
동기화된 "전경" 하위 항목의 경우 하위 명령이 데이터를 가져와야 합니다. 따라서 쉘은 stdin에서 읽히지 않습니다. 대신, 하위 프로세스가 종료되고 해당 종료 상태를 사용할 수 있을 때 절전 모드로 전환되고 SIGCHLD에 의해 깨어날 것으로 예상됩니다. 따라서 두 번째 전경 하위 프로세스를 시작하라고 지시할 방법이 없습니다.
비동기 "백그라운드" 하위 프로세스의 경우 하위 프로세스는 표준 입력 연결이 끊어진 상태에서 포크(/dev/null에 연결)됩니다. Stdout과 stderr은 여전히 연결되어 있으므로(리디렉션되지 않는 한) 비동기 프로세스는 여전히 터미널로 보낼 수 있습니다(회선 동기화는 무작위일 수 있음). 그러면 쉘은 프롬프트를 표시하고 다음 명령(예: "jobs")을 기다립니다. 다른 비동기 프로세스를 시작하거나, 한 번에 하나의 명령을 실행하거나, 내장된 셸 명령을 처리할 수 있으므로 많은 백그라운드 작업을 동시에 수행할 수 있습니다. 각 비동기 하위 프로세스가 종료되면 여전히 SIGCHLD를 수신하고 상태를 수집하고 작업 목록에서 제거하는 등의 작업을 할 수 있습니다.
터미널을 닫으면 쉘이 창 입력을 가져온 스트림에서 EOF를 얻는 것으로 의심됩니다. 각 하위 항목이 시작될 때 설정되는 내부 목록을 사용하여 모든 하위 항목을 종료합니다.
답변3
이해해야 할 중요한 차이점은 터미널과 셸 사이입니다. 터미널은 컴퓨터 화면에서 명령을 입력하고, 텍스트를 읽고, 프로그램 출력을 수신하는 데 사용하는 인터페이스입니다. 반면에 Shell은 커널과 상호 작용하여 프로그램 실행을 담당하는 개체입니다.
터미널이 "멈추지" 않습니다. 쉘이 프로세스를 완료할 때까지 "대기"하는 동안에는 새 프롬프트를 표시하지 않습니다. 동일한 시스템에서 여러 터미널을 사용할 수 있습니다(이것이 우리 tmux
가 할 수 있는 것입니다!).
터미널에서 명령을 입력하거나 프로그램을 실행하면 터미널은 키 입력을 구문 분석하여 셸에 전달합니다. 그런 다음 입력을 구문 분석하여 프로세스를 실행합니다. 입력이 셸에 전달되면 터미널이 작업을 완료한 것입니다. 이제 수행할 작업은 스크립트가 완료될 때까지 기다리는 것뿐입니다.
이 설명은 마지막 질문에도 답이 될 것입니다. 터미널 화면을 닫으면 이 신호가 현재 실행 중인 프로그램에 전파되어 종료됩니다.