Tại sao ed không thể thoát khỏi Cc?


20

Chương trình ed, một trình soạn thảo văn bản tối thiểu, không thể được thoát bằng cách gửi nó gián đoạn thông qua việc sử dụng Ctrl- C, thay vào đó in thông báo lỗi "?" đến bàn điều khiển. Tại sao không edthoát khi nhận được ngắt? Chắc chắn không có lý do tại sao một thông báo lỗi khó hiểu ở đây lại hữu ích hơn là chỉ thoát ra. Hành vi này dẫn nhiều người dùng mới vào loại tương tác sau:

$ ed
hello
?
help
?
exit
?
quit
?
^C
?
^C
?
?
?
^D
$ su
# rm -f /bin/ed

Một chất thải bi thảm như vậy dễ dàng tránh được nếu edđơn giản là đồng ý bị gián đoạn.

Một chương trình cứng đầu khác lessthể hiện hành vi tương tự là dường như không có nhiều lý do để bỏ qua C-c. Tại sao các chương trình này không chỉ là một gợi ý?


4
Các ứng dụng tương tác không giống như không tương tác. Hành vi Ctrl-C mà bạn quen dùng là mặc định cho những hành vi không tương tác. Những người tương tác có thể ghi đè hành vi của Ctrl-C cho mục đích riêng của họ.
jw013

4
Ngoài ra, không chắc chắn nếu trò đùa
jw013

@ jw013 Vâng, "phiên thông thường" là một trò đùa (tôi không thể tìm thấy vì lý do nào đó) nhưng câu hỏi của tôi là nghiêm trọng. Điều tôi không hiểu là tại sao các ứng dụng này chọn ghi đè hành vi của Ctrl-C nếu nó không thực sự cung cấp bất cứ điều gì hữu ích.
Lily Chung

1
Vì câu hỏi này xuất hiện dưới dạng câu trả lời tìm kiếm hàng đầu của google về "cách thoát ed", tôi muốn thêm vào đây rằng đó chỉ là "q" theo sau là trả về. Nhiều người đã chết để mang lại cho chúng tôi thông tin này.
Dmitri

Câu trả lời:


19

Ctrl+ Cgửi SIGINT . Hành động thông thường cho SIGINT là quay lại vòng lặp toplevel của chương trình, hủy lệnh hiện tại và vào chế độ trong đó chương trình chờ lệnh tiếp theo. Chỉ các chương trình không tương tác được cho là chết vì SIGINT.

Vì vậy, điều tự nhiên là Ctrl+ Ckhông giết ed, nhưng khiến nó quay trở lại vòng lặp toplevel của nó. Ctrl+ Chủy bỏ dòng đầu vào hiện tại và trở về dấu nhắc ed.

Điều tương tự cũng xảy ra với ít hơn: Ctrl+ Clàm gián đoạn lệnh hiện tại và đưa bạn trở lại dấu nhắc lệnh của nó.

Vì lý do lịch sử, ed bỏ qua SIGQUIT ( Ctrl+ \). Các ứng dụng thông thường không nên bắt tín hiệu này và cho phép chúng bị chấm dứt, với kết xuất lõi nếu được bật.


@Kzqai Không, các ứng dụng thông thường không nên bắt SIGQUIT, nó có nghĩa là một lối thoát khẩn cấp.
Gilles 'SO- ngừng trở nên xấu xa'

À, gotcha. Được rồi, rút ​​lại.
Kzqai

18

Các Unix V7 ed(1)mã nguồn là một chương trình C 1762-line nguyên thủy chỉ với một vài ý kiến, một trong số đó là tiêu đề này bình luận cao khai sáng:

/*
 * Editor
 */

Cho rằng bản thân mã nguồn không cung cấp bất kỳ lý do hợp lý nào, bạn sẽ chỉ lấy nó từ tác giả của chương trình.

edban đầu được viết bởi Ken Thompson trong bản lắp ráp PDP-11 , nhưng bạn thực sự cần nói chuyện với bất kỳ ai đã chuyển nó cho C. Đó có thể là Dennis Ritchie , vì anh ta đã tạo C cho Unix và là một trong nhiều người đã sử dụng C để làm cho Unix di động đến các máy không PDP. Tuy nhiên, Tiến sĩ Ritchie không còn ở đây để trả lời những câu hỏi như vậy.

Việc đọc mã của tôi cho thấy rằng nó đã được thực hiện để thử và bảo quản nội dung của bản sao trong lõi của tài liệu đã chỉnh sửa. Bạn sẽ nhận thấy rằng các trình soạn thảo văn bản khác cũng không chết Ctrl-C.

Đây là những gì edtrên Ctrl-C:

onintr()
{
    signal(SIGINT, onintr);
    putchr('\n');
    lastc = '\n';
    error(Q);
}

(Có, K & R C. Chúng tôi không cần các chỉ định loại trả về hoặc khai báo tham số của steenkin.)

