เหตุใดจึงไม่สามารถออกด้วย Cc ได้


20

โปรแกรมedตัวแก้ไขข้อความขั้นต่ำไม่สามารถออกได้โดยส่งการขัดจังหวะโดยใช้Ctrl- Cแทนที่จะพิมพ์ข้อความแสดงข้อผิดพลาด "?" ไปยังคอนโซล ทำไมไม่edเพียงออกเมื่อได้รับการขัดจังหวะ? แน่นอนไม่มีเหตุผลว่าทำไมข้อผิดพลาดที่เป็นความลับมีประโยชน์มากกว่าที่นี่เพียงแค่ออกจาก พฤติกรรมนี้นำผู้ใช้ใหม่จำนวนมากไปสู่การโต้ตอบประเภทต่อไปนี้:

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

ขยะที่น่าเศร้าเช่นนี้สามารถหลีกเลี่ยงได้ง่ายหากedตกลงกันว่าจะถูกขัดจังหวะ

อีกหนึ่งโปรแกรมปากแข็งจัดแสดงเป็นพฤติกรรมที่คล้ายกันซึ่งยังไม่ปรากฏว่ามีเหตุผลมากพอที่จะไม่สนใจless C-cเหตุใดโปรแกรมเหล่านี้จึงไม่เป็นเพียงคำใบ้


4
แอปพลิเคชันแบบโต้ตอบนั้นไม่เหมือนกับแบบไม่โต้ตอบ พฤติกรรม Ctrl-C ที่คุณคุ้นเคยเป็นค่าเริ่มต้นสำหรับพฤติกรรมที่ไม่โต้ตอบ สิ่งที่โต้ตอบอาจแทนที่พฤติกรรมของ Ctrl-C เพื่อจุดประสงค์ของพวกเขาเอง
jw013

4
นอกจากนี้ไม่แน่ใจว่าเป็นเรื่องตลก
jw013

@ jw013 ใช่ "เซสชั่นทั่วไป" เป็นเรื่องตลก (ฉันไม่สามารถหาได้ด้วยเหตุผลบางอย่าง) แต่คำถามของฉันจริงจัง สิ่งที่ฉันไม่เข้าใจคือสาเหตุที่แอปพลิเคชันเหล่านี้เลือกที่จะแทนที่การทำงานของ Ctrl-C หากมันไม่ได้ให้ประโยชน์อะไรเลย
Lily Chung

1
เนื่องจากคำถามนี้เป็นคำตอบการค้นหายอดนิยมของ Google สำหรับ "วิธีออกจาก ed" ฉันต้องการเพิ่มที่นี่ซึ่งเป็นเพียง 'q' ตามด้วยการส่งคืน ชาว Bothans จำนวนมากเสียชีวิตเพื่อนำข้อมูลนี้มาให้เรา
Dmitri

คำตอบ:


19

Ctrl+ Cส่งSIGINT แอ็คชันทั่วไปสำหรับ SIGINT คือการกลับไปที่ลูประดับบนของโปรแกรมยกเลิกคำสั่งปัจจุบันและเข้าสู่โหมดที่โปรแกรมรอคำสั่งถัดไป โปรแกรมที่ไม่ต้องมีการโต้ตอบเท่านั้นที่ควรจะตายจาก SIGINT

ดังนั้นมันจึงเป็นธรรมชาติที่Ctrl+ Cไม่ได้ฆ่าเอ็ด แต่ทำให้มันกลับไปที่วงบนสุดของมัน Ctrl+ Cยกเลิกสายอินพุตปัจจุบันและกลับไปที่พรอมต์ ed

สิ่งเดียวกันจะน้อยลง: Ctrl+ Cขัดจังหวะคำสั่งปัจจุบันและนำคุณกลับไปที่พรอมต์คำสั่ง

ด้วยเหตุผลทางประวัติศาสตร์ ed ไม่สนใจSIGQUIT ( Ctrl+ \) แอปพลิเคชันปกติไม่ควรจับสัญญาณนี้และอนุญาตให้ตัวเองถูกยกเลิกด้วยการถ่ายโอนข้อมูลหลักหากเปิดใช้งาน


