จะเกิดอะไรขึ้นเมื่อกด Ctrl + Alt + F <Num>


38

ฉันกำลังมองหาคำอธิบายว่าเกิดอะไรขึ้นใน Linux เมื่อกดปุ่มชุดนี้เพื่อเปลี่ยนเทอร์มินัลปัจจุบัน โดยเฉพาะอย่างยิ่งส่วนประกอบซอฟต์แวร์ใดที่ขัดขวางการรวมคีย์นี้และเปลี่ยนเทอร์มินัล มันเป็นเคอร์เนลหรือไม่ ถ้าเป็นเคอร์เนลคุณสามารถระบุตำแหน่งของไฟล์ต้นฉบับที่จัดการสิ่งนี้ได้หรือไม่?

แก้ไข: ฉันต้องการเข้าใจวิธีการทำงานในทั้งกราฟิก (X11) และสภาพแวดล้อมแบบข้อความ


1
เพื่อชี้แจงคุณกดปุ่มเหล่านี้ใน X11 (นั่นคือเซสชั่นกราฟิก) หรือบนคอนโซลข้อความ? คำตอบนั้นแตกต่างกัน
derobert

คำตอบ:


36

มันเป็นเคอร์เนล โปรดทราบว่าคีย์บอร์ดคือฮาร์ดแวร์และทุกสิ่งที่เกิดขึ้นที่นั่นผ่านเคอร์เนล ในกรณีของการสลับ VT มันจัดการกับเหตุการณ์ได้อย่างสมบูรณ์และไม่ผ่านสิ่งใด ๆ ไปยัง userspace (แต่ฉันเชื่อว่ามี ioctl ที่เกี่ยวข้องกับวิธีการซึ่งโปรแกรม userspace สามารถได้รับการแจ้งเตือนของสวิทช์ที่เกี่ยวข้องกับพวกเขาและอาจส่งผลกระทบต่อ ซึ่ง X ไม่ต้องสงสัยเลย)

เคอร์เนลมีคีย์แมปที่สร้างไว้ สิ่งนี้สามารถแก้ไขได้ในขณะที่ทำงานด้วยloadkeysและดูด้วยdumpkeys:

[...]
keycode  59 = F1               F13              Console_13       F25             
        alt     keycode  59 = Console_1       
        control alt     keycode  59 = Console_1       
keycode  60 = F2               F14              Console_14       F26             
        alt     keycode  60 = Console_2       
        control alt     keycode  60 = Console_2       
keycode  61 = F3               F15              Console_15       F27             
        alt     keycode  61 = Console_3       
        control alt     keycode  61 = Console_3
[...]   

เคอร์เนลแหล่งที่มาประกอบด้วยไฟล์ keymap เริ่มต้นซึ่งมีลักษณะเช่นนี้; สำหรับ 3.12.2 src/drivers/tty/vt/defkeymap.mapมัน คุณจะสังเกตเห็นว่ามีไฟล์defkeymap.c ที่เกี่ยวข้อง(ซึ่งสามารถสร้างได้ด้วยloadkeys --mktable) การจัดการอยู่ในkeyboard.c(ไฟล์ทั้งหมดเหล่านี้อยู่ในไดเรกทอรีเดียวกัน) ซึ่งเรียกset_console()จากvt.c :

» grep set_console *.c
keyboard.c:     set_console(last_console);
keyboard.c:     set_console(i);
keyboard.c:     set_console(i);
keyboard.c:     set_console(value);
vt.c:int set_console(int nr)
vt_ioctl.c:                     set_console(arg);

ฉันแก้ไขความนิยมบางส่วนจากรายการนั้น คุณสามารถเห็นลายเซ็นของฟังก์ชั่นในบรรทัดสุดท้ายที่สอง

ดังนั้นสิ่งเหล่านี้เกี่ยวข้องกับการสับเปลี่ยน ถ้าคุณดูที่ลำดับของการโทรในที่สุดคุณกลับมาในkbd_event() keyboard.cนี่ถูกลงทะเบียนเป็นตัวจัดการเหตุการณ์สำหรับโมดูล:

(3.12.2 drivers/tty/vt/keyboard.cบรรทัด 1473)

MODULE_DEVICE_TABLE(input, kbd_ids);

static struct input_handler kbd_handler = {
    .event      = kbd_event,   <--- function pointer HERE
    .match      = kbd_match,
    .connect    = kbd_connect,
    .disconnect = kbd_disconnect,
    .start      = kbd_start,
    .name       = "kbd",
    .id_table   = kbd_ids,
};  