Dịch sang tiếng Anh , ed:

  1. Đăng ký lại bộ xử lý tín hiệu.

    (Unix đã không nhận được tín hiệu tự động đặt lại cho đến 4.3BSD , vào giữa những năm 1980.)

  2. Viết ra một dòng mới và nhớ rằng nó đã làm như vậy, thông qua biến toàn cục lastc.

    ( ed.ccó khoảng sáu mươi biến toàn cầu.)

  3. Gọi error()hàm, vốn nổi tiếng không chỉ là in ?, từ quan điểm của người dùng.

Nói cách khác, nó nói, "Bạn không thực sự có ý định làm điều đó, phải không?"


2
Cũng đáng lưu ý rằng rất nhiều trình soạn thảo văn bản không thoát trên Control-C. Vim cũng không. Cả nano cũng không. Tôi cũng không nghĩ emacs cũng vậy, nhưng không cài đặt nó để kiểm tra.
derobert

3
@derobert Vi xử lý Ctrl + C theo cách Unix: quay trở lại toplevel. Emacs có keybindings riêng, do nguồn gốc không phải là Unix; Emacs tương đương với Ctrl + C của Unix là Ctrl + G (ký tự chuông - rung chuông ở máy tính để làm gián đoạn nó)
Gilles 'SO- ngừng trở thành ác quỷ'

@derobert: Điểm công bằng. Tôi đã thêm điều này vào câu trả lời.
Warren Young

2
@Gilles: Một trong những tác dụng phụ của việc gọi error(s)vào ed.clà quay lại vòng xử lý chính. Nó làm như vậy với một longjmp()cuộc gọi. rùng mình
Warren Young

1
Cảm ơn bạn đã chi tiết và bài học lịch sử. Đây là một chi lớn!
alichaudry

7

ed, giống như các chương trình tương tác khác, sử dụng Ctrl+ Cđể làm gián đoạn các tác vụ của chính chương trình.
Điều này rất giống với trường hợp bình thường, trong đó nó làm gián đoạn một tác vụ đang chạy trong shell - một lệnh.

Từ góc độ người dùng, cả hai biến thể đều rất giống nhau. Việc xử lý tín hiệu là khác nhau: trong trường hợp thông thường, tín hiệu SIGINTđược gửi đến quá trình tiền cảnh, lệnh đang chạy và lệnh xử lý nó bằng cách thoát.
Trong trường hợp ed, tín hiệu được gửi đến quá trình tiền cảnh, edví dụ. Nếu có một tác vụ đang chạy ed, nó bị gián đoạn và lời nhắc được hiển thị. Nếu không có nhiệm vụ chạy, không có gì thay đổi.

Lưu ý cách shell cũng không thoát trên Ctrl+ C, giống như ed. Và nó thoát trên Ctrl+ D. Một lần nữa, giống nhưed


3

Có ba tín hiệu edquan tâm:

  1. INT
  2. HUP
  3. QUIT

Đặc tả POSIXed cho biết như sau về những điều sau:

SIGINT

Các edtiện ích có trách nhiệm gián đoạn hoạt động hiện tại của nó, hãy viết các chuỗi ?\nđầu ra tiêu chuẩn, và trở về chế độ lệnh (xem phần MÔ TẢ EXTENDED).

SIGHUP

Nếu bộ đệm không trống và đã thay đổi kể từ lần ghi cuối cùng, edtiện ích sẽ cố gắng ghi một bản sao của bộ đệm vào một tệp. Đầu tiên, tập tin có tên ed.huptrong thư mục hiện tại sẽ được sử dụng; nếu thất bại, tập tin có tên ed.huptrong thư mục được đặt tên bởi HOMEbiến môi trường sẽ được sử dụng. Trong mọi trường hợp, edtiện ích sẽ thoát mà không ghi tệp vào tên đường dẫn hiện được ghi nhớ và không quay lại chế độ lệnh.

SIGQUIT

Các edtiện ích sẽ bỏ qua sự kiện này.

Vì vậy, bất kỳ triển khai ednào bạn đang sử dụng, nó đều tuân thủ đặc điểm kỹ thuật POSIX liên quan đến INTtín hiệu (đó là những gì Ctrl+Cgửi).

Về vấn đề này, trình soạn thảo hoạt động giống như một vỏ tương tác, cũng không chấm dứt khi nhận được INTtín hiệu. Các biên tập viên khác, chẳng hạn như vinanolàm điều tương tự.


1
Một số triển khai chương trình cố tình mâu thuẫn với POSIX, vì vậy có thể hữu ích để giải thích lý do căn bản cho tiêu chuẩn / chi phí phá vỡ nó trong trường hợp này. stackoverflow.com/questions/38605463/ từ
sourcejedi

1
@sourcejedi Tiêu chuẩn không nói gì về các tín hiệu trong lý do của nó. Tôi đã không tìm thấy lý do nào nói bất cứ điều gì về lý do tại sao các tiêu chuẩn được tuân theo trong các nguồn edmà tôi có sẵn. Nó hoạt động theo cách tương tự như vỏ, cũng không chấm dứt khi nhận INTtín hiệu.
Kusalananda
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.