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

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

나는 Ctrlc완료하는 데 오랜 시간이 걸리는 프로세스를 중단하기 위해 껍질을 두 번 쳤습니다.

^C두 번 울렸지만 프로세스는 계속 진행되었습니다.

Ctrlc평소처럼 프로세스를 종료 하지 않은 이유는 무엇입니까 ?

답변1

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

  • 일반적으로 누를 때 전송되는 SIGINT 신호를 무시 하거나 Ctrl-C(셸에서와 같이 trap '' INT) 종료하지 않기로 결정하는(또는 적시에 종료하지 못하는) 자체 핸들러를 갖습니다.
  • SIGINT를 포그라운드 작업으로 보내는 문자가 다른 것(예: stty int '^K'쉘의 경우) 이라는 것을 터미널 장치에 알립니다.
  • 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 신호가 해당 프로세스의 모든 프로세스에 전송됩니다.터미널의 포그라운드 프로세스 그룹. 일반적으로 프로세스 그룹에 프로세스를 배치하는 쉘입니다(쉘에 매핑됨).직업) 그리고 터미널 장치에전경하나.

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

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

    예로서:

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

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

    명령이 아직 프로세스 그룹 리더(해당 포그라운드 프로세스 그룹의 리더)가 아닌 경우 새 프로세스 그룹을 시작하는 것은 동일한 효과를 갖습니다.

    예를 들어, 쉘에 따라,

    $ 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
    

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

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

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

    동일한 프로세스 그룹에 남아 있지만 perl대신 터미널 장치에 전경 프로세스 그룹의 ID가 상위 프로세스 ID와 동일한 그룹임을 알려줍니다(위의 참고 사항 참조).

관련 정보