linux 串列埠驅動 console tty解析

2021-10-23 03:03:51 字數 3364 閱讀 5797

熟悉的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 串列埠也是一種終端裝置,在基本硬體操...