TTY终端设备文件接口的基本结构

 TTY终端设备文件接口的基本结构
=============================
1) 在操作系统中, 应用程序一般不能直接操作硬件, 只能通过系统调用按照内核所提供的抽象形式来间接访问硬件. 在Linux系统中, 所有的硬件对象抽象为文件对象, 通过对文件的系统调用来访问. 用户对文件的系统调用操作基于该文件对象的操作函数表(file_operations), 每一打开的文件都继承了某类文件操作表. 对于一般文件来说(包括目录文件和符号链接文件), 文件对象继承了它所在文件系统的某种文件操作表. 对于设备文件来说, 文件对象继承了它的主设备号所在驱动程序的文件操作表. 设备的文件操作表是设备驱动的起点, 但往往并不在这个层次上直接完成设备操作. 如果在某个层次上对不同对象的某类操作具有某种共性, 那么就可以象提取"公因式"那样将这类操作抽象出来, 然后建立更低一级的操作层次来区分不同的对象, 这样就形成了不同层次的驱动接口.
2) 打开终端的文件操作表为tty_fops, 终端的打开结构用tty_struct结构描述, 文件结构的private_data指针指向打开的终端结构, 如果当前进程的终端指针(current->tty)指向某个打开的终端结构, 则表示该进程与此终端相关联. tty_driver结构描述终端的输出设备, 终端线路规程(tty_ldisc)用来在文件接口与输入设备和输出设备之间进行调控. TTY规程(N_TTY)用于连接终端输入驱动设备和终端显示驱动设备, PPP规程(N_PPP)用来连接终端驱动设备和网络驱动设备.
3) 当用户写入终端文件时, 通过TTY规程的write_chan操作间接输出到终端输出设备. 终端的输入设备将接收数据写入终端打开结构的轮换缓冲区(tty_flip_buffer)之中, 轮换缓冲区使用两个各512字节的缓冲区交替进行读写, 使数据的接收和处理互不重叠同时进行. 轮换缓冲区包含字符数据和字符标志两组缓冲区, 每一字符都具有对应的属性字符. 接收的数据在任务队列中传递给线路规程的receive_buf进行操作. 对于TTY规程, receive_buf操作对接收字符按照终端协议进行处理, 输出数据最终转移到打开终端的read_buf缓冲区中供用户接收. 对于PPP规程, receive_buf操作将识别接收到的PPP帧, 转变为IP帧作为ppp设备的接收帧处理.
4) 伪终端设备是一种特殊的终端驱动设备, 它并不驱动某个物理设备, 而是用来将终端的输出定向到应用程序中进行处理. 伪终端设备由主-从两个成对的设备构成, 当打开主设备(pty)时, 对应的从设备(ttyp)随之打开, 形成连接状态. 输入到主设备数据成为从设备的输出, 输入到从设备的数据成为主设备的输出, 形成双向管道. 伪终端设备常用于远程登录服务器来建立网络和终端的关联. 当通过telnet远程登录到另一台主机时, telnet进程与远程主机的telnet服务器相连接. telnet服务器使用某个pty主设备并通过对应的ttyp从设备与你在远程主机上所运行的程序相互通信.
5) Linux内核是一个以文件为对象的系统, 用户进程的虚拟空间是可执行文件的映射框架, CPU在可执行文件的映射空间中运行. 用户的文件接口实际上是字符流的接口, UNIX将人机接口归结为与终端文件的接口. 我想与文件相对的另一种对象就是窗口, 它们在不同的方向上产生了截然不同的人机界面风格.
6) 熟悉Windows API编程的都知道, Windows应用程序初始化时需要用RegisterClass()注册自已所定义的窗口类, 然后就可以用该窗口类创建它的窗口实例. 从驱动程序观点来看, 每一个窗口类可看成一个以窗口为对象的驱动程序, 所谓窗口元件就是一种窗口驱动设备, Windows应用程序则是在整个操作系统范围内((而不是内核范围内)以窗口为对象的各种层次的驱动程序集合. 如果将窗口类的消息函数(WndProc)看成第一个窗口驱动层次, 那么MFC所提供的应用程序接口可看成更末端层次的一种窗口驱动接口(用户只要在MFC基础上定义一些枝节的操作就可以了). 按照这种推理, 窗口系统由窗口管理核心和各种窗口驱动程序构成, 窗口应用程序则以窗口系统某种抽象而又统一的接口与窗口对象交互.
; drivers/char/tty_io.c:
/*
* Where all of the state associated with a tty is kept while the tty
* is open.  Since the termios state should be kept even if the tty
* has been closed --- for things like the baud rate, etc --- it is
* not stored here, but rather a pointer to the real state is stored
* here.  Possible the winsize structure should have the same
* treatment, but (1) the default 80x24 is usually right and (2) it's
* most often used by a windowing system, which will set the correct
* size each time the window is created or resized anyway.
* IMPORTANT: since this structure is dynamically allocated, it must
* be no larger than 4096 bytes.  Changing TTY_FLIPBUF_SIZE will change
* the size of this structure, and it needs to be done with care.
* - TYT, 9/14/92
*/
struct tty_struct { 终端设备文件的打开结构
int magic;
struct tty_driver driver;
struct tty_ldisc ldisc;
struct termios *termios, *termios_locked;
int pgrp;
int session;
kdev_t device;
unsigned long flags;
int count;
struct winsize winsize;
unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
unsigned char low_latency:1, warned:1;
unsigned char ctrl_status;
struct tty_struct *link;
struct fasync_struct *fasync;
struct tty_flip_buffer flip;
int max_flip_cnt;
int alt_speed; /* For magic substitution of 38400 bps */
wait_queue_head_t write_wait;
wait_queue_head_t read_wait;
struct tq_struct tq_hangup;
void *disc_data;
void *driver_data;
struct list_head tty_files;
#define N_TTY_BUF_SIZE 4096
/*
* The following is data for the N_TTY line discipline.  For
* historical reasons, this is included in the tty structure.
*/
unsigned int column;
unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
unsigned char closing:1;
unsigned short minimum_to_wake;
unsigned overrun_time;
int num_overrun;
unsigned long process_char_map[256/(8*sizeof(unsigned long))];
char *read_buf;
int read_head;
int read_tail;
int read_cnt;
unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))];
int canon_data;
unsigned long canon_head;
unsigned int canon_column;
struct semaphore atomic_read;
struct semaphore atomic_write;
spinlock_t read_lock;
};
struct fasync_struct {
int magic;
int fa_fd;
struct fasync_struct *fa_next; /* singly linked list */
struct file *fa_file;
};
#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
#define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
#define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1)
#define PTMX_DEV MKDEV(TTYAUX_MAJOR,2)
/*
* This is the flip buffer used for the tty driver.  The buffer is
* located in the tty structure, and is used as a high speed interface
* between the tty driver and the tty line discipline.
*/
#define TTY_FLIPBUF_SIZE 512
struct tty_flip_buffer {
struct tq_struct tqueue;
struct semaphore pty_sem;
char *char_buf_ptr;
unsigned char *flag_buf_ptr;
int count;
int buf_num;
unsigned char char_buf[2*TTY_FLIPBUF_SIZE];
char flag_buf[2*TTY_FLIPBUF_SIZE];
unsigned char slop[4]; /* N.B. bug overwrites buffer by 1 */
};
struct tty_driver { 终端驱动设备结构
int magic; /* magic number for this structure */
const char *driver_name;
const char *name;
int name_base; /* offset of printed name */
short major; /* major device number */
short minor_start; /* start of minor device number*/
short num; /* number of devices */
short type; /* type of tty driver */
short subtype; /* subtype of tty driver */
struct termios init_termios; /* Initial termios */
int flags; /* tty driver flags */
int *refcount; /* for loadable tty drivers */
struct proc_dir_entry *proc_entry; /* /proc fs entry */
struct tty_driver *other; /* only used for the PTY driver */
/*
* Pointer to the tty data structures
*/
struct tty_struct **table;
struct termios **termios;
struct termios **termios_locked;
void *driver_state; /* only used for the PTY driver */
/*
* Interface routines from the upper tty layer to the tty
* driver.
*/
int  (*open)(struct tty_struct * tty, struct file * filp);
void (*close)(struct tty_struct * tty, struct file * filp);
int  (*write)(struct tty_struct * tty, int from_user,
      const unsigned char *buf, int count);
void (*put_char)(struct tty_struct *tty, unsigned char ch);
void (*flush_chars)(struct tty_struct *tty);
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 (*break_ctl)(struct tty_struct *tty, int state);
void (*flush_buffer)(struct tty_struct *tty);
void (*set_ldisc)(struct tty_struct *tty);
void (*wait_until_sent)(struct tty_struct *tty, int timeout);
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);
/*
* linked list pointers
*/
struct tty_driver *next;
struct tty_driver *prev;
};
struct tty_ldisc { 终端线路规程
int magic;
char *name;
int num;
int flags;
/*
* The following routines are called from above.
*/
int (*open)(struct tty_struct *);
void (*close)(struct tty_struct *);
void (*flush_buffer)(struct tty_struct *tty);
ssize_t (*chars_in_buffer)(struct tty_struct *tty);
ssize_t (*read)(struct tty_struct * tty, struct file * file,
unsigned char * buf, size_t nr);
ssize_t (*write)(struct tty_struct * tty, struct file * file,
const unsig
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值