導航:首頁 > 操作系統 > linux控制台串口

linux控制台串口

發布時間:2022-11-06 11:21:35

linux 串口驅動程序術語介紹

在Linux中經常碰到「控制台」、「終端」、「console」、「tty」、「terminal」等術語,也經常使用到這些設備文件:ldevconsole、/dev/ttySACO、/dev/tty0等。要理解這些術語,需要從以前的計算機說起。
最初的計算機價格昂貴,一台計算機通常連接上多套鍵盤和顯示器供多人使用。在以前專門有這種可以連上一台電腦的設備,它只有顯示器和鍵盤,外加簡單的處理電路,本身不具有處理計算機信息的能力。用戶通過它連接到計算機上(通常是通過串口),然後登錄系統,並對計算機進行操作。這樣一台只有輸入、顯示部件(比如鍵盤和顯示器)並能夠連接到計算機的設備就叫做終端。tty 是Teletype 的縮寫,Teletype是最早出現的一種終端設備,很像電傳打字機。在Linux中,就用tty來表示「終端」,比如內核文件tty_io.c、tty _ioctl.c等都是與「終端」相關的驅動程序;設備文件/dev/ttySACO、/dev/tty0等也表示某類終端設備。「console」的意思即為「控制台」,顧名思義,控制台就是用戶與系統進行交互的設備,這和終端的作用相似。實際上,控制台與終端相比,也只是多了一項功能:它可以顯示系統信息,比如內核消息、後台服務消息。從硬體上看,控制台與終端都是具備輸入、顯示功能的設備,沒有區別。「控制台」、「終端」、「控制終端」這些名詞經常混著用,表示的是同一個意思。
控制台與終端的區別體現在軟體.上,Linux內核從很早以前發展而來,代碼中仍保留了「控制台」、「終端」的概念。啟動Linux內核前傳入的命令行參數「console=…」就是用來指定「控制台」的。控制台在tty 驅動初始化之前就可以使用了,它最開始的時候被用來顯示內核消息(比如 printk 函數輸出的消息)。

⑵ Linux C 配置串口

配置串口需要包含頭文件

其中最核心的配置結構體為:

如何獲取該結構呢?我們操作串口跟操作文件一樣,也是調用 open() 函數來打開串口,

這樣我們就能夠得到一個文件描述符 fd ,然後就可以調用 tcgetattr() 函數來獲取上述配置結構體了。

Linux 串口默認的配置為:波特率 9600,數據位 8 位,無奇偶校驗,停止位 1 位,無 CTS/RTS 。

以下介紹一些常用的配置項:波特率、奇偶校驗、數據位、停止位、硬體控制流。

相關介面:

Linux 將串口的波特率分為了輸入波特率和輸出波特率,不過最常用的場景是將兩者設置成一樣。

cfgetispeed() 函數獲取輸入波特率, cfgetospeed() 函數獲取輸出波特率。 cfsetispeed() 函數設置輸入波特率, cfsetospeed() 函數用於設置輸出波特率,當然 cfsetspeed() 函數擴展為同時設置輸入和輸出波特率。

上述介面中的 speed_t 是一系列波特率的標志位,例如常用的 115200 波特率就為 B115200,參考下述選項:

設置奇偶校驗位可以通過修改 termios 結構體中的 c_cflag 成員來實現,若無校驗,則將 PARENB 位設為 0;若有校驗,則 PARENB 為 1。之後再根據 PARODD 來區分奇偶校驗, PARODD 為 1 表示奇校驗, PARODD 為 0 表示偶校驗。例如設置無奇偶校驗位:

設置數據位可以通過修改 termios 結構體中的 c_cflag 成員來實現,CS5、CS6、CS7 和 CS8 分別代表數據位 5、6、7 和 8。不過在設置數據位之前,需要先用 CSIZE 來做屏蔽欄位,清楚這幾個標志位,例如設置數據位為 8 位:

設置停止位可以通過修改 termios 結構體中的 c_cflag 成員來實現, CSTOPB 位為 1 表示 2 位停止位, CSTOPB 位為 0 標志 1 位停止位。例如設置停止位為 1 位:

