Liunx tty子系統分析之三 tty字符設備文件操作接口說明

本章主要介紹tty字符設備文件對應的操作接口,從而說明tty設備的數據打開、關閉、讀、寫等接口的實現等內容。

tyy file_operations定義

tty字符設備文件操作接口的定義如下,主要包括tty_fops、console_fops、hung_up_tty_fops,其中console_fops為控制檯設備的文件操作接口,hung_up_tty_fops為tty設備掛起後的文件操作接口,而tty_fops則為非控制檯設備的文件操作接口。

Liunx tty子系統分析之三 tty字符設備文件操作接口說明

在之前幾章的介紹中,我們已經說明過,在tty字符設備文件的打開操作後,完成tty_struct創‘建、tty_struct與tty_port、tty_struct與tty_ldisc等關聯,下面我們簡要分析下這幾個函數。

tty_open接口

針對tty_open接口而言,主要實現如下幾個功能:

  1. 若打開的tty設備為控制終端,則通過調用tty_open_current_tty湖區當前進程對應控制終端所對應的tty_struct指針;
  2. 若1中沒有找到對應tty_struct,則根據字符設備號從tty_drivers鏈表中查找已註冊的tty_driver,若該tty_driver與對應tty端口的tty_struct已完成綁定,則獲取對應的tty_struct指針;
  3. 若以上兩步均沒有獲取到tty端口對應的tty_struct,則說明該tty端口對應的tty_struct還沒有創建,則調用tty_init_dev完成tty_struct的創建,並完成tty_struct與tty_driver的綁定、tty_struct與tty_port、tty_struct與ldisc、tty_struct與tty device的綁定操作, 並調用tty_ldisc_setup,進行線路規程的打開(如termios的設置,ldisc的使能、ldisc緩存的初始化等)等等

針對tty_open接口,主要涉及如下幾個函數的調用:tty_open_current_tty、tty_driver_lookup_tty、tty_init_dev、initialize_tty_struct、tty_driver_install_tty等接口,而針對tty_init_dev接口而言,則主要實現tty_struct的創建以及各數據結構之間的關聯等信息。

tty_init_dev

1. 創建一個tty_struct類型的變量,用於完成一個tty_struct、tty_driver的綁定等操作

2.調用initialize_tty_struct,初始化tty_struct類型變量,包括根據tty端口的id、tty端口對應的device

tty端口對應tty_driver、線路規程等設置該tty_struct對應的成員

3.調用tty_driver_install_tty,完成tty_driver與tty_struct的綁定,並初始化tty_struct的termios參數

4.調用tty_ldisc_setup,打開線路規程的open接口(如設置termios、關閉流控、使能ldisc)等功能

5.完成tty_struct與tty_port的關聯


tty_read接口

當執行完成tty_open後,則完成了tty_driver、tty_port、tty device、tty_ldisc、tty_struct等數據結構的關聯,則可以與tty端口進行讀寫操作了。下面說明下tty_read的操作流程。

如下圖所示,針對應用程序讀tty端口的操作,主要包括如下幾個步驟:

  1. 應用程序read調用sys_read接口,由內核的vfs_read接口繼續進行讀操作;
  2. vfs_read則根據tty字符設備文件inode,調用tty_read進行讀操作;
  3. 而tty_read則通過tty_struct獲取其關聯的tty_ldisc,調用tty_ldisc的read接口;
  4. 在tty_ldisc的read接口中,從tty->ldisc_data中獲取已存儲的數據,若存儲的數據個數小於應用程序所需要讀取的個數,則將該讀進程加入到tty_struct->read_wait等待隊列中,等待數據可讀或者超時時間到期時,再次喚醒該讀進程。
  5. 在tty_driver的驅動中,在其接收中斷中,當接收到數據後,則將數據寫入到tty_port的緩存中(調用tty_insert_flip_char執行寫入操作),最後調用tty_flip_buffer_push接口,從而執行tty_port的buf對應的工作隊列,從而調用其回調函數flush_to_ldisc,而在flush_to_ldisc中會調用tty_ldisc->ops->receive_buff接口,將數據寫入到tty->ldisc_data的接收緩存中,並喚醒tty_struct->read_wait,喚醒該等待隊列上所有阻塞的讀進程。

Liunx tty子系統分析之三 tty字符設備文件操作接口說明

tty_write接口

針對tty_write的操作流程,與tty_read類似,下面說明下tty_read的操作流程。

如下圖所示,針對應用程序寫tty端口的操作,主要包括如下幾個步驟:

  1. 應用程序write調用sys_write接口,由內核的vfs_write接口繼續進行讀操作;
  2. vfs_write則根據tty字符設備文件inode,調用tty_write進行讀操作;
  3. 而tty_write'則通過tty_struct獲取其關聯的tty_ldisc,調用tty_ldisc的write接口;
  4. 在tty_ldisc的write接口中,調用tty_driver->ops->write接口進行寫操作,若當前需要寫入的數據沒有寫完,則將該寫進程加入到tty_struct->write_wait等待隊列中,等待數據可寫或者超時,再次喚醒該寫進程。
  5. 在tty_driver的驅動中,在其發送中斷中,若該tty端口可繼續進行數據的寫操作,則調用tty_wakeup,並喚醒tty_struct->write_wait,喚醒該等待隊列上所有阻塞的寫進程。

Liunx tty子系統分析之三 tty字符設備文件操作接口說明

tty_poll接口

該接口主要用於select、epoll機制,主要也是藉助tty_struct->read_wait、tty_struct->write_wait等待隊列,完成tty_poll接口的實現,此處不再展開。

tty_close接口

  1. 若當前tty_struct上僅有一個文件描述符,則該tty_struct變量也可以釋放掉,因此需要等待該文件描述符上所有已等待的讀寫隊列成員,並設置tty_struct是可釋放的;
  2. 調用tty_del_file,解除該文件描述符與tty_struct的關聯;

該接口主要調用release_tty、tty_ldisc_release、tty_ldisc_kill、tty_del_file等接口,用於解除tty_struct、tty_driver、tty_ldisc、tty_port、tty device之間的關聯。此處我們對release_tty進行簡要說明

release_tty接口

其實現的功能如下:

  1. 調用tty_driver->ops->shutdown,執行tty端口的關閉操作(如關閉收發中斷、停止接收與發送等功能);
  2. 調用tty_driver_remove_tty,去除tty_struct與tty_driver的關聯
  3. 調用tty_kref_put,tty_struct的引用計數減一,當tty_struct的引用計數為0時,則調用queue_release_one_tty,釋放該tty_struct的空間(包括調用tty_struct->cleanup釋放tty端口的資源,並釋放該tty_struct所佔用的空間)


本章主要介紹tty字符設備接口的文件操作接口,其open接口主要完成tty_struct創建、tty_driver、tty_port、tty_ldisc、tty device的關聯操作;而讀寫接口則主要藉助等待隊列、工作隊列完成對tty端口的讀寫操作。下一章則根據tty__register_driver、tty_port_register_device創建一個虛擬的tty串口驅動,以便我們不借助開發板也可以進行tty子系統驅動的學習工作。


分享到:


相關文章: