Tại sao Ctrl-C không tự giết Terminal?


39

Thiết bị đầu cuối đang chạy khi chúng tôi mở nó.

luvpreet@DHARI-Inspiron-3542:/$

Tôi vừa mở nó. Vì vậy, khi tôi nhấn Ctrl+ C, tại sao nó không tự chết và đóng thiết bị đầu cuối ??


21
thiết bị đầu cuối không chạy trong thiết bị đầu cuối ;-)
Pilot6

3
liên quan đến lý do tại sao control-d hoạt động: unix.stackexchange.com/a/110248/14305
Janus Troelsen

Câu trả lời:


48

Ctrl+ Clà tín hiệu ngắt. Khi bạn nhập cái này vào một thiết bị đầu cuối, bash sẽ gửi SIGINT cho công việc ở phía trước. Nếu không có việc làm (đó là trường hợp khi bạn vừa mở một thiết bị đầu cuối), không có gì xảy ra. Chương trình giả lập thiết bị đầu cuối không phải là một công việc chạy trong shell, vì vậy, nó không nhận được tín hiệu và không đóng.

Nếu bạn muốn đóng thiết bị đầu cuối bằng phím điều khiển, hãy sử dụng Ctrl+ D(EOF) khiến bash thoát (và cũng đóng thiết bị đầu cuối).

Xem thêm: Hướng dẫn về tín hiệu của Bash cho người mới bắt đầu và chuyên sâu hơn Cách xử lý tín hiệu hoạt động
lưu ý: câu trả lời này đã được chỉnh sửa kể từ khi bình luận được đăng


4
Thuật ngữ thích hợp là vỏ sẽ "bẫy" tín hiệu. Câu chuyện khác nhau là khi bạn khởi chạy một cửa sổ đầu cuối từ bên trong một cửa sổ khác. Gửi ctrl + c đến cửa sổ cha sẽ giết tiến trình con.
Sergiy Kolodyazhnyy

1
Ngoài ra, các cửa sổ GUI cũng có thể được hướng dẫn để bẫy các tín hiệu cụ thể đến từ máy chủ X11. Đó là cách bạn có thể có các cửa sổ bật lên thông báo cho bạn về công việc chưa được lưu hoặc mở các tab như trong trình duyệt
Sergiy Kolodyazhnyy

8
@chrylis chương trình đầu cuối chỉ gửi ký tự ctrl-c, đây thực sự là lớp tty kernel biến nó thành tín hiệu.
Random832

3
@chrylis: Và thiết bị đầu cuối, hoặc một chương trình chạy bên trong nó - ví dụ như trình soạn thảo văn bản - cũng có thể dịch Ctl-C sang một số hành động khác.
jamesqf

3
Tôi không nghĩ bashsẽ chấm dứt bất kỳ chương trình nào khi nhấn ctrl-c. Nó sẽ chỉ cho kernel biết nhóm quá trình nào đang hoạt động và kernel sẽ tạo tín hiệu cho nhóm quy trình đó khi nhận được ctrl-c từ chương trình đầu cuối.
kasperd

32

Tổ ^Chợp phím, giống như các tổ hợp phím khác *, không phải là phép thuật - nó sẽ gửi một mã khóa đến bất kỳ chương trình nào có trọng tâm. (Trong X, mã khóa là 54 đối Cvới công cụ sửa đổi là 0x4 Ctrl.) Chương trình nhận luồng khóa có trách nhiệm thực hiện điều gì đó phù hợp với chúng - hãy nhớ rằng trong nhiều ứng dụng GUI, tổ hợp phím sẽ sao chép vào bảng tạm.

Khi trình giả lập thiết bị đầu cuối GUI (ví dụ: Konsole) hoặc thiết bị đầu cuối ảo nhận được một tổ hợp phím mà nó diễn giải là ^C, nó có thể thực hiện một trong ba điều. Nếu thiết bị đầu cuối ở chế độ thô , thì chương trình đang chạy đã yêu cầu thiết bị đầu cuối không tự thực hiện bất kỳ thao tác nào của các phím đặc biệt và chuyển thẳng chúng đến chương trình. Một số chương trình hỗ trợ các tính năng nâng cao như chỉnh sửa dòng nhận đầu vào bàn phím trong một số cấu hình ở giữa tổ hợp phím thô hoàn chỉnh và dòng văn bản được xử lý; bash, ví dụ, nhận từng lần nhấn phím một lần. ^Cđược giải thích bởi thiết bị đầu cuối, nhưng phím backspace được gửi đến shell như hiện trạng.

