Tại sao Ctrl-D (EOF) thoát khỏi vỏ?


68

Bạn có nghĩa đen là "kết thúc một tệp" bằng cách nhập chuỗi thoát này, tức là phiên shell tương tác được xem như một luồng tệp thực sự bởi shell, giống như bất kỳ luồng tệp nào khác? Nếu vậy, tập tin nào?

Hoặc, tín hiệu Ctrl+ Dchỉ là một trình giữ chỗ có nghĩa là "người dùng đã cung cấp xong đầu vào và bạn có thể chấm dứt"?



6
FYI, trong bash bạn có thể làm set -o ignoreeofđể thay đổi hành vi đó.
Keith

Tôi đã từng gặp vấn đề tương tự. Lỗi của tôi là tôi đã vô tình gán phím tắt hồ sơ konsole cho "Ctrl + d". Không phải khoảnh khắc tự hào nhất của tôi.
Brian Simonsen

Câu trả lời:


78

^Dtự (còn được gọi là \04hoặc 0x4, END OF TRANSMISSION bằng Unicode) là giá trị mặc định cho eoftham số ký tự điều khiển đặc biệt của trình điều khiển đầu cuối hoặc trình điều khiển giả trong nhân (chính xác hơn là theo ttyquy tắc dòng được gắn vào nối tiếp hoặc giả thiết bị tty ). Đó là c_cc[VEOF]những termioscấu trúc truyền cho TCSETS / TCGETS ioctlmột vấn đề với thiết bị đầu cuối để ảnh hưởng đến hành vi của tài xế.

Lệnh điển hình gửi chúng ioctlssttylệnh.

Để lấy tất cả các tham số:

$ stty -a
tốc độ 38400 baud; hàng 58; cột 191; dòng = 0;
xâm nhập = ^ C; bỏ = ^ \; xóa = ^?; giết = ^ U; eof = ^ D ; eol = <undef>; eol2 = <undef>; swtch = <undef>; bắt đầu = ^ Q; dừng lại = ^ S; nghi ngờ = ^ Z; rprnt = ^ R; werase = ^ W; lnext = ^ V; tuôn ra = ^ O;
tối thiểu = 1; thời gian = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc-nobnl onlcr -onoc -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

eofTham số đó chỉ liên quan khi thiết bị đầu cuối ở icanonchế độ.

Trong chế độ đó, trình điều khiển đầu cuối (không phải trình giả lập thiết bị đầu cuối) thực hiện trình chỉnh sửa dòng rất đơn giản , nơi bạn có thể gõ Backspaceđể xóa một ký tự, Ctrl-Uđể xóa toàn bộ dòng ... Khi một ứng dụng đọc từ thiết bị đầu cuối, nó sẽ không thấy gì cho đến khi bạn nhấn Returnvào điểm read()trả về dòng đầy đủ bao gồm LFký tự cuối cùng (theo mặc định, trình điều khiển thiết bị đầu cuối cũng dịch các CRthiết bị đầu cuối của bạn gửi Returnđến LF).

Bây giờ, nếu bạn muốn gửi những gì bạn đã nhập cho đến nay mà không cần nhấn Enter, đó là nơi bạn có thể nhập eofký tự. Khi nhận được ký tự đó từ trình giả lập thiết bị đầu cuối, trình điều khiển thiết bị đầu cuối sẽ gửi nội dung hiện tại của dòng, để ứng dụng thực hiện readtrên đó sẽ nhận được nó (và nó sẽ không bao gồm LFký tự dấu ).

Bây giờ, nếu dòng hiện tại trống và được cung cấp, ứng dụng sẽ đọc đầy đủ các dòng đã nhập trước đó, readsẽ trả về 0 ký tự.

Điều đó biểu thị phần cuối của tệp cho ứng dụng (khi bạn đọc từ một tệp, bạn đọc cho đến khi không còn gì để đọc). Đó là lý do tại sao nó được gọi là eofký tự, bởi vì việc gửi nó khiến ứng dụng thấy rằng không có thêm đầu vào nào khả dụng.

Bây giờ, các shell hiện đại, tại dấu nhắc của chúng không đặt thiết bị đầu cuối ở icanonchế độ vì chúng thực hiện trình chỉnh sửa dòng riêng của chúng, tiên tiến hơn nhiều so với trình điều khiển đầu cuối tích hợp sẵn. Tuy nhiên, trong trình chỉnh sửa dòng riêng của họ , để tránh gây nhầm lẫn cho người dùng, họ cung cấp cho ^Dnhân vật (hoặc bất kỳ eofcài đặt nào của thiết bị đầu cuối với một số) có cùng ý nghĩa (để biểu thị eof).


Tôi biết một khi tôi bắt đầu đọc bình luận này rằng nó được viết bởi Stephane :) Bạn, Stephane, là anh hùng Bash của tôi, và tôi không bị mỉa mai. Tôi rất thích ăn trưa với bạn và chọn bộ não của bạn nếu bạn từng đến NYC, tôi đang mua.
Gregg Leventhal

@GreggLeventhal. Cảm ơn. Cơ hội của tôi đến NYC bất cứ lúc nào cũng khá mong manh.
Stéphane Chazelas

Đó là EOT ngay cả trong ASCII 7 bit
Bananguin

9

CTRL_D chỉ là một tín hiệu cho biết đây là phần cuối của luồng văn bản. Bạn không kết thúc một tệp với nó, bạn kết thúc luồng đầu vào của mình bằng cách nhập nó. Ngoài ra CTRL_D không đại diện cho bất kỳ ký tự hoặc byte nào như bạn có thể tìm ra với hexdump của công cụ:

# cat >test.txt
asdf# hexdump -C test.txt 
00000000  61 73 64 66                                       |asdf|
00000004
# ll test.txt 
-rw-r--r-- 1 root root 4 Jan 21 11:55 test.txt

5
Và lý do mà nó kết thúc shell là vì shell về cơ bản là một quá trình chấp nhận đầu vào và thực hiện công cụ với nó. Khi bạn nói với nó rằng sẽ không còn đầu vào nào nữa, vỏ sẽ không còn gì nữa.
Jenny D

Tôi nhận ra rằng chuỗi EOF không được chứa bởi một tệp văn bản và được HĐH tạo ra để báo cáo rằng không có thêm dữ liệu để đọc. Tôi nghĩ điều tôi thực sự hỏi là liệu phiên cuối của thiết bị đầu cuối tương tác được xem như một luồng tệp thực sự bằng vỏ, giống như bất kỳ luồng tệp nào khác.
Geeb

Chỉ cần chỉnh sửa câu hỏi ban đầu để làm rõ.
Geeb

2
có, luồng đi đến bash là luồng đầu vào như bất kỳ luồng nào khác. CTRL_D báo hiệu rằng luồng đầu vào ở cuối và bash có thể thoát.
Thorsten Staerk
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.