14.4 資料傳送和接收
圖 14.3 所示終端裝置資料傳送和接收過程中的資料流以及函式呼叫關係。
圖 14.3 終端裝置資料傳送和接收過程中的資料流以及函式呼叫關係
使用者在有資料傳送給終端裝置時,通過「write()系統呼叫 — tty 核心 — 線路規程」的層層呼叫,最終呼叫 tty_driver結構體中的 write()函式完成傳送。
因為傳輸速度和 tty 硬體緩衝區容量的原因,不是所有的寫程式要求的字元都可以在呼叫寫函式時被傳送,因此寫函式應當返回能夠傳送給硬體的位元組數以便使用者程式檢查是否所有的資料被真正寫入。如果在 write()呼叫期間發生任何錯誤,乙個負的錯誤碼應當被返回。
tty_driver 的 write()函式接受 3 個引數 tty_struct、傳送資料指標及要傳送的位元組數。
int (*write)(struct tty_struct * tty, const unsigned char *buf, int count);
一般首先會通過 tty_struct 的 driver_data 成員得到裝置私有資訊結構體,然後依次進行必要的硬體操作開始
傳送,**清單 14.6 為 tty_driver 的 write()。
**清單 14.6 tty_driver 結構體的 write()成員函式
static int ***_write(struct tty_struct *tty, const unsigned char *buf, int count)
/* 拷貝到傳送緩衝區 */
memcpy(***->xmit_buf + ***->xmit_head, buf, c);
***->xmit_head = (***->xmit_head + c) &(serial_xmit_size - 1);
***->xmit_cnt += c;
local_irq_restore(flags);/*恢復儲存的中斷狀態標誌,使能當預處理器上的中斷*/
buf += c;
count -= c;
total += c;
}if (***->xmit_cnt && !tty->stopped && !tty->hw_stopped)
start_xmit(***);/* 開始傳送 */
return total; /* 返回傳送的位元組數 */
}當 tty 子系統自己需要傳送資料到 tty 裝置時,如果沒有實現 put_char()函式,write()函式將被呼叫,此時傳入的 count 引數為 1,通過對**清單 14.7 的分析即可獲知。
**清單 14.7 put_char()函式的 write()替代
drivers/char/tty_io.c
/** called by a tty driver to register itself.
*/int tty_register_driver(struct tty_driver *driver)
if (!driver->major)
} else
if (error < 0)
if (p) else
cdev_init(&driver->cdev, &tty_fops);
driver->cdev.owner = driver->owner;
error = cdev_add(&driver->cdev, dev, driver->num);
if (error)
if (!driver->put_char)//沒有定義 put_char()函式
driver->put_char = tty_default_put_char;
mutex_lock(&tty_mutex);
list_add(&driver->tty_drivers, &tty_drivers); /* 臨界資源 */
mutex_unlock(&tty_mutex);
if ( !(driver->flags & tty_driver_dynamic_dev) )
proc_tty_register_driver(driver);
return 0;}/*
* the default put_char routine if the driver did not define one.
*/static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
備註:tty_operations 結構體中沒有提供 read()函式。因為傳送是使用者主動的,而接收即使用者調 read()則是讀一片緩衝區中已放好的資料。tty 核心在乙個稱為 struct tty_flip_buffer 的結構體中緩衝資料直到它被使用者請求。因為 tty 核心提供了緩衝邏輯,因此每個 tty驅動並非一定要實現它自身的緩衝邏輯。
tty 驅動不必過於關心 tty_flip_buffer 結構體的細節,如果其 count 字段大於或等於 tty_flipbuf_size,這個 flip 緩衝區就需要被重新整理到使用者,重新整理通過對 tty_flip_buffer_push()函式的呼叫來完成。
**清單 14.8 tty_flip_buffer_push()範例
for (i = 0; i < data_size; ++i)
tty_flip_buffer_push(tty);
分析:從 tty 驅動接收到字元將被 tty_insert_flip_char()函式插入 flip 緩衝區。該函式的第 1 個引數是資料應當儲存入的 tty_struct 結構體,第 2 個引數是要儲存的字元,第 3 個引數是應當為這個字元設定的標誌,如果字元是乙個接收到的常規字元,則設為 tty_normal,如果是乙個特殊型別的指示錯誤的字元,依據具體的錯誤型別,應當設為 tty_break、tty_parity 或tty_overrun。
Linux 終端裝置驅動
1 控制台 1 控制台是乙個虛擬的終端,它必須對映到真正的終端上 2 控制台是個只輸出的裝置,功能很簡單,只能在核心中訪問 2 偽終端 一種特殊的終端裝置,由主 從兩個成對的裝置構成,當開啟主裝置時,對應的從裝置隨之開啟,形成連線狀態 輸入到主裝置的資料成為從裝置的輸出,輸入到從裝置的資料成為主裝置...
Linux終端裝置驅動(三)
圖14.5 串列埠核心層 串列埠核心層為串列埠裝置驅動提供了如下3個結構體 1 uart driver uart driver包含串列埠裝置的驅動名 裝置名 裝置號等資訊,它封裝了tty driver,使得底層的uart驅動無需關心tty driver,其定義如 清單14.13。清單14.13 ua...
linux 終端裝置
終端解釋 終端是一種字元型裝置,它有多種型別,通常使用tty來簡稱各種型別的終端裝置。tty是teletype的縮寫。teletype是最早出現的一種終端裝置,很象電傳打字機 或者說就是 是由teletype公司生產的。在linux系統的裝置特殊檔案目錄 dev 下,終端特殊裝置檔案一般有以下幾種 ...