Tuy nhiên, hầu hết các chương trình đều sử dụng chế độ nấu (vì nó không ở dạng thô), trong đó thiết bị đầu cuối diễn giải một số tổ hợp phím cơ bản trước khi thực sự gửi chúng đến chương trình (đây là lý do tại sao bạn có thể sử dụng backspace trong cat). Trong chế độ này, thiết bị đầu cuối tự chuyển ^Ctổ hợp phím thành SIGINTtín hiệu và gửi nó đến tiến trình con. Vì thiết bị đầu cuối tạo tín hiệu, nó sẽ không bị lẫn lộn và chấm dứt.

  • SysRq thực sự là ma thuật

Rõ ràng không phải là siêu liên quan ở đây, nhưng đối với điện toán nói chung, có nhiều tổ hợp phím ma thuật hơn ngoài kia. Nổi tiếng nhất, Ctrl+ Alt+ Deletetrong thế giới Windows, nơi tổ hợp phím khá gần với phép thuật (nó có thể được sử dụng để khiến Windows hoạt động, điều đó khá kỳ diệu trong chính nó!), Vì nó được mã hóa cứng vào hệ thống để làm gián đoạn và ghi đè lên khá nhiều thứ, mọi thứ khá giống với SysRqý nghĩa đó.
KRyan

7
Bash không sử dụng chế độ thô - nó sử dụng chế độ ký tự một lúc tức là cbreak/ -icanon, nhưng nó để isigchế độ được đặt và không nhận được tín hiệu thực khi bạn nhấn các phím được ánh xạ tới chúng. Nó xử lý SIGINTbằng cách hành xử như bạn mô tả (nó không chỉ hủy chỉnh sửa dòng, nó cũng hủy bất kỳ lệnh nội bộ nào có thể đang chạy trong một vòng lặp), và hoàn toàn bỏ qua SIGTSTPSIGQUIT. Các chương trình khác, như vi, có thể không.
Random832

1
@KRyan Ctrl+ Alt+ Deletetrước đây thậm chí còn kỳ diệu hơn ngày hôm nay - blog.msdn.microsoft.com/oldnewthing/20140912-00/?p=44083 . Mặc dù tôi là một người thích Linux nhưng tôi thường nhận ra rằng Windows đã làm cho mọi thứ trở nên thân thiện và hợp lý với những tài nguyên hạn chế như vậy trong những ngày đầu.
Muzer

Trên một số hệ điều hành, ngay cả khi một chương trình khác tập trung vào hệ thống (trình quản lý cửa sổ tôi đoán?) Thực sự có được các phím nhấn trước khi trình giả lập thiết bị đầu cuối từng làm. Nếu bạn có thể định cấu hình các phím tắt trên bàn phím để chụp các cửa sổ, mở các ứng dụng, kích hoạt các tập lệnh thì trước khi các phím được nhấn được gửi đến trình giả lập thiết bị đầu cuối, chúng sẽ được kiểm tra xem có bất kỳ phím tắt nào bạn đã định cấu hình không. Và một ví dụ khác nếu bạn không có ứng dụng nào mở ^csẽ không giết trình quản lý cửa sổ :). Không thể nhận xét về nhân vật thô / nấu tại một thời điểm, nhưng câu trả lời là tại chỗ về cách mà tổ hợp phím đó được tạo raSIGINT
Ajay

2
" Chế độ nấu (vì nó không còn sống)": Tôi ... không nói nên lời. Sau tất cả những năm này, tôi không bao giờ thực hiện kết nối.
isanae

8

^Cthường được ánh xạ (xem stty -a) đến SIGINTtín hiệu (xem man 7 signal).

Một cái không bị bắt SIGINTlàm gián đoạn quá trình chạy, NHƯNG ...

SIGINT là một trong những tín hiệu mà một quá trình có thể chỉ định hành vi cho ("Bắt tín hiệu").

Những gì bạn gọi là "thiết bị đầu cuối" bắt SIGINTvà quay trở lại làm việc.


7

Khi tôi mới bắt đầu, tôi đã thiếu một phần rằng khi tôi đang sử dụng dòng lệnh tôi thực sự đang sử dụng hai chương trình riêng biệt, một thiết bị đầu cuối và một trình bao (ví dụ: bash)

Shell là những gì bạn có thể đã biết, một chương trình lấy các lệnh đầu vào hoặc tập lệnh, thực thi chúng và in kết quả đầu ra của chúng.

Thiết bị đầu cuối ở phía bên kia giống như một người đàn ông ở giữa người dùng và chương trình (chương trình này thường là một cái vỏ như bash hoặc cá). Những gì thiết bị đầu cuối làm là đọc ví dụ đầu vào từ bàn phím, có thể xử lý đầu vào đó theo một cách nào đó và chuyển hướng nó sang chương trình khác (bash).

