Điều gì xảy ra khi nhấn Ctrl + Alt + F <Num>?


38

Tôi đang tìm kiếm một lời giải thích về những gì xảy ra trong Linux khi tổ hợp phím này được nhấn để thay đổi thiết bị đầu cuối hiện tại. Cụ thể, thành phần phần mềm nào chặn tổ hợp phím này và thay đổi thiết bị đầu cuối? Nó có phải là hạt nhân không? Nếu đó là kernel, bạn có thể cung cấp vị trí của tệp nguồn xử lý việc này không?

Chỉnh sửa: Tôi muốn hiểu làm thế nào điều này hoạt động trong cả môi trường đồ họa (X11) và văn bản.


1
Để làm rõ, bạn có đang nhấn các phím này trong khi ở X11 (nghĩa là phiên đồ họa) hoặc trên bảng điều khiển văn bản không? Câu trả lời là khác nhau.
derobert

Câu trả lời:


36

Nó là hạt nhân. Hãy nhớ rằng bàn phím là phần cứng và mọi thứ xảy ra ở đó đều đi qua kernel; trong trường hợp chuyển đổi VT, nó tự xử lý sự kiện hoàn toàn và không chuyển bất kỳ thứ gì vào không gian người dùng (tuy nhiên, tôi tin rằng có một phương tiện liên quan đến ioctl có thể được thông báo về việc chuyển đổi xảy ra liên quan đến họ và có thể ảnh hưởng đến nó, mà X không nghi ngờ gì).

Hạt nhân có một sơ đồ xây dựng vào nó; điều này có thể được sửa đổi trong khi chạy với loadkeysvà được xem với 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
[...]   

Nguồn kernel chứa tệp keymap mặc định trông giống hệt như thế này; cho 3.12.2 src/drivers/tty/vt/defkeymap.map. Bạn cũng sẽ nhận thấy có một tệp defkeymap.c tương ứng (có thể được tạo bằng loadkeys --mktable). Việc xử lý nằm trong keyboard.c(tất cả các tệp này nằm trong cùng một thư mục) sẽ gọi set_console()từ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);

Tôi đã chỉnh sửa một số lượt truy cập ra khỏi danh sách đó; bạn có thể thấy chữ ký hàm trên dòng cuối cùng thứ hai.

Vì vậy, đây là những điều liên quan đến việc chuyển đổi. Nếu bạn nhìn vào chuỗi các cuộc gọi, cuối cùng bạn trở lại kbd_event()trong keyboard.c. Điều này được đăng ký như một trình xử lý sự kiện cho mô-đun:

(3.12.2 drivers/tty/vt/keyboard.cdòng 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);           

Do đó, kbd_event()nên được gọi khi một cái gì đó nổi lên từ trình điều khiển phần cứng thực tế (có thể là một cái gì đó từ drivers/hid/hoặc drivers/input/). Tuy nhiên, bạn sẽ không thấy nó được gọi là kbd_eventbên ngoài tệp đó, vì nó được đăng ký thông qua một con trỏ hàm.

Một số tài nguyên để xem xét kỹ lưỡng kernel

  • Các Linux Cross tham khảo Định danh Search là một công cụ tuyệt vời.
  • Các Interactive Linux Kernel Bản đồ là một đồ họa ngoại thú vị để các công cụ tham khảo chéo.
  • Có một vài tài liệu lưu trữ lịch sử của Danh sách gửi thư hạt nhân Linux (LKML) khổng lồ, trở lại ít nhất là năm 1995; một số trong số chúng không được duy trì và có các tính năng tìm kiếm bị hỏng, nhưng gmane dường như hoạt động rất tốt. Mọi người đã hỏi rất nhiều câu hỏi trong danh sách thư và đó cũng là một phương tiện liên lạc chính giữa các nhà phát triển.
  • Bạn có thể đưa các printkdòng của riêng mình vào nguồn như một phương tiện theo dõi đơn giản (không phải tất cả các lib C tiêu chuẩn đều có thể được sử dụng trong mã kernel, bao gồm printf từ stdio). công cụ printk kết thúc trong syslog.

Wolfgang Mauerer đã viết một cuốn sách lớn tuyệt vời về hạt nhân 2.6, Kiến trúc hạt nhân Linux chuyên nghiệp , đi qua rất nhiều nguồn. Greg Kroah-Hartman , một trong những nhà phát triển nguyên tắc trong thập kỷ qua, cũng có rất nhiều thứ đang đá xung quanh.


1
Cảm ơn, đây chính xác là những gì tôi đang tìm kiếm. Bạn có thể giải thích những gì xảy ra trước đó trong chuỗi không? Làm thế nào để mã trong keyboard.c được gọi khi chúng ta nhấn Ctrl + Alt + F1? keyboard.c không phải là "trình điều khiển bàn phím" thực sự, phải không?
user31765

1
Không, tôi không nghĩ vậy. Đó là tất cả các phần của trình điều khiển tty, mà keyboard.csẽ là một trình xử lý sự kiện; bản thân "trình điều khiển bàn phím" sẽ ở mức thấp hơn - có rất nhiều trong số chúng drivers/input/keyboard/dành cho những thứ không phải là usb. Công cụ USB được chuẩn hóa nên sẽ chỉ có một (có thể liên quan drivers/hid/usbhid/usbkbd.c). Tôi đoán rằng trình điều khiển bàn phím là để tạo ra một scancode có thể được trao cho vt / keyboard.c (xem getkeycode () ở gần đầu của nó). Documentation/input/input.txtcó một số gợi ý (tuyệt vời cổ xưa, lol).
goldilocks

Tái bút Nhiều nhà phát triển hạt nhân có trong danh sách thư hạt nhân linux (LKML) được mở cho công chúng và nếu bạn để ý đến P & Q của bạn, v.v. ( tux.org/lkml ) thì đáng để tìm hiểu ở đó ... chỉ cần đảm bảo với bạn thiết lập một thư mục cho nó ngay lập tức, có rất nhiều thư liên quan.
goldilocks

Khi kiểm tra mã chặt chẽ hơn, chỉ có ba hàm không lỗi thời trong keyboard.c gọi set_console: fn_lastcons (), fn_dec_console () và fn_inc_console (). Một để đi đến giao diện điều khiển cuối cùng và một để đi bên phải hoặc bên trái. Vì vậy, tôi vẫn không hiểu cách set_console () được gọi khi chúng ta nhấn Ctrl + Alt + F <num>. Tôi giả sử chúng ta phải truyền <num> làm tham số cho set_console () ở đâu đó. Tôi thấy rằng set_console () cũng mọc lên trong vt_ioctl.c, nhưng không phải chỉ dành cho ioctl từ không gian người dùng, ví dụ từ chvt? Vẫn còn một số lỗ hổng trong sự hiểu biết của tôi.
dùng31765

1
Có nhiều thứ có khả năng liên quan hơn trong trình điều khiển / ẩn. Cũng lưu ý 'console_callback ()' trong vt.c, có thể thực hiện chuyển đổi và được đăng ký ở trên cùng thông qua DECLARE_WORK. Điều này liên quan đến công cụ lên lịch: lxr.free-electrons.com/ident?i=DECLARE_WORK (công cụ tham chiếu chéo này có thể được cung cấp từ makelinux.net/kernel_map mà bạn có thể thấy thú vị); Tôi giả sử rằng làm cho chức năng đó là một "vòng lặp chính" cho vt. Rõ ràng liên kết bị thiếu ở đây chính xác là cách các sự kiện bàn phím được thông qua.
goldilocks
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.