1. 程式人生 > >《Linux Device Drivers》第十八章 TTY驅動程式——note

《Linux Device Drivers》第十八章 TTY驅動程式——note

  • 簡介
    • 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
  • 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);
  • ioctls
    • 當ioctl為一個裝置節點被呼叫時,tty核心將呼叫tty_driver結構中的ioctl回撥函式
    • 常用詞tty ioctl的列表
      • TIOCSERGETLSR
        • 獲得這個tty裝置線路狀態暫存器(LSR)的值
      • TIOCGSERIAL
        • 獲得序列線路資訊
      • TIOCSSERIAL
        • 設定序列線路資訊
      • TIOCMIWAIT
        • 等待MSR的變化
      • TIOCGICOUNT
        • 獲得中斷計數
  • 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驅動程式中的指標