@ Kzqai ไม่แอปพลิเคชันทั่วไปไม่ควรจับ SIGQUIT มันหมายถึงเป็นการออกฉุกเฉิน
Gilles 'หยุดความชั่วร้าย'

อ้า gotcha ตกลงหดกลับ
Kzqai

18

Unix V7 ed(1)รหัสที่มาเป็นโปรแกรม C 1,762 เส้นดั้งเดิมมีเพียงไม่กี่ความเห็นซึ่งเป็นหนึ่งในความคิดเห็นนี้ส่วนหัวสูง enlightening:

/*
 * Editor
 */

เนื่องจากซอร์สโค้ดเองไม่ได้ให้เหตุผลใด ๆ คุณจะได้รับจากผู้เขียนโปรแกรมเท่านั้น

edแรกเริ่มเขียนโดย Ken Thompson ในการประชุม PDP-11แต่คุณต้องพูดกับใครก็ตามที่ส่งไปยัง C นั่นอาจเป็นDennis Ritchieเนื่องจากเขาสร้าง C สำหรับ Unix และเป็นหนึ่งในหลาย ๆ คนที่ใช้ C ทำให้ Unix พกพาไปยังเครื่องที่ไม่ใช่ PDP ดร. ริตชี่ไม่ได้ตอบคำถามเหล่านี้อีกต่อไปแล้ว

การอ่านรหัสของฉันแสดงให้เห็นว่ามีการพยายามเก็บรักษาเนื้อหาของสำเนาin-coreของเอกสารที่แก้ไข คุณจะพบว่าการแก้ไขข้อความอื่น ๆ Ctrl-Cยังไม่ตาย

นี่คือสิ่งที่edเกิดขึ้นCtrl-C:

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

(ใช่K&R C.เราไม่ต้องการตัวระบุประเภทส่งคืนหรือการประกาศพารามิเตอร์ของ steenkin)

แปลเป็นภาษาอังกฤษed:

  1. ลงทะเบียนตัวจัดการสัญญาณอีกครั้ง

    (Unix ไม่ได้รับสัญญาณรีเซ็ตอัตโนมัติจนถึง 4.3BSDในช่วงกลางทศวรรษ 1980)

  2. เขียนบรรทัดใหม่และจำไว้ว่าทำเช่นนั้นผ่านตัวแปรlastcกลาง

    ( ed.cมีตัวแปรทั่วโลกประมาณหกสิบ )

  3. เรียกใช้error()ฟังก์ชันที่มีชื่อเสียงมากกว่าการพิมพ์เพียงเล็กน้อย?จากมุมมองของผู้ใช้

กล่าวอีกนัยหนึ่งก็คือการพูดว่า "คุณไม่ได้ตั้งใจทำแบบนั้นจริงเหรอ?"


2
นอกจากนี้ยังมีข้อสังเกตว่าตัวแก้ไขข้อความจำนวนมากไม่ได้ออกจาก Control-C เสียงเรียกเข้ายังไม่ได้ ไม่ทำนาโน ฉันไม่คิดว่า emac ทำเช่นนั้น แต่ยังไม่ได้ติดตั้งเพื่อทดสอบ
Derobert

3
@derobert Vi ปฏิบัติ Ctrl + C ด้วยวิธี Unix: กลับไปที่ระดับบนสุด Emacs มีการผูกกุญแจของตัวเองเนื่องจากต้นกำเนิดที่ไม่ใช่ยูนิกซ์ Emacs ที่เทียบเท่ากับ Ctrl + C ของ Unix คือ Ctrl + G (ตัวอักษรกระดิ่ง - กดกริ่งที่คอมพิวเตอร์เพื่อขัดจังหวะ)
Gilles 'SO- หยุดความชั่วร้าย'

@derobert: จุดยุติธรรม ฉันได้เพิ่มสิ่งนี้ในคำตอบ
Warren Young

2
@Gilles: หนึ่งในผลข้างเคียงของการโทรerror(s)เข้าed.cคือการกลับไปที่ลูปการประมวลผลหลัก มันทำได้ด้วยการlongjmp()โทร ตัวสั่น
วอร์เรนยังก์

1
ขอบคุณสำหรับรายละเอียดและบทเรียนประวัติศาสตร์ นี่เป็นการอ่านที่ยอดเยี่ยม!
alichaudry

