在tty core代碼tty_io.c中,有如下幾行代碼
/* * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */static int __init tty_init(void){ cdev_init(&tty_cdev, &tty_fops); if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) panic("Couldn't register /dev/tty driver\n"); device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); cdev_init(&console_cdev, &console_fops); if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) panic("Couldn't register /dev/console driver\n"); device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");#ifdef CONFIG_VT vty_init(&console_fops);#endif return 0;}
這裡建立了幾個system級 終端裝置,他們並不是真實的物理裝置,每個都會建立這幾個裝置節點
/dev/tty
裝置號(5, 0)是裝置/dev/tty,表示當前進程的“控制終端”,並沒有代表任何物理意義上的終端,訪問裝置(5,0)就是訪問當前進程的”控制終端“。每一個進程通常都有一個“控制終端”。如果沒有,當開啟第一個終端裝置時,就把這個終端裝置設定為進程的"控制終端“(當然這個新開啟的終端必須代表具體的終端裝置)。如果我們不想把開啟的終端裝置作為進程的控制終端,那麼可以在系統調用open的參數flags中加入O_NOCTTY標識。
進程的控制終端存放在task_struct.signal->tty中。
個人認為引入/dev/tty (5,0)的意義在於,為應用程式層提供了訪問當前進程“控制終端”的short cut。我們可以在tty_open中看到如下代碼
if (device == MKDEV(TTYAUX_MAJOR, 0)) { tty = get_current_tty(); if (!tty) { unlock_kernel(); mutex_unlock(&tty_mutex); return -ENXIO; } driver = tty_driver_kref_get(tty->driver); index = tty->index; filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ /* noctty = 1; */ /* FIXME: Should we take a driver reference ? */ tty_kref_put(tty); goto got_driver; }
如果開啟的裝置節點是/dev/tty,那麼就操作get_current_tty返回的當前進程“控制終端”
/dev/tty0
主裝置號4,次裝置號0。表示當前虛擬控制台,在支援 虛擬控制台(console)的核心中有個全域量fg_console,表示當前的“前台控制台”。
/dev/console
主裝置號5, 次裝置號為1。用於外接控制台,核心在初始化的過程中安裝模組時會通過函數register_console,登記用做控制台的終端裝置,把一個console資料結構掛到核心中的console_drivers隊列中。
如果要開啟的終端裝置是/dev/console,那麼就在console_drivers隊列中找到第一個console結構,它所對應的裝置號就是當前系統控制台的裝置號