Ngoài ra, điều này cũng hoạt động theo cách khác, khi chương trình kia xuất ra một cái gì đó, rằng một cái gì đó được chuyển hướng đến thiết bị đầu cuối, thì đó là công việc của thiết bị đầu cuối để đưa thứ gì đó ra màn hình. Ở giữa nhận đầu vào và in ra màn hình, thiết bị đầu cuối có thể diễn giải đầu vào mà nó đang nhận theo nhiều cách khác nhau.

Ví dụ: nếu một chương trình xuất ra chuỗi sau:

\e[0;31m some extra foobar text

Thiết bị đầu cuối sẽ xuất ra màn hình "một số văn bản foobar bổ sung" với các chữ màu đỏ. Điều này là do thiết bị đầu cuối chọn xử lý mã kỳ lạ đó theo cách đặc biệt mà mã gợi ý để in đầu ra sau bằng màu đỏ.

Tương tự như vậy khi người dùng nhấn Ctrl - C, điều đặc biệt duy nhất về điều này là thiết bị đầu cuối chọn xử lý nó theo một cách đặc biệt, không có gì đặc biệt khác về chuỗi khóa này. Cụ thể điều này gợi ý nó gửi tín hiệu ngắt (SIGINT) đến quá trình đang chạy bên trong thiết bị đầu cuối, đó là vỏ. Nếu tại thời điểm đó tồn tại bất kỳ chương trình nào được sinh ra bởi trình bao và hiện đang chạy ở nền trước thì nó cũng nhận được tín hiệu. Bây giờ vỏ có một trình xử lý đặc biệt cho tín hiệu này và không có gì xảy ra. Nhưng hầu hết các chương trình đều có các trình xử lý mặc định mà trong trường hợp của SIGINT chỉ cần thoát.


5

Mỗi tín hiệu có một hành động mặc định liên quan đến nó. Hành động mặc định cho tín hiệu là hành động mà tập lệnh hoặc chương trình thực hiện khi nhận được tín hiệu.

Ctrl+ Cgửi tín hiệu "ngắt" ( SIGINT ), mặc định để chấm dứt quá trình cho công việc đang chạy ở nền trước.

Ctrl+ Dnói với thiết bị đầu cuối rằng nó nên đăng ký EOF trên đầu vào tiêu chuẩn, điều này bash diễn giải như một mong muốn để thoát .

Một quá trình có thể chọn bỏ qua tín hiệu INT và Bash làm như vậy khi nó chạy ở chế độ tương tác.

Từ hướng dẫn :

Khi bash có tính tương tác, trong trường hợp không có bẫy, nó sẽ bỏ qua SIGTERM (để kill 0 không giết được vỏ tương tác) và SIGINT bị bắt và xử lý (do đó quá trình dựng sẵn chờ đợi bị gián đoạn). Trong mọi trường hợp, bash bỏ qua SIGQUIT. Nếu kiểm soát công việc có hiệu lực, bash sẽ bỏ qua SIGTTIN, SIGTTOU và SIGTSTP.


Hiểu nó với cái bẫy :

bẫy là một chức năng được tích hợp vào vỏ đáp ứng tín hiệu phần cứng và các sự kiện khác. Nó xác định và kích hoạt các trình xử lý sẽ được chạy khi shell nhận được tín hiệu hoặc các điều kiện đặc biệt khác.

trap [-lp] [arg] [sigspec …]

-l in một danh sách các tên tín hiệu và số tương ứng của chúng.
-phiển thị các lệnh bẫy được liên kết với mỗi SIGNALClickEC.

arg sẽ được đọc và thực thi khi shell nhận tín hiệu sigspec. Mỗi sigspec là tên tín hiệu hoặc số tín hiệu. Tên tín hiệu không phân biệt chữ hoa chữ thường và tiền tố SIG là tùy chọn.

Nếu một sigspec0 hoặc EXIT , arg được thực thi khi thoát khỏi shell. Để hiểu nó, hãy đóng terminal và mở nó sau khi chỉnh sửa dòng sau trong .bashrctệp.

trap 'notify-send "Ctrl D pressed"' 0

Ctrl D tương tự như exitlệnh để thoát khỏi terminal.

Nếu bạn muốn Bash thoát khi nhận được tín hiệu INT, ngay cả trong chế độ tương tác, bạn có thể thêm thông tin sau vào ~/.bashrc:

trap 'exit' INT

hoặc là

trap 'exit' 2

1
có vẻ hợp pháp !!
luv.preet
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.