7

edเช่นเดียวกับโปรแกรมเชิงโต้ตอบอื่น ๆ ใช้Ctrl+ Cเพื่อขัดจังหวะงานของโปรแกรมเอง
นี่คล้ายกับกรณีปกติมากโดยที่มันขัดจังหวะงานที่รันในเชลล์ - คำสั่ง

จากมุมมองของผู้ใช้ตัวแปรทั้งสองมีความคล้ายคลึงกันมาก การจัดการสัญญาณแตกต่างกัน: ในกรณีปกติสัญญาณSIGINTจะถูกส่งไปยังกระบวนการพื้นหน้าคำสั่งที่รันอยู่และคำสั่งจะจัดการกับมันโดยออกจาก
ในกรณีของedสัญญาณจะถูกส่งไปยังกระบวนการเบื้องหน้าedอินสแตนซ์ หากมีงานที่ทำงานอยู่edจะถูกขัดจังหวะและมีการแจ้งเตือนปรากฏขึ้น หากไม่มีการทำงานใด ๆ จะไม่มีการเปลี่ยนแปลงใด ๆ

หมายเหตุวิธีเปลือกยังไม่ได้ออกจากบนCtrl+ เช่นเดียวกับC edและที่มันไม่ทางออก+Ctrl Dอีกครั้งเช่นเดียวกับed


3

มีสามสัญญาณที่edใส่ใจ:

  1. INT
  2. HUP
  3. QUIT

ข้อมูลจำเพาะ POSIX ของedพูดว่าต่อไปนี้เกี่ยวกับสิ่งเหล่านี้:

SIGINT

edยูทิลิตี้จะขัดขวางกิจกรรมปัจจุบันเขียนสตริง?\nออกมาตรฐานและกลับไปที่โหมดคำสั่ง (ดูรายละเอียดในส่วน EXTENDED)

SIGHUP

หากบัฟเฟอร์ไม่ว่างเปล่าและมีการเปลี่ยนแปลงตั้งแต่การเขียนครั้งล่าสุดedยูทิลิตี้จะพยายามเขียนสำเนาของบัฟเฟอร์ในไฟล์ ก่อนอื่นให้ใช้ไฟล์ที่มีชื่อed.hupอยู่ในไดเรกทอรีปัจจุบัน หากล้มเหลวไฟล์ที่มีชื่อed.hupในไดเรกทอรีที่มีชื่อโดยHOMEตัวแปรสภาพแวดล้อมจะถูกนำมาใช้ ในกรณีใด ๆedยูทิลิตี้จะออกโดยไม่ต้องเขียนไฟล์ไปยังชื่อพา ธ ที่จำได้ในปัจจุบันและไม่กลับไปที่โหมดคำสั่ง

SIGQUIT

edยูทิลิตี้จะไม่สนใจกับเหตุการณ์นี้

ดังนั้นการใช้งานของedคุณกำลังใช้มันเป็นไปตามข้อกำหนด POSIX เกี่ยวกับINTสัญญาณ (ซึ่งเป็นสิ่งที่Ctrl+Cส่ง)

ในเรื่องนี้บรรณาธิการทำงานเหมือนเปลือกโต้ตอบซึ่งยังไม่ยุติเมื่อได้รับINTสัญญาณ บรรณาธิการอื่น ๆ เช่นviและnanoทำสิ่งเดียวกัน


1
การใช้งานโปรแกรมบางอย่างขัดแย้งกับ POSIX โดยเจตนาดังนั้นอาจเป็นประโยชน์ในการอธิบายเหตุผลสำหรับมาตรฐาน / ค่าใช้จ่ายในการทำลายมันในกรณีนี้ stackoverflow.com/questions/38605463/…
sourcejedi

1
@sourcejedi มาตรฐานไม่ได้พูดอะไรเกี่ยวกับสัญญาณในเหตุผลของมัน ฉันไม่พบเหตุผลที่จะพูดอะไรเกี่ยวกับสาเหตุที่มีการปฏิบัติตามมาตรฐานในแหล่งที่มาของedฉัน มันทำงานในลักษณะที่คล้ายกันเป็นเปลือกซึ่งยังไม่ยุติในการรับINTสัญญาณ
Kusalananda
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.