int __init kbd_init(void)
{

[...]

    error = input_register_handler(&kbd_handler);           

ดังนั้นkbd_event()ควรเรียกใช้เมื่อมีบางสิ่งเกิดขึ้นจากไดรเวอร์ฮาร์ดแวร์จริง (อาจเป็นบางสิ่งบางอย่างจากdrivers/hid/หรือdrivers/input/) อย่างไรก็ตามคุณจะไม่เห็นมันถูกอ้างถึงว่าkbd_eventอยู่นอกไฟล์นั้นเนื่องจากไฟล์นั้นถูกลงทะเบียนผ่านตัวชี้ฟังก์ชั่น

ทรัพยากรบางอย่างสำหรับกลั่นกรองเคอร์เนล

  • การค้นหาตัวระบุการอ้างอิงไขว้ของ Linuxเป็นเครื่องมือที่ยอดเยี่ยม
  • อินเตอร์แอคที Linux Kernel แผนที่เป็นปลายด้านหน้าที่น่าสนใจกราฟิกเครื่องมืออ้างอิงข้าม
  • มีจดหมายเหตุทางประวัติศาสตร์บางส่วนของ Linux Kernel Mailing List (LKML) ขนาดใหญ่ซึ่งกลับไปอย่างน้อยปี 1995; บางคนไม่ได้รับการบำรุงรักษาและมีฟีเจอร์การค้นหาที่ใช้งานไม่ได้ แต่gmaneนั้นทำงานได้ดีมาก ผู้คนได้ถามคำถามมากมายในรายการจดหมายและเป็นวิธีการสื่อสารหลักระหว่างนักพัฒนาเช่นกัน
  • คุณสามารถฉีดprintkบรรทัดของคุณเองลงในซอร์สเป็นวิธีการติดตามอย่างง่าย (ไม่สามารถใช้ C C มาตรฐานทั้งหมดในเคอร์เนลโค้ดรวมถึง printf จาก stdio) สิ่ง printk สิ้นสุดใน syslog

Wolfgang Mauerer เขียนหนังสือเล่มใหญ่เกี่ยวกับเคอร์เนลProfessional Linux Kernel Architecture 2.6 ซึ่งผ่านแหล่งข้อมูลมากมาย Greg Kroah-Hartmanหนึ่งในผู้พัฒนาหลักการสำหรับทศวรรษที่ผ่านมามีสิ่งต่าง ๆ มากมายที่เตะไปรอบ ๆ


1
ขอบคุณนี่คือสิ่งที่ฉันกำลังมองหา คุณช่วยอธิบายสิ่งที่เกิดขึ้นก่อนหน้านี้ในห่วงโซ่ได้หรือไม่? รหัสใน keyboard.c จะถูกเรียกได้อย่างไรเมื่อเรากด Ctrl + Alt + F1 keyboard.c ไม่ใช่ "ไดรเวอร์แป้นพิมพ์" จริงใช่ไหม?
user31765

1
ไม่ฉันไม่คิดอย่างนั้น มันเป็นส่วนหนึ่งของไดรเวอร์ tty ซึ่งkeyboard.cจะเป็นตัวจัดการเหตุการณ์ "ไดรเวอร์แป้นพิมพ์" นั้นจะอยู่ในระดับที่ต่ำกว่า - มีไดรเวอร์มากมายdrivers/input/keyboard/สำหรับสิ่งที่ไม่ใช่ usb สิ่งที่ USB เป็นมาตรฐานดังนั้นจะมีเพียงหนึ่ง (อาจเกี่ยวข้องกับdrivers/hid/usbhid/usbkbd.c) ฉันเดาว่าไดรเวอร์แป้นพิมพ์ใช้สำหรับการผลิตscancodeที่สามารถส่งมอบให้กับ vt / keyboard.c (ดูที่ getkeycode () ใกล้กับส่วนบนของสิ่งนั้น) Documentation/input/input.txtมีคำแนะนำบางอย่าง (โบราณที่เยี่ยมยอด, ฮ่า ๆ )
goldilocks

PS เคอร์เนล devs จำนวนมากอยู่ในรายชื่อเมลเคอร์เนล linux (LKML) ซึ่งเปิดให้สาธารณชนและถ้าคุณคำนึงถึง P & Qs ของคุณ ฯลฯ ( tux.org/lkml ) มันคุ้มค่าที่จะถามที่นั่น ... แค่ให้แน่ใจว่าคุณ ตั้งค่าโฟลเดอร์ได้ทันทีมีอีเมลจำนวนมากที่เกี่ยวข้อง
goldilocks

เมื่อตรวจสอบรหัสอย่างใกล้ชิดมีฟังก์ชันที่ไม่ล้าสมัยเพียงสามอย่างใน keyboard.c ซึ่งเรียกใช้ set_console: fn_lastcons (), fn_dec_console () และ fn_inc_console () หนึ่งอันสำหรับคอนโซลสุดท้ายและอีกตัวสำหรับไปทางขวาหรือซ้าย ดังนั้นฉันยังคงไม่เข้าใจว่า set_console () ถูกเรียกเมื่อเรากด Ctrl + Alt + F <num> ฉันคิดว่าเราต้องผ่าน <num> เป็นพารามิเตอร์เพื่อ set_console () ที่ไหนสักแห่ง ฉันเห็นว่า set_console () ปลูกพืชใน vt_ioctl.c ด้วย แต่นั่นไม่ใช่เพียงสำหรับ ioctl จากพื้นที่ผู้ใช้เช่นจาก chvt? ยังมีความเข้าใจของฉัน
user31765

1
มีสิ่งที่เกี่ยวข้องมากขึ้นในไดรเวอร์ / hid นอกจากนี้ยังสังเกตเห็น 'console_callback ()' ใน vt.c ซึ่งสามารถทำการสลับและลงทะเบียนที่ด้านบนผ่าน DECLARE_WORK สิ่งนี้เกี่ยวข้องกับตัวกำหนดตารางเวลา: lxr.free-electrons.com/ident?i=DECLARE_WORK (เครื่องมือตัวอ้างอิงโยงสามารถป้อนจากmakelinux.net/kernel_mapซึ่งคุณน่าสนใจ); ฉันคิดว่ามันทำให้ฟังก์ชั่นนั้นเป็น "main loop" สำหรับ vt เห็นได้ชัดว่าลิงค์ที่หายไปที่นี่คือสิ่งที่เหตุการณ์แป้นพิมพ์ผ่าน
goldilocks
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.