熟悉的for_each_console。遍歷console_drivers鍊錶。對於存在device成員的console,呼叫device方法。獲取tty_driver,退出遍歷。
之後對於該console裝置的讀寫操作都是基於該tty_driver。
全部的輸入輸出裝置都會註冊tty_driver。
所以,對於乙個新實現的輸入輸出裝置,假設想讓其即作為kernel的printk輸出裝置。也作為user空間的控制台。則須要在上面u_console基礎上再實現device方法成員,來返回該裝置的tty_driver。
那麼另乙個問題:
假設cmdline指定2個i/o裝置。「console=ttys0,115200 console=ttys1,115200」,user空間選擇哪個作為console?
使用者空間console open時,console_device遍歷console_drivers,找到有device成員的console。獲取tty_driver,就會退出遍歷。
所以哪個console放在console_drivers前面。就會被選擇為user空間的console。
在分析register_console時,假設要註冊的newcon是cmdline指定的最新的console(i = selected_console),則置位con_consdev。
而在後面newcon加入console_drivers時,推斷該置位。置位con_consdev,則將newcon加入到console_drivers的煉表頭,否則插入到後面。
所以這裡user空間會選擇ttys1作為使用者控制項的console!
總結下,kernel和user空間下都有乙個console,關係到kernel下printk的方向和user下printf的方向,實現區別還是非常大的。
kernel下的console是輸入輸出裝置driver中實現的簡單的輸出console,僅僅實現write函式,而且是直接輸出到裝置。
user空間下的console,實際就是tty的乙個樣例。全部操作函式都繼承與tty。全功能,能夠開啟 讀寫 關閉。所以對於console的讀寫。都是由kernel的tty層來終於傳送到裝置。
kernel的tty層之下還有ldisc線路規程層,線路規程層之下才是詳細裝置的driver。
ldisc層處理一些對於控制台來說有意義的輸入輸出字元,比方輸入的crtl+c。輸出的『\n『進過線路規程會變為』\n\r『。
所以對於kernel下console的write方法。不要忘記,對於log buf中'\n'的處理。實現乙個簡單的線路規程!
kernel下printk的輸出接管,可以通過for_each_console找到 原始的console。然後呼叫register_console,註冊自己的console
可以參考
user下printf的輸入輸出接管,tty_register_driver和tty_register_device註冊自己的tty驅動
參考:static struct tty_operations tty_lan_ops = ;
下面分析的code都在register_console 這個函式中
在register_console中,如果console_cmdline 中的console driver和selected_console相等,也就是下面的條件成立
if (i == selected_console)
這樣當註冊真正的console的時候下面的條件就會成立
if (bcon && ((newcon->flags & (con_consdev | con_boot)) == con_consdev))
newcon->flags &= ~con_printbuffer;
這樣下面這個if條件就不成了,因此console_seq 就不會被修改,還保持上一次earlycon 列印的值,也就是earlycon列印的log,真正的console不會重複列印
if (newcon->flags & con_printbuffer)
總結一下con_printbuffer這個flag,表示從buffer中的第一行log開始列印,而con_consdev表示從earlycon沒有列印的log開始列印,通過設定con_consdev來清零con_printbuffer,這樣就避免earlycon和real console的log的重複列印
tty_lan_driver = alloc_tty_driver(tty_lan_minors_num);
if(!tty_lan_driver)
return -enomem;
tty_lan_driver->owner = this_module;
tty_lan_driver->driver_name = "tty_sclu";
tty_lan_driver->name = "ttty_sclu";
tty_lan_driver->major = tty_lan_major,
tty_lan_driver->minor_start = 0;
tty_lan_driver->type = tty_driver_type_serial;
tty_lan_driver->subtype = serial_type_normal;
//tty_driver_dynamic_dev標誌表示手動註冊device裝置,在tty_io.c中會判斷,如果沒有該標誌,會呼叫tty_register_device,
//後續就不用再次註冊device裝置了
tty_lan_driver->flags = tty_driver_real_raw | tty_driver_dynamic_dev;
tty_lan_driver->init_termios = tty_std_termios;
tty_lan_driver->init_termios.c_cflag = b115200 | cs8 | cread | hupcl | clocal;
tty_set_operations(tty_lan_driver, &tty_lan_ops);
retval = tty_register_driver(tty_lan_driver);
if(retval)
tty_register_device(tty_lan_driver, 0, null);
return 0;
參考:
linux下串列埠(serial)和串列埠驅動
pc上的串列埠一般是ttys,板子上linux的串列埠一般叫做ttysac,是usb口轉串列埠的是ttyusb 外插串列埠卡的話預設是dev下的ttys 一般ttys0對應com1,ttys1對應com2 1.檢視串列埠的驅動資訊 cat proc tty driver serial 2.檢視串列埠...
Linux串列埠驅動分析read
串列埠read函式分析 當應用程式呼叫read系統呼叫時,會呼叫tty fops中的tty read 接下來分析tty read函式 其中最重要的就是ld ops read tty,file,buf,count 也就是呼叫線路規程中read函式 static ssize t tty read str...
Linux下串列埠 網絡卡驅動
一 串列埠 1 一台有輸入 顯示部件,然後能夠連線的計算機的裝置叫做終端。linux中用tty表示終端。控制台和終端相比只是多了一項功能,它可以顯示系統資訊,比如核心訊息 後台服務訊息。啟動linux核心前傳入的命令列引數 console 就是用來指定控制台。2 串列埠也是一種終端裝置,在基本硬體操...