Ctrl-C가 작동하지 않는 이유는 무엇입니까?

Ctrl-C가 작동하지 않는 이유는 무엇입니까?

Ctrlc완료하는 데 오랜 시간이 걸리는 프로세스를 중지하려고 쉘을 두 번 쳤습니다 .

^C두 번이나 반복됐지만 그 과정은 계속됐다.

Ctrlc평소처럼 프로세스를 종료하면 어떨까요 ?

답변1

프로세스는 다음을 선택할 수 있습니다.

  • 눌렀을 때 일반적으로 전송되는 SIGINT 신호를 무시 하거나 Ctrl-C(shell 에서처럼 trap '' INT) 자체 핸들러가 종료하지 않도록 결정하도록 합니다(또는 제 시간에 종료하지 못함).
  • SIGINT를 포그라운드 작업으로 보낸 문자가 다른 문자(예: stty int '^K'셸의 with) 였음을 터미널 장치에 알립니다.
  • stty -isig( 셸에서와 마찬가지로) 신호를 보내지 않도록 터미널 장치에 지시합니다 .

또는 중단할 수 없는 시스템 호출과 같이 중단할 수 없습니다.

Linux(비교적 새로운 커널 포함)에서는 프로세스가 무시하고 있는지 및/또는 알 수 있습니다.다루다SIGINT를 통해 출력 보기

$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ:   0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000

SIGINT는 2입니다. 위 SigIgn의 두 번째 비트는 1이며, 이는 SIGINT가 무시됨을 나타냅니다.

다음을 통해 이를 자동화할 수 있습니다.

$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ && 
    $F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign

intr현재 문자가 무엇인지 또는 isig특정 터미널에 대해 활성화 되어 있는지 확인하려면 다음을 수행하십시오 .

$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig

(위 문자는 intr( 보통 ) ^C눌려지면 터미널(에뮬레이터)에서 전송되며 입력 신호는 비활성화되지 않습니다.CTRL-C

$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig

( intr문자는 비활성화되어 있습니다 ^K) .isig/dev/pts/1

완전성을 기하기 위해 프로세스가 SIGINT 수신을 중지할 수 있는 다른 두 가지 방법이 있지만 일반적으로 볼 수 있는 방법은 아닙니다.

위에서 Ctrl+CSIGINT 신호는 프로세스의 모든 프로세스에 전송됩니다.터미널의 포그라운드 프로세스 그룹. 일반적으로 쉘은 프로세스를 프로세스 그룹(쉘에 매핑됨)에 배치합니다.일하다) 그리고 최종 장치에 어느 것이 있는지 알려줍니다.전망하나.

이제 프로세스는 다음을 수행할 수 있습니다.

  • 해당 프로세스 그룹을 떠나십시오. 다른 프로세스 그룹(현재 프로세스 그룹을 제외한 모든 프로세스 그룹)으로 이동하는 경우전망Ctrl-C1) 그러면 더 이상 SIGINT (또는 SIGTSTP, SIGQUIT와 같은 기타 키보드 관련 신호)를 수신하지 않습니다 . 그러나 터미널 장치에서 읽기(및 터미널 장치 설정에 따라 쓰기)를 시도하는 경우(백그라운드 프로세스처럼) 중단될 수 있습니다.

    예를 들어:

    perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
    

    중단할 수 없습니다 Ctrl-C. 위는 perl상위 프로세스 ID와 동일한 ID를 가진 프로세스 그룹에 참여하려고 시도합니다. 일반적으로 해당 ID를 가진 프로세스 그룹이 존재한다는 보장은 없습니다. 그러나 여기서 perl명령이 대화형 셸의 프롬프트에서 단독으로 실행되면 ppid는 셸의 프로세스가 되며 셸은 일반적으로 자체 프로세스 그룹에서 시작됩니다.

    명령이 아직 프로세스 그룹 리더(전경 프로세스 그룹의 리더)가 아닌 경우 새 프로세스 그룹을 시작하여 동일한 효과를 갖습니다.

    예를 들어, 쉘에 따르면,

    $ ps -j >&2 | perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10'
      PID  PGID   SID TTY          TIME CMD
    21435 21435 21435 pts/12   00:00:00 zsh
    21441 21441 21435 pts/12   00:00:00 ps
    21442 21441 21435 pts/12   00:00:00 perl
    

    같은 효과가 있을 것입니다. 포그라운드 프로세스 그룹에서 시작하지만 대부분의 쉘에서는 ps해당 그룹의 리더가 되므로(위 출력에서 ​​볼 수 있듯이 pgid는 및 pid임) 자체 프로세스 그룹을 시작할 수 있습니다.perlpspspsperlpsperl

  • 또는 포그라운드 프로세스 그룹을 변경할 수도 있습니다. 기본적으로 tty 장치에 SIGINT를 다른 프로세스 그룹으로 보내도록 지시합니다.Ctrl+C

    perl -MPOSIX -e 'tcsetpgrp(0,getppid) or die$!; sleep 5'
    

    거기에서 perl동일한 프로세스 그룹에 머물면서 포그라운드 프로세스 그룹의 ID가 상위 프로세스 ID와 동일하다는 것을 터미널 장치에 알립니다(위 참고 사항 참조).

관련 정보