設置硬體控制流可以通過修改 termios 結構體中的 c_cflag 成員來實現, CRTSCTS 為 1 表示使用硬體控制流,為 0 表示不使用硬體控制流。例如使能硬體控制流:

當然,最後還需要用 tcflush() 拋棄存儲在 fd 里的未接收的數據。

再利用介面 tcsetattr() 函數將配置信息寫入文件描述符 fd :

這樣整個串口最常用的用法就配置完成了。

具體的配置使用可以參考我的項目 HCI-Middleware 里的 hci_transport_uart_linux.c 文件。

參考:

⑶ LINUX控制台怎麼定向到串口終端

利用串口終端作為Linux控制台,可以免去額外的鍵盤,顯示卡和顯示器,同時可將Linux主機作為一個任意用途的嵌入式黑匣。那麼LINUX控制台怎麼定向到串口終端?下面跟著學習啦小編一起來了解一下吧。
LINUX控制台怎麼定向到串口終端
目的: 台機已經裝好Linux,顯示器有問題,平時一般都SSH控制,當Linux網路掛的時候,想通過串口來管理。
硬體:台機自帶兩個串口(上面的是COM1)[under Windows] or ttyS0[under Linux)),筆記本T61p沒有串口,買了個USB轉串口(具體見下圖)。同時需要串口交叉線一根(NULL modem Cable),母對母(公的是針),都是凹口那種。
目標機器:安裝的CentOS 5.2 Linux 內核2.6.18-92.1.22.el5和2.6.18-92.1.22.el5xen
客戶端: Windows XP SP3 IBM OEM. 安裝USB轉串口驅動。
需要把輸出定向到串口,一般有下面幾處:
BIOS中的設置
GRUB設置
/etc/inittab 設置
/etc/securetty 設置
BIOS中的設置
BIOS設置的作用我沒嘗試過,如果是可以連BIOS設置都可以定向到串口,那個強大了。也不知道如何去掉機器需要連鍵盤的限制。沒拿出顯示器所以沒看我台機的BIOS,不過這個功能一般只有伺服器級別的機器有。【注1】台機一般沒有串口重定向功能。
GRUB設置
這里的配置是為了把grub菜單定向到串口,這樣你就可以在串口操作grub,選擇啟動項,使用single mode等等。
同時也要給kernel參數加上console選項。
[root@CentOS5 ~]# cat /boot/grub/menu.lst
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/vg00/lv_root
# initrd /initrd-version.img
#boot=/dev/hdb1
serial --unit=0 --speed=9600 --word=8 --parity=no --stop=1
terminal --timeout=10 serial console
default=2
timeout=20
#splashimage=(hd0,0)/grub/splash.xpm.gz =>這些在console下會工作不正常,注釋掉。
#hiddenmenu
title CentOS (2.6.18-92.1.22.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-92.1.22.el5 ro root=/dev/vg00/lv_root rhgb quiet
initrd /initrd-2.6.18-92.1.22.el5.img
title CentOS Serial[ttyS0] - Console (2.6.18-92.1.22.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-92.1.22.el5 ro root=/dev/vg00/lv_root console=ttyS0,9600 console=tty0
initrd /initrd-2.6.18-92.1.22.el5.img
title CentOS Console - serial[ttyS0] (2.6.18-92.1.22.el5) [get more output in serial console]
root (hd0,0)
kernel /vmlinuz-2.6.18-92.1.22.el5 ro root=/dev/vg00/lv_root console=tty0 console=ttyS0,9600
initrd /initrd-2.6.18-92.1.22.el5.img
title CentOS Xen (2.6.18-92.1.22.el5xen)
root (hd0,0)
kernel /xen.gz-2.6.18-92.1.22.el5
mole /vmlinuz-2.6.18-92.1.22.el5xen ro root=/dev/vg00/lv_root rhgb quiet xencons=off
mole /initrd-2.6.18-92.1.22.el5xen.img
title CentOS Xen Serial[ttyS0] - Console (2.6.18-92.1.22.el5xen)
root (hd0,0)
kernel /xen.gz-2.6.18-92.1.22.el5
mole /vmlinuz-2.6.18-92.1.22.el5xen ro root=/dev/vg00/lv_root xencons=off console=ttyS0,9600 console=tty0
mole /initrd-2.6.18-92.1.22.el5xen.img
title CentOS Xen Console - serial[ttyS0] (2.6.18-92.1.22.el5xen)
root (hd0,0)
kernel /xen.gz-2.6.18-92.1.22.el5
mole /vmlinuz-2.6.18-92.1.22.el5xen ro root=/dev/vg00/lv_root xencons=off console=tty0 console=ttyS0,9600
mole /initrd-2.6.18-92.1.22.el5xen.img
title Other
rootnoverify (hd0,0)
chainloader +1
後面的console有順序關系,詳見下文【注2】,我常用串口所以console=tty0 console=ttyS0,9600這個順序的輸出信息比較多。
因為我的機器有xen的內核,xen默認情況下會把串口做為xencons,所以這里設置xencons=off.
When multiple consoles are listed output is sent to all consoles and input is taken from the last listed console. The last console is the one Linux uses as the /dev/consoledevice.
/etc/inittab 設置
系統系統後,需要在串口上監聽請求,所以要有個類似伺服器的程序(agetty, mgetty etc)。
/etc/inittab中添加
s0:2345:respawn:/sbin/agetty -L -f /etc/issue.serial 9600 ttyS0 vt100
#s1:2345:respawn:/sbin/agetty -L -f /etc/issue.serial 9600 ttyS1 vt100
#S0:2345:respawn:/sbin/mgetty -r -x 9 ttyS0 ==> mgetty 用來調試比較好,log也豐富。
What is a getty?
A getty is is a program that opens a tty port, prompts for a login name, and runs the /bin/login command. It is normally invoked by init.
所以其他程序就不能再來佔用ttyS0了,串口是獨占模式的吧。
vt100:
vt100 is the terminal emulation. You can use others, but VT100 is the most common or "standard". Another widely used termial type is VT102.
OK都可以了,可以重啟server了。這里如果想測試下串口線,推薦先在Linux啟動下mgetty,因為他的debug信息和log比較豐富,適合排錯和測試。
#mgetty –r –x 9 ttyS0
Log在/var/log/mgetty*中。
/etc/securetty設置
因為一般我們都是使用root登陸串口來維護,所以需要設置root可以在COM1和COM2登陸。
在/etc/securetty中添加:
ttyS0
ttyS1
Windows客戶端連接可以用超級終端或者Putty。
注意啟動server的時候,putty就應該去連接串口了,這樣才可以看到所有信息。
本來正常情況下,接下去kernel的boot信息應該也會打到串口的。但是沒有,確定是Xen內核的關系。
系統啟動起來後,過了init,agetty就起來了,這個時候就可以通過串口登陸了。(在/etc/securetty中需要添加ttyS0)
看過「 LINUX控制台怎麼定向到串口終端 」的人還看了:

⑷ Linux如何配製成在啟動的時候默認選擇串口作為控制台,不輸出到顯示器

vim /etc/grub.conf配置里
在kernel那一行的,最後加上" console=ttyS0,115200"就可以了
註:console前要有空格,S0這個是S零

⑸ 如何查看linux下串口是否可用串口名稱等

1、查看串口是否可用,可以對串口發送數據比如對com1口,echo lyjie126 > /dev/ttyS0

2、查看串口名稱使用 ls -l /dev/ttyS* 一般情況下串口的名稱全部在dev下面,如果你沒有外插串口卡的話默認是dev下的ttyS* ,一般ttyS0對應com1,ttyS1對應com2,當然也不一定是必然的;

3、查看串口驅動:cat /proc/tty/drivers/serial

4、查看串口設備:dmesg | grep ttyS*

(5)linux控制台串口擴展閱讀

介面劃分標准

同步串列介面(英文:SynchronousSerialInterface,SSI)是一種常用的工業用通信介面。。

非同步串列是指UART(Universal Asynchronous Receiver/Transmitter),通用非同步接收/發送。UART是一個並行輸入成為串列輸出的晶元,通常集成在主板上。UART包含TTL電平的串口和RS232電平的串口。 TTL電平是3.3V的,而RS232是負邏輯電平,它定義+5~+12V為低電平,而-12~-5V為高電平,MDS2710、MDS SD4、EL805等是RS232介面,EL806有TTL介面。

串列介面按電氣標准及協議來分包括RS-232-C、RS-422、RS485等。RS-232-C、RS-422與RS-485標准只對介面的電氣特性做出規定,不涉及接插件、電纜或協議。

⑹ 如何在紅帽企業Linux下設置串口終端

一個串口控制台將發送所有的終端顯示到串口,而串口終端則可以實現通過串口登錄到系統。你可以同時設置兩個或者其中一個。 為了控制內核輸出所有控制台消息到串口,你需要在時向內核傳遞參數console=ttyS0,這可以通過GRUB來實現,下面的例子會將控制台消息發送到tty0(顯示器控制台)和ttyS0(串口1),發送到串口控制台的速度為115200,但是需要注意的是一種類型設備只能定義一個控制台,例如不能把消息同時發送到串口1和串口2,編輯/boot/grub/grub.conf,添加如下內容: console=ttyS0,115200 console=tty0 例如: # cat /boot/grub/grub.conf# grub.conf generated by anaconda## Note that you do not have to rerun grub after making changes to this file# NOTICE: You have a /boot partition. This means that# all kernel and initrd paths are relative to /boot/, eg.# root (hd0,0)# kernel /vmlinuz-version ro root=/dev/hda2# initrd /initrd-version.img#boot=/dev/hdadefault=0timeout=10splashimage=(hd0,0)/grub/splash.xpm.gztitle Red Hat Enterprise Linux AS (2.4.21-27.0.2.ELsmp) root (hd0,0) kernel /vmlinuz-2.4.21-27.0.2.ELsmp ro root=LABEL=/ console=ttyS0,115200 console=tty0 initrd /initrd-2.4.21-27.0.2.ELsmp.img 串口終端 為了設置一個串口終端,需要為串口衍生(spawn)一個agetty,在/etc/inittab添加如下內容: co:2345:respawn:/sbin/agetty ttyS0 115200 vt100 init q 例如: # Run gettys in standard runlevels1:2345:respawn:/sbin/mingetty tty12:2345:respawn:/sbin/mingetty tty23:2345:respawn:/sbin/mingetty tty34:2345:respawn:/sbin/mingetty tty45:2345:respawn:/sbin/mingetty tty56:2345:respawn:/sbin/mingetty tty6co:2345:respawn:/sbin/agetty ttyS0 115200 vt100 init q 也可以在/etc/securetty文件中添加串口設置,這樣才可以以root身份從串口登錄,在該文件最後添加一行,內容為 ttyS0 (如果不添加此行,則登錄時會不能輸入密碼。

⑺ Linux怎麼把串口設置

簡單的運行 dmesg 命令
$ dmesg | grep tty
輸出:
[ 37.531286] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 37.531841] 00:0b: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[ 37.532138] 0000:04:00.3: ttyS1 at I/O 0x1020 (irq = 18) is a 16550A

setserial 命令
setserial 是一個程序用於設定並/或報告某個串口關聯的配置信息。該信息包括串口用到的I/O 埠和中斷號,以及Break鍵是否應被解釋為Secure Attention Key 等等。 僅僅是輸出如下的命令:
$ setserial -g /dev/ttyS[0123]
輸出:
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: 16550A, Port: 0x1020, IRQ: 18
/dev/ttyS2, UART: unknown, Port: 0x03e8, IRQ: 4
/dev/ttyS3, UART: unknown, Port: 0x02e8, IRQ: 3

帶-g選項的setserial幫助找到你的Linux板子上的物理串口。
Linux 串口控制台程序
一旦串口被確定了,你就能使用許多的工具來配置Linux板子:
minicom- 用於控制modem和連接到mp 設備的最好的串口通信程序。
wvidial or other GUI dial up networking program - 一個內建智能PPP 撥號器。
getty / agetty - agetty 打開一個 tty 埠, 提示登錄名稱並調用 /bin/login 命令。
grub / lilo configuration - 配置串口為系統控制台。

⑻ linux下怎樣對串口編程

使用串口協議登錄Linux終端控制台,通過Zmodem文件傳輸協議接收一個外部文件。 命令:rz -y 會彈出文件瀏覽窗口,選擇要上傳的文件即可。 -y 表示若文件已存在,則覆蓋。

⑼ LINUX控制台怎麼定向到串口終端

物理連接好串口; 然後配置: 編輯/boot/grub/grub.conf ,添加內容: console=ttyS0,115200 console=tty0 在/etc/securetty在該文件最後添加一行,內容為:ttyS0 確定安裝好服務/客戶端好就ok了。。

⑽ linux 啟動時何時初始化console,串口等

1、LINUX下TTY、CONSOLE、串口之間是怎樣的層次關系?具體的函數介面是怎樣的?串口是如何被調用的?


2、printk函數是把信息發送到控制台上吧?如何讓PRINTK把信息通過串口送出?或者說系統在什麼地方來決定是將信息送到顯示器還是串口?


3、start_kernel中一開始就用到了printk函數(好象是printk(linux_banner什麼的),在 這個時候整個內核還沒跑起來呢那這時候的printk是如何被調用的?在我們的系統中,系統啟動是用的現代公司的BOOTLOADER程序,後來好象跳到了LINUX下的head-armv.s, 然後跳到start_kernel,在bootloader 里串口已經是可用的了,那麼在進入內核後是不是要重新設置?


以上問題可能問的比較亂,因為我自己腦子里也比較亂,主要還是對tty,console,serial之間的關系,特別是串口是如何被調用的沒搞清這方面的資料又比較少(就情景分析中講了一點),希望高手能指點一二,非常謝!

我最近也在搞這方面的東西,也是寫一個串口設備的驅動

搞了將近一個月了,其中上網找資料,看源代碼,什麼都做了

但還是一蹋糊塗的,有些問題還是不明白,希望一起討論討論


在/proc/device(沒記錯應該是這個文件)

裡面有一個叫serial的驅動,其主設備號是4,次設備號是64-12X(沒記錯應該是這個范圍)

大家都知道,串口的次設備號是從64開始的,串口1 /dev/ttyS0就對應次設備號64,串口2就對應65

問題是現在我機上只有兩個串口,它注冊這么多次設備號來干什麼?


對於一個接在串口1的設備,在我注冊驅動的時候

我是需要自己找一個主設備號呢?

還是就用主設備號4,次設備號從上面12X的後面選?

還是就用主設備號4,次設備號64?


在linux的內核中有一個tty層,我看好像有些串口驅動是從這里開始的

例如調用tty_register_driver()來注冊驅動

就像在pci子系統里調用pci_register_driver()那樣的

那麼,用這種機制來注冊的驅動,

它是直接對串口的埠操作呢(例如用inb(),outb()....之類的)

還是某些更底層的驅動介面呢?


這些問題纏了我很久都沒解決,搞得最後不得不放棄

現在轉向用戶空間的應用程序,看能不能有些更高效的方法來實現

(在用戶空間只能用open("/dev/ttyS0", O_RDWR)來實現了)

另外還有,系統里已經為我們實現了串口的驅動

所以我們在用戶空間的程序里直接open("/dev/ttyS0")就可用了

但是現在要寫的是接在串口上的設備的驅動

在內核模塊中可不可以包含某個頭文件,然後就可以直接用串口驅動中的介面呢?

看到你們的問題後,感覺很有典型性,因此花了點工夫看了一下,做了一些心得貼在這里,歡迎討論並指正:

1、LINUX下TTY、CONSOLE、串口之間是怎樣的層次關系?具體的函數介面是怎樣的?串口是如何被調用的?

tty和console這些概念主要是一些虛設備的概念,而串口更多的是指一個真正的設備驅動Tty實際是一類終端I/O設備的抽象,它實際上更多的是一個管理的概念,它和tty_ldisc(行規程)和tty_driver(真實設備驅動)組合在一起,目的是向上層的VFS提供一個統一的介面通過file_operations結構中的tty_ioctl可以對其進行配置。查tty_driver,你將得到n個結果,實際都是相關晶元的驅動因此,可以得到的結論是(實際情況比這復雜得多):每個描述tty設備的tty_struct在初始化時必然掛如了某個具體晶元的字元設備驅動(不一定是字元設備驅動),可以是很多,包括顯卡或串口chip不知道你的ARM Soc是那一款,不過看情況你們應該用的是常見的chip,這些驅動實際上都有而console是一個緩沖的概念,它的目的有一點類似於tty實際上console不僅和tty連在一起,還和framebuffer連在一起,具體的原因看下面的鍵盤的中斷處理過程Tty的一個子集需要使用console(典型的如主設備號4,次設備號1―64),但是要注意的是沒有console的tty是存在的

而串口則指的是tty_driver舉個典型的例子:

分析一下鍵盤的中斷處理過程:

keyboard_interrupt―>handle_kbd_event―>handle_keyboard_event―>handle_scancode

void handle_scancode(unsigned char scancode, int down)

{

……..

tty = ttytab? ttytab[fg_console]: NULL;

if (tty && (!tty->driver_data)) {

……………

tty = NULL;

}

………….

schele_console_callback();

}

這段代碼中的兩個地方很值得注意,也就是除了獲得tty外(通過全局量tty記錄),還進行了console 回顯schele_console_callbackTty和console的關系在此已經很明了!!!


2、printk函數是把信息發送到控制台上吧?如何讓PRINTK把信息通過串口送出?或者說系統在什麼地方來決定是將信息送到顯示器還是串口?

具體看一下printk函數的實現就知道了,printk不一定是將信息往控制台上輸出,設置kernel的啟動參數可能可以打到將信息送到顯示器的效果。函數前有一段英文,很有意思:

/*This is printk. It can be called from any context. We want it to work.

*

* We try to grab the console_sem. If we succeed, it's easy - we log the output and

* call the console drivers. If we fail to get the semaphore we place the output

* into the log buffer and return. The current holder of the console_sem will

* notice the new output in release_console_sem() and will send it to the

* consoles before releasing the semaphore.

*

* One effect of this deferred printing is that code which calls printk() and

* then changes console_loglevel may break. This is because console_loglevel

* is inspected when the actual printing occurs.

*/

這段英文的要點:要想對console進行操作,必須先要獲得console_sem信號量如果獲得console_sem信號量,則可以「log the output and call the console drivers」,反之,則「place the output into the log buffer and return」,實際上,在代碼:

asmlinkage int printk(const char *fmt, ...)

{

va_list args;

unsigned long flags;

int printed_len;

char *p;

static char printk_buf[1024];

static int log_level_unknown = 1;

if (oops_in_progress) { /*如果為1情況下,必然是系統發生crush*/

/* If a crash is occurring, make sure we can't deadlock */

spin_lock_init(&logbuf_lock);

/* And make sure that we print immediately */

init_MUTEX(&console_sem);

}

/* This stops the holder of console_sem just where we want him */

spin_lock_irqsave(&logbuf_lock, flags);

/* Emit the output into the temporary buffer */

va_start(args, fmt);

printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);/*對傳入的buffer進行處理,注意還不是

真正的對終端寫,只是對傳入的string進行格式解析*/

va_end(args);

/*Copy the output into log_buf. If the caller didn't provide appropriate log level tags, we insert them here*/

/*注釋很清楚*/

for (p = printk_buf; *p; p++) {

if (log_level_unknown) {

if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {

emit_log_char('<');

emit_log_char(default_message_loglevel + '0');

emit_log_char('>');

}

log_level_unknown = 0;

}

emit_log_char(*p);

if (*p == ' ')

log_level_unknown = 1;

}

if (!arch_consoles_callable()) {

/*On some architectures, the consoles are not usable on secondary CPUs early in the boot process.*/

spin_unlock_irqrestore(&logbuf_lock, flags);

goto out;

}

if (!down_trylock(&console_sem)) {

/*We own the drivers. We can drop the spinlock and let release_console_sem() print the text*/

spin_unlock_irqrestore(&logbuf_lock, flags);

console_may_schele = 0;

release_console_sem();

} else {

/*Someone else owns the drivers. We drop the spinlock, which allows the semaphore holder to

proceed and to call the console drivers with the output which we just proced.*/

spin_unlock_irqrestore(&logbuf_lock, flags);

}

out:

return printed_len;

}

實際上printk是將format後的string放到了一個buffer中,在適當的時候再加以show,這也回答了在start_kernel中一開始就用到了printk函數的原因


3、start_kernel中一開始就用到了printk函數(好象是printk(linux_banner什麼的),在這個時候整個內核還沒跑起來呢。那這時候的printk是如何被調用的?在我們的系統中,系統啟動是用的現代公司的BOOTLOADER程序,後來好象跳到了LINUX下的head-armv.s, 然後跳到start_kernel,在bootloader 里串口已經是可用的了,那麼在進入內核後是不是要重新設置?

Bootloader一般會做一些基本的初始化,將kernel拷貝物理空間,然後再跳到kernel去執行。可以肯定的是kernel肯定要對串口進行重新設置,原因是Bootloader有很多種,有些不一定對串口進行設置,內核不能依賴於bootloader而存在。


多謝樓上大俠,分析的很精闢。我正在看printk函數。


我們用的CPU是hynix的hms7202。在評估板上是用串口0作

控制台,所有啟動過程中的信息都是通過該串口送出的。

在bootloader中定義了函數ser_printf通過串口進行交互。


但我還是沒想明白在跳轉到linux內核而console和串口尚未

初始化時printk是如何能夠工作的?我看了start_kernel

的過程(並通過超級終端作了一些跟蹤),console的初始化

是在console_init函數里,而串口的初始化實際上是在1號

進程里(init->do_basic_setup->do_initcalls->rs_init),

那麼在串口沒有初始化以前prink是如何工作的?特別的,在

start_kernel一開始就有printk(linux_banner),而這時候

串口和console都尚未初始化呢。

  1. 在start_kernel一開始就有printk(linux_banner),而這時候串口和console都尚未初始化?

  2. 仔細分析printk可以對該問題進行解答代碼中的:

  3. /* Emit the output into the temporary buffer */

  4. va_start(args, fmt);

  5. printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);

  6. va_end(args);

  7. 將輸入放到了printk_buf中,接下來的

  8. for (p = printk_buf; *p; p++) {

  9. if (log_level_unknown) {

  10. if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {

  11. emit_log_char('<');

  12. emit_log_char(default_message_loglevel + '0');

  13. emit_log_char('>');

  14. }

  15. log_level_unknown = 0;

  16. }

  17. emit_log_char(*p);

  18. if (*p == ' ')

  19. log_level_unknown = 1;

  20. }

  21. 則將printk_buf中的內容進行解析並放到全局的log_buf(在emit_log_char函數)中if (!down_trylock(&console_sem)) {

  22. /*

  23. * We own the drivers. We can drop the spinlock and let

  24. * release_console_sem() print the text

  25. */

  26. spin_unlock_irqrestore(&logbuf_lock, flags);

  27. console_may_schele = 0;

  28. release_console_sem();

  29. } else {

  30. /*

  31. * Someone else owns the drivers. We drop the spinlock, which

  32. * allows the semaphore holder to proceed and to call the

  33. * console drivers with the output which we just proced.

  34. */

  35. spin_unlock_irqrestore(&logbuf_lock, flags);

  36. }

  37. 則是根據down_trylock(&console_sem)的結果調用release_console_sem(),在release_console_sem()中才真正的對全局的log_buf中的內容相應的console設備驅動進行處理。至此,可以得到如下的一些結論:

  38. (1)printk的主操作實際上還是針對一個buffer(log_buf),該buffer中的內容是否顯示(或者說向終端輸出),則要看是否可以獲得console_sem(2)printk所在的文件為printk.c,是和體系結構無關的,因此對任何平台都一樣。 可以推測的結論是:

  39. (1)kernel在初始化時將console_sem標為了locked,因此在start_kernel一開始的printk(linux_banner)中實際只將輸入寫入了緩沖,等在串口和console初始化後,對printk的調用才一次將緩沖中的內容向串口和console輸出。 (2)在串口和console的初始化過程中,必然有對console_sem的up操作。

  40. (3)因此,在embedded的調試中,如果在console的初始化之前系統出了問題,不會有任何的輸出。 唯一可以使用的只能是led或jtag了。(4)因此,你的問題可以看出解答。2.console的初始化.

  41. 不知道你用的是那一個內核版本,在我看的2.4.18和2.4.19中,都是在start_kernel中就對console進行的初始化。從前面的分析來看,console的初始化不應該太晚,否則log_buf有可能溢出。

  42. 多謝樓上,分析的很精彩!

我們用的內核版本是2.4.18,console的初始化確實是在

start_kernel->console->init。關於tty和串口,我這里還想再問一下tty設備的操作的總入口


static struct file_operations tty_fops = {

llseek: no_llseek,

read: tty_read,

write: tty_write,

poll: tty_poll,

ioctl: tty_ioctl,

open: tty_open,

release: tty_release,

fasync: tty_fasync,

};


而對串口的操作定義在:


static struct tty_driver serial_driver 這個結構中

serial.c中的多數函數都是填充serial_driver中的函數指針

那麼在對串口操作時,應該是先調用tty_fops中的操作(比如

tty_open等),然後再分流到具體的串口操作(rs_open等)吧?

但tty_driver(對串口就是serial_driver)中有很多函數指針

並不跟file_operations中的函數指針對應,不知道這些對應

不上的操作是如何被執行的?比如put_char,flush_char,read_proc,

write_proc,start,stop等。

以下是我對這個問題的一些理解:

這實際上還是回到原先的老問題,即tty和tty_driver之間的關系。從實現上看,tty_driver實際上是tty機制的實現組件之一,借用面向對象設計中的常用例子,這時的tty_driver就象是tty這部汽車的輪胎,tty這部汽車要正常運行,還要tty_ldisc(行規程),termios,甚至struct tq_struct tq_hangup(看tty_struct)等基礎設施。它們之間的關系並非繼承。至於tty_driver中的函數指針,再打個C++中的比喻,它們實際上很象虛函數,也就是說,可以定義它們,但並不一定實現它們、實際上還不用說tty_driver,只要查一下serial_driver都會發現n多個具體的實現,但對各個具體的設備,其tty_driver中的函數不一定全部實現、所以put_char,flush_char,read_proc, write_proc,start,stop這些函數的情況是有可能實現,也有可能不實現 即使被實現,也不一定為上層(VFS層)所用.

閱讀全文

與linux控制台串口相關的資料

熱點內容
dvd光碟存儲漢子演算法 瀏覽:758
蘋果郵件無法連接伺服器地址 瀏覽:963
phpffmpeg轉碼 瀏覽:672
長沙好玩的解壓項目 瀏覽:145
專屬學情分析報告是什麼app 瀏覽:564
php工程部署 瀏覽:833
android全屏透明 瀏覽:737
阿里雲伺服器已開通怎麼辦 瀏覽:803
光遇為什麼登錄時伺服器已滿 瀏覽:302
PDF分析 瀏覽:486
h3c光纖全工半全工設置命令 瀏覽:143
公司法pdf下載 瀏覽:383
linuxmarkdown 瀏覽:350
華為手機怎麼多選文件夾 瀏覽:683
如何取消命令方塊指令 瀏覽:350
風翼app為什麼進不去了 瀏覽:779
im4java壓縮圖片 瀏覽:362
數據查詢網站源碼 瀏覽:151
伊克塞爾文檔怎麼進行加密 瀏覽:893
app轉賬是什麼 瀏覽:163