《Linux Device Drivers》第十八章 TTY驅動程式——note
阿新 • • 發佈:2018-11-13
- 簡介
- tty裝置的名稱是從過去的電傳打字機縮寫而來,最初是指連線到Unix系統上的物理或虛擬終端
- Linux tty驅動程式的核心緊挨在標準字元裝置驅動層之下,並提供了一系列的功能,作為介面被終端型別裝置使用
- 有三種類型的tty驅動程式:控制檯、串列埠和pty
- /proc/tty/drivers
- 當前註冊並存在於核心的tty裝置在/sys/class/tty下都有自己的子目錄
- 小型TTY驅動程式
- <linux/tty_driver.h>
- struct tty_driver
- tiny_tty_driver = alloc_tty_driver(TINY_TTY_MINORS);
- static struct tty_operations serial_ops = {.open=tiny_open, .close=tiny_close, .write=tiny_write, .write_room=tiny_write_room, .set_termios=tiny_set_termios,}
- tiny_tty_driver->owner=THIS_MODULE;
- tiny_tty_driver->driver_name=”tiny_tty”;
- tiny_tty_driver->name=”ttty”;
- tiny_tty_driver->devfs_name=”tty/ttty%d”;
- tiny_tty_driver->major=TINY_TTY_MAJOR;
- tiny_tty_driver->type=TTY_DRIVER_TYPE_SERIAL;
- tiny_tty_driver->subtype=SERIAL_TYPE_NORMAL;
- tiny_tty_driver->flags=TTY_DRIVER_REAL_RAW|TTY_DRIVER_NO_DEVFS;
- tiny_tty_driver->init_termios=tty_std_termios;
- tiny_tty_driver->init_termios.c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL;
- tty_set_operaions(tiny_tty_driver, &serial_ops);
- retval = tty_register_driver(tiny_tty_driver);
- for (i=0;i<TINY_TTY_MINORS; ++i) tty_unregister_device(tiny_tty_driver, i);
- tty_unregister_driver(tiny_tty_driver);
- termios結構
- 用來提供一系列安全的設定值
- struct termios
- tcflag_t c_iflag;
- tcflag_t c_oflag;
- tcflag_t c_cflag;
- tcflag_c c_lflag;
- cc_t c_line;
- tty_driver函式指標
- open和close
- 當用戶使用open開啟由驅動程式分配的裝置節點時,tty核心將呼叫open函式
- 當呼叫open函式時,tty驅動程式或者將資料儲存到傳遞給它的tty_struct變數中
- 資料流
- 當資料要傳送給硬體時,使用者呼叫write函式
- 首先tty核心接收到了該呼叫,然後核心將資料傳送給tty驅動程式的write函式
- tty驅動程式在中斷上下文中時,它不會呼叫任何可能休眠的函式
- 當tty子系統本身需要將一些資料傳送到tty裝置之外時,可以呼叫write函式
- 當tty核心想知道由tty驅動程式提供的可用寫入緩衝區大小時,就會呼叫write_room函式
- 其他緩衝函式
- flush_chars
- wait_until_sent
- flush_buffer
- 怎麼沒有read函式
- 當tty驅動程式接收到資料後,它將負責把從硬體獲取的任何資料傳遞給tty核心,而不使用傳統的read函式
- tty核心將緩衝資料直到接到來自使用者的請求
- 在一個名為tty_flip_buffer的結構中,tty核心緩衝從tty驅動程式接收的資料
- tty_insert_flip_char
- tty_flip_buffer_push
- open和close
- TTY線路設定
- set_termios
- 大部分termios的使用者空間函式將會被庫轉換成對驅動程式節點的ioctl呼叫
- 大量的不同tty ioctl呼叫會被ttyp核心轉換成一個對tty驅動程式的set_termios函式呼叫
- tty驅動程式必須能夠對在termios結構中所有不同的設定進行解碼,並對任何需要的改變做出響應
- tiocmget和tiocmset
- 在2.4及更早的核心中,使用了大量的tty ioctl呼叫來獲得及設定不同的控制線路引數
- 這通過常量TIOCMGET、TIOCMBIS、TIOCMBIC和TIOCMSET來完成
- TIOCMGET用來獲得核心的線路設定值,在2.6.版本的核心中,該ioctl呼叫被tty驅動程式中的tiocmget回撥函式所代替
- 剩下的三個ioctl現在被簡化成tty驅動程式中的一個tiocmset回撥函數了
- int (*tiocmget) (struct tty_struct *tty, struct file *file);
- int (*tiocmset) (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
- set_termios
- ioctls
- 當ioctl為一個裝置節點被呼叫時,tty核心將呼叫tty_driver結構中的ioctl回撥函式
- 常用詞tty ioctl的列表
- TIOCSERGETLSR
- 獲得這個tty裝置線路狀態暫存器(LSR)的值
- TIOCGSERIAL
- 獲得序列線路資訊
- TIOCSSERIAL
- 設定序列線路資訊
- TIOCMIWAIT
- 等待MSR的變化
- TIOCGICOUNT
- 獲得中斷計數
- TIOCSERGETLSR
- proc和sys對TTY裝置的處理
- tty核心為任何tty驅動程式都提供了非常簡單的辦法,用來維護在/proc/tty/driver目錄中的一個檔案
- 如果驅動程式定義了read_proc或者write_proc函式,將建立該檔案,接著任何對該檔案的讀寫將被髮送給驅動程式
- tty_driver結構詳解
- tty_driver結構用來向tty核心註冊一個tty驅動程式
- struct tty_driver
- struct module *owner;
- int magic;
- 幻數
- const char *driver_name;
- 在/proc/tty和sysfs中使用,表示驅動程式的名字
- const char *name;
- 驅動程式節點的名字
- int name_base;
- 為建立裝置名字而使用的開始編號
- short major;
- 驅動程式的主裝置號
- short minor_start;
- 驅動程式使用的最小次裝置號
- short num;
- 可以分配驅動程式次裝置號的個數
- short type;
- TTY_DRIVER_TYPE_SYSTEM
- TTY_DRIVER_TYPE_CONSOLE
- TTY_DRIVER_TYPE_SERIAL
- TTY_DRIVER_TYPE_PTY
- short subtype;
- 描述向tty核心註冊的是何種tty驅動程式
- struct termios init_termios;
- 當被建立時,含有初始值的termios結構
- int flags;
- 驅動程式標誌位
- struct proc_dir_entry *proc_entry;
- 該驅動程式的/proc入口結構體
- struct tty_driver *other;
- 指向tty從屬裝置驅動程式的指標
- void *driver_state;
- tty驅動程式內部的狀態
- struct tty_driver *next;
- struct tty_driver *prev;
- 連結變數
- tty_operations結構詳解
- tty_operations結構中包含所有的回撥函式,它們被tty驅動程式設定,並被tty核心呼叫
- struct tty_operations
- int (*open) (struct tty_struct *tty, struct file *filp);
- int (*close) (struct tty_struct *tty, struct file *filp);
- int (*write) (struct tty_struct *tty, const unsigned char *buf, int count);
- void (*put_char) (struct tty_struct *tty, unsigned char ch);
- void (*flush_chars) (struct tty_struct *tty);
- void (*wait_until_sent) (struct tty_struct *tty, int timeout);
- int (*write_room) (struct tty_struct *tty);
- int (*chars_in_buffer) (struct tty_struct *tty);
- int (*ioctl) (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
- void (*set_termios) (struct tty_struct *tty, struct termios *old);
- void (*throttle) (struct tty_struct *tty);
- void (*unthrottle) (struct tty_struct *tty);
- void (*stop) (struct tty_struct *tty);
- void (*start) (struct tty_struct *tty);
- void (*hangup) (struct tty_struct *tty);
- void (*bread_ctl) (struct tty_struct *tty, int state);
- void (*flush_buffer) (struct tty_struct *tty);
- void (*set_ldisc) (struct tty_struct *tty);
- void (*send_xchar) (struct tty_struct *tty, char ch);
- int (*read_proc) (char *page, char **start, off_t off, int count, int *eof, void *data);
- int (*write_proc) (struct file *file, const char *buffer, unsigned long count, void *data);
- int (*tiocmget) (struct tty_struct *tty, struct file *file);
- int (*tiocset) (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
- tty_struct結構詳解
- tty核心使用tty_struct儲存當前特定tty埠的狀態
- struct tty_struct
- unsigned long flags;
- 當前tty裝置的狀態
- TTY_THROTTLED
- TTY_IO_ERROR
- TTY_OTHER_CLOSED
- TTY_EXCLUSIVE
- TTY_DEBUG
- TTY_DO_WRITE_WAKEUP
- TTY_PUSH
- TTY_CLOSING
- TTY_DONT_FLIP
- TTY_HW_COOK_OUT
- TTY_HW_COOK_IN
- TTY_PTY_LOCK
- TTY_NO_WRITE_SPLIT
- struct tty_flip_buffer flip;
- tty裝置的交替緩衝區
- struct tty_ldisc ldisc;
- tty裝置的線路規程
- wait_queue_head_t write_wait;
- 用於tty寫函式的wait_queue
- struct termios *termios;
- 指向設定tty裝置的termios結構指標
- unsigned char stopped:1;
- 表示tty裝置是否已經停止
- unsigned char hw_stopped:1
- 表示tty裝置硬體是否已經停止
- unsigned char low_latency:1
- 表示tty裝置是否是個慢速裝置
- unsigned char closing:1
- 表示tty裝置是否正在關閉埠
- struct tty_driver driver;
- 控制tty裝置的當前tty_driver結構
- void *driver_data;
- tty_driver用來把資料儲存在tty驅動程式中的指標
- unsigned long flags;