linux0.12-10-1-总体功能

第10章 字符设备驱动程序

[466页]

10-1 总体功能

本章的程序可分成三部分:
第一部分是是关于RS-232串行线路驱动程序,包括程序rs_io.s和serial.c;
第二部分是涉及控制台的驱动程序,包括键盘中断驱动程序keyboard.S和控制台显示驱动程序console.c;
第三部分是终端驱动程序与上层接口部分,包括终端输入输出程序tty_io.c和终端控制程序tty_ioctl.c。

下面首先概述终端控制驱动程序实现的基本原理,然后分这三部分说明它们的基本功能。

10-1-1 终端驱动程序基本原理

终端驱动程序用于控制终端设备,在终端设备和进程之间传输数据,并对所传输的数据进行一定的处理。
用户在键盘上键入对的原始数据(raw data),在通过终端程序处理后,被传送给一个接收进程;而进程向终端发送的数据,在终端程序处理后,被显示在终端屏幕上或者通过串行线路被送到远程终端。

根据终端程序对待输入或输出数据的方式,可以把终端工作模式分成两种。
一种是规范模式(canonical),此时经过终端程序的数据将被进行变换处理,然后再送出。例如把TAB字符
扩展为8个空格字符,用键入的删除字符(backspace)控制删除前面键入的字符等。使用的处理函数一般称
为行规则(line discipline)模块。
另一种是非规范模式或秤原始(raw)模式。在这种模式下,行规则程序仅在终端与进程之间传送数据,而不对数据进行规范模式变换处理。

在终端驱动程序中,根据它们与设备的关系,以及在执行流程中的位置,可以分为字符设备的直接驱动程序和上层直接联系的接口程序。

可以用图10-1表示这种控制关系。
在这里插入图片描述

10-1-2 Linux支持的终端设备类型

终端是一种字符型设备,它有多种类型。通常使用tty来简称各种类型的终端设备。tty是Teletype的缩写。Teletype是一种由Teletype公司生产的最早的终端设备,外观很像电传打字机。在Linux0.1x系统设备文件目录/dev/中,通常包含以下一些终端设备文件:

这些终端设备文件可以分为以下几种类型:
(1)串行端口终端(/dev/ttySn)
(2)伪终端(/dev/ptyp、/dev/ttyp)
(3)控制终端(/dev/tty)
(4)控制台(/dev/ttyn,/dev/console)
(5)其他类型

10-1-3 中断基本数据结构

每个终端设备都对应一个tty_struct数据结构,主要用来保存终端设备当前参数设置、
所属的前台进程组ID合字符IO缓冲队列等信息。该结构定义在include/linux/tty.h文件中,
其结构如下所示:

struct tty_struct {
	struct termios termios;						//终端io属性和控制字符数据结构。
	int pgrp;									//所属进程组。
	int session;								//
	int stopped;								//停止标志。
	void (*write)(struct tty_struct * tty);		//tty写函数指针。
	struct tty_queue *read_q;					//tty读队列。
	struct tty_queue *write_q;					//tty写队列。
	struct tty_queue *secondary;				//tty辅助队列(存放规范模式字符序列),可称为规范(熟)模式队列。
	};

extern struct tty_struct tty_table[];//tty结构数组。

Linux内核使用了数组tty_table[]来保存系统中每个终端设备的信息。每个数组项是一个数据结构tty_struct,对应系统中一个终端设备。
Linux0.12内核共支持三个终端设备。
一个是控制台设备,另外两个是使用系统上两个串行端口的串行终端设备。

termios结构用于存放对应终端设备的io属性。有关该结构的详细描述下面说明。
pgrp是进程组标识,它指明一个会话处于前台的进程组,即当前拥有该终端设备的进程组。
pgrp主要用于进程的作业控制操作。
stopped是一个标志,标识对应终端设备是否已经停止使用。
函数指针*write是该终端设备的输出处理函数,
对于控制台终端,它负责驱动显示硬件,在屏幕上显示字符等信息。对于通过系统串行端口连接的串行终端,它负责把输出字符发送到串行端口。

终端所处理的数据被保存在3个tty_queue结构的字符缓冲队列中(或称为字符表),如下所示:

struct tty_queue {
	unsigned long data;				//等待队列缓冲区中当前数据统计值。
									//对于串口终端,则存放串口端口地址。
	unsigned long head;				//缓冲区中数据头指针。
	unsigned long tail;				//缓冲区中数据尾指针。
	struct task_struct * proc_list;	//等待本缓冲队列的进程列表。
	char buf[TTY_BUF_SIZE];			//队列的缓冲区。
};

每个字符缓冲队列的长度是1KB。
其中读缓冲队列read_q用于临时存放从键盘或串行终端输入的原始(raw)字符序列;
写缓冲队列write_q用于存放写到控制台显示屏或串行终端去的数据;
根据ICANON标志,辅助队列secondary用于存放从read_q中取出的经过规则程序处理(过滤)的数据,或称为熟(cooked)模式数据。这是在行规则程序把原始数据中的特殊字符如删除(backspace)字符变换后的规范输入数据,以字符行为单位供应用程序读取使用。
上层终端读函数tty_read()即用于读取secondary队列中的字符。

在读入用户键入的数据时,中断处理汇编程序只负责把原始字符数据放入输入缓冲队列中,而由中断处理过程中调用的C函数(copy_to_cooked())来处理字符的变换工作。例如当进程向一个终端写数据时,终端驱动程序就会调用行规则函数cpy_to_cooked(),把用户缓冲区中的所有数据到写缓冲队列汇总,并将数据发送到终端上显示。在终端上按下一个键时,所引发的键盘中断处理过程会把按键扫描码对应的字符放入读队列read_q中,并调用规范模式处理程序把read_q
中的字符经过处理再放入辅助队列secondary中。与此同时,如果终端设备设置了回显标志(L_ECHO),则也把该字符放入写队列write_q中,并调用终端写函数把该字符显示在屏幕上。通过除了像键入密码或其他特殊要求以外,回显标志都是置位的。可以通过修改终端的termios结构中的信息来改变这些标志值。

在上述tty_struct结构中还包括一个termios结构,该结构定义在include/termios.h头文件中,
其字段内容如下所示:

#define NCCS 17
struct termios {
	tcflag_t c_iflag;		/* input mode flags */		//输入模式标志。
	tcflag_t c_oflag;		/* output mode flags */		//输出模式标志。
	tcflag_t c_cflag;		/* control mode flags */	//控制模式标志。
	tcflag_t c_lflag;		/* local mode flags */		//本地模式标志。
	cc_t c_line;			/* line discipline */		//线路规程(速率)。
	cc_t c_cc[NCCS];		/* control characters */	//控制字符数组。
};

c_iflag是输入模式标志集。Linux0.12内核实现了POSIX.1定义的所有11个输入标志,参见termios.h头文件中的说明。终端设备驱动程序用这些标志来控制如何对终端输入的字符
进行变换(过滤)处理。例如是否需要把输入的换行符(NL)转换成回车符(CR)、是否需要把输入的大写字符转换成小写字符(因为以前有些终端设备只能输入大写字符)等。在Linux0.12内核中,相关的处理函数是tty_io.c文件中的copy_to_cooked()。参见termios.h文件第83~96行。

c_oflag是输出模式标志集。终端设备驱动程序使用这些标志控制如何把字符输出到终端上,主要在tty_io.c的tty_write()函数中使用。参见termios.h文件第99~129行。

c_cflag是控制模式标志集。主要用于定义串行终端传输特性,包括波特率、字符位数以及停止位数等。参见termios.h文件第132~166行。

c_lflag是本地模式标志集。主要用于控制驱动程序与用户的交互。例如是否需要回显(Echo)字符、是否需要把擦除字符直接显示在屏幕上、是否需要让终端上键入的控制字符产生信号。这些操作主要在copy_to_cooked()函数和tty_read()中使用。

例如,若设置了ICANON标志,则表示终端处于规范模式输入状态,否则终端处于非规范模式。
如果设置ISIG标志,则表示收到终端发出的控制字符INTR、QUIT、SUSP时系统需要产生相应的信号。
参见termios.h文件第169~183行。

上述4中标志集的类型都是unsigned long,每个位可表示一种标志,因此每个标志集最多可有32个输入标志。所有
这些标志及其含义可参见termios.h头文件。

c_cc[]数组包含了终端所有可以修改的特殊字符。例如你可以通过修改其中的中断字符(^C)由其他按键产生。其中NCCS是数组的长度值。终端默认的c_cc[]数组初始值定义在include/linux/tty.h文件中。程序引用该数组中各项时定义了数组项符号名,这些名称都以字母V开头,例如VINTR/VMIN。
参见termios.h文件第64~80行。

因此,利用系统调用ioctl或使用相关函数(tcsetattr()),我们可以通过修改termios结构中的信息来改变终端的设置参数。行规则函数即是根据这些设置参数进行操作。例如,控制
终端是否要对键入的字符进行回显、设置串行终端传输的波特率、清空读缓冲队列和写缓冲队列。

当用户修改终端参数,将规范模式标志复位,就会把终端设置为工作在原始模式,此时 行规则程序会把用户键入的数据原封不动地传送给用户,而回车符也被当作普通字符处理。
因此,在用户使用系统调用read时,就应该作出某种决策方案以判断系统调用read什么时候算完成并返回。这将由终端termios结构中的VTIME和VMIN控制字符决定。这两个是读操作的超时定时值。VMIN表示为了满足读操作,需要读取的最少字符数;VTIME则是一个读操作等待定时值。

我们可以使用命令stty来查看当前终端设备termios结构中标志的设置情况。在Linux0.1x系统命令行提示
符下键入stty命令会显示以下信息:

其中带有减号的标志标志没有设置。另外对于现在的Linux系统,需要键入"sty-a"才能
显示所有这些信息,并且显示格式有所区别。

终端程序所使用的上述主要数据结构和它们之间的关系如图10-2所示。
在这里插入图片描述

10-1-4 规范模式和非规范模式

1、 规范模式
当c_lflag中的ICANON标志置位时,则按照规范模式对终端输入数据进行处理。此时输入字符被装配成行,进程以字符行的形式读取。当一行字符输入后,终端驱动程序会立即返回。行的定界符有NL、EOL、EOL2和EOF。其中除最后一个EOF(文件结束)将被处理程序删除外,其余4个字符将被作为一行的最后一个字符返回给调用程序。

在规范模式下,终端输入的以下字符将被处理:ERASE、KILL、EOF、EOL、REPRINT、WERASE和EOL2。
具体字符的作用看赵老师。[472页]

2、 非规范模式
如果ICANON处于复位状态,则终端程序工作在非规范模式下。此时终端程序不对上述字符进行处理,而是将它们当作普通字符处理。输入数据也没有行的概念。终端程序何时返回读进程是由MIN和TIME的 值确定的。这两个变量时c_cc[]数组中的变量。通过修改它们即可改变在非规范模式下进程读字符的处理方式。

MIN指明读操作最少需要读取的字符;TIME指定等待读取字符的超时值(计量单位是1/10S)。
根据它们的值可分4中情况来说。
(1)MIN>0,TIME>0
(2)MIN>0,TIME=0
(3)MIN=0,TIME>0
(4)MIN=0,TIME=0
[472页]

10-1-5 控制台终端和串行终端设备

在Linux0.12系统中可以使用两类终端:
一类是主机上的控制台终端;
控制台终端由内核中的键盘中断处理程序keyboard.S和显示控制程序console.c进行管理。
它接收上层tty_io.c程序传递下来的显示字符或控制信息,并控制在主机屏幕上字符的显示,
同时控制台(主机)把键盘按键产生的代码由keyboard.S传递到tty_io.c程序去处理。

一类是串行硬件终端设备。
串行终端设备则通过线路连接到计算机串行端口上,并通过内核中的串行程序rs_io.s与tty_io.c直接进行信息交互。

keyboard.S和console.c这两个程序实际上是Linux系统主机中使用显示器和键盘模拟一个硬件终端设备的仿真程序。只是由于在主机上,因此我们称这个模拟终端环境为控制台终端,或直接称为控制台。这两个程序所实现的功能就相当于一个串行终端设备固化再ROM中的终端处理程序的作用
(除了通信部分),也像普通PC上的一个终端仿真软件。因此虽然程序在内核中,但我们还是可以独立地看待它们。这个模拟终端与普通的硬件终端设备主要的区别在于不需要通过串行线路通信驱动程序。因此keyboard.S和console.c程序必须模拟一个实际终端设备(例如DEC的VT100终端)具备的所有硬件处理功能,即 终端设备固化程序中除通信以外的所有处理功能。控制台终端和串行终端设备在处理结构上的相互去呗与类似之处 参见图10-3。所以如果我们对一般硬件终端设备或终端仿真程序工作原理有一定了解,那么阅读这两个程序就不会遇到什么困难。
图10-3
在这里插入图片描述

1、 控制台驱动程序
在Linux0.12内核中,终端控制台驱动程序涉及keyboard.S和console.c程序。keyboard.S用于处理用户键入的字符,把它们放入读缓冲队列read_q中,并调用copy_to_cooked()函数读取read_q中的字符,经转换后放入辅助缓冲队列secondary。console.c程序实现控制台终端收到代码的输出处理。
看看赵老师举的例子 [473页]

图10-4 控制台键盘中断处理过程
在这里插入图片描述

对于进程执行tty写操作,终端驱动程序是一个字符一个字符进行处理的。在写缓冲队列write_q没有满时,就从用户缓冲区取一个字符,经过处理放入write_q中。当把用户数据全部放入write_q队列或者此时write_q已满,就调用终端结构tty_struct中指定的写函数,把write_q缓冲队列中的
数据输出到控制台。对于控制台终端,其写函数是con_write(),在console.c程序中实现。

有关控制台终端操作的驱动程序,主要涉及两个程序:
一个是键盘中断处理程序keyboard.S,主要用于把用户键入的字符放入read_q缓冲队列中;
另一个是屏幕显示处理程序console.c,用于从write_q队列中取出字符并显示在屏幕上。

所有这三个字符缓冲队列与上述函数或文件的关系都可以用图10-5清晰地表示出来。
在这里插入图片描述

2、串行终端驱动程序
处理串行终端操作的程序有serial.c和rs_io.s。
serial.c程序负责对串行端口进行初始化操作。另外,通过取消对发送保持寄存器空中断允许的屏蔽来开启串行中断发送字符操作。rs_io.s程序是串行中断处理过程。主要根据引发中的4种原因分别进行处理。

引起系统发生串行中断的情况有:
由于modem状态发生了变化;
由于线路状态发生了变化;
由于接收到字符;
由于在中断允许标志寄存器中设置了发送保持寄存器中断允许标志,需要发送字符。

10-1-6 中断驱动程序接口

通常,用户通过文件系统与设备打交道。每个设备都有一个文件名称,并相应地也在文件系统中占一个索引节点(i节点)。但该i节点中的文件类型是设备类型,以便与其他正规文件区别。用户就可以直接使用文件系统调用来访问设备。终端驱动程序也同样为此目的向文件系统提供了调用接口函数。终端驱动程序与系统其他程序的接口是使用tty_io.c文件中的通用函数实现的。其中实现了读终端函数tty_read()和写终端函数tty_write(),以及输入行规则函copy_to_cooked()。
另外,在tty_ioctl.c程序中,实现了修改终端参数的输入输出控制函数(或系统调用)tty_ioclt()。终端的设置参数放在终端结构中的termios结构中,其中的参数比较多,也比较复杂,
请参考include/termios.h文件中的说明。

对于不同终端设备,可以有不同的行规则程序与之匹配。但在Linux0.12中仅有一个行规则函数,因此termios结构中的行规则字段"c_line"不起作用,都被设置为0。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/22875.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

韦东山Linux驱动入门实验班(2)hello驱动---驱动层与应用层通讯,以及自动产生设备节点

前言 (1)学习韦东山老师的Linux,因为他讲的很精简,以至于很多人听不懂。接下来我讲介绍韦东山老师的驱动实验班的第二个Hello程序。 (2)注意,请先学习完视频再来看这个教程!本文仅供…

iptables防火墙2

文章目录 iptables防火墙21 SNAT1.1 原理1.2 应用环境1.3 转换前提条件1.4 SNAT转换 2 DNAT2.1 原理2.2 应用环境2.3 转换前提条件 3 SNAT转换3.1 先配置作为网关服务器的虚拟机3.2 修改ens33的网卡3.3 修改ens36的网卡3.4 开启PC2网关服务器的路由转发功能3.5 永久开启3.6 配置…

【Midjourney】Midjourney 辅助工具 ② ( 自定义命令工具 | 设置颜色 | 设置材质 | 设置随机种子 | 设置图片链接 )

文章目录 一、Midjourney Prompt Tool 自定义命令工具1、设置颜色参数2、设置材质参数3、设置随机种子参数4、设置图片链接 Midjourney 提示词命令 可以使用 辅助工具 进行生成 , 辅助工具如下 : Midjourney Prompt Tool 自定义命令工具Midjourney Prompt Generator 命令生成器…

前端开发推荐vscode安装什么插件?

前言 可以参考一下下面我推荐的插件,注意:插件的目的是用于提高开发的效率,节约开发的时间,像类似检查一些bug、拼写错误等这些可以使用插件快速的识别,避免在查找错误上浪费过多的时间,但切记不要过度依赖…

【Python Power BI】零基础也能轻松掌握的学习路线与参考资料

Python和Power BI是现代数据分析和可视化领域中最受欢迎的工具之一,Python是一种高级编程语言,广泛用于数据科学和分析,而Power BI是一种业务智能工具,用于创建交互式大屏幕和实时报表。Python和Power BI的结合使用可以为数据科学…

探索编程的极限:挑战炫技代码

程序员常常被视为具有超强技术能力的人才,而他们手中的代码也往往充满了令普通人惊叹的炫技操作。作为程序员的我,将和大家分享一些炫技的代码写法 一、编程语言介绍 本人主攻Java。下面我将介绍一下Java语言。 Java是一种广泛使用的高级编程语言&…

字符串、字符串列表,倒序生成字典。

带数字的字符串以数字为key倒序生成字典,字符串列表按其元素索引为key倒序生成字典。 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅仅是基础那么简…

什么是护网?护网怎么参加?

一、什么是护网行动? 护网行动是以公安部牵头的,用以评估企事业单位的网络安全的活动。 具体实践中。公安部会组织攻防两方,进攻方会在一个月内对防守方发动网络攻击,检测出防守方(企事业单位)存在的安全…

叮咚买菜业绩大幅低于预期,2023年前景堪忧

来源l:猛兽财经 作者:猛兽财经 叮咚买菜2023年第一季度业绩低于预期 叮咚买菜(DDL)于5月12日公布了2023年第一季度财报。 财报显示,叮咚买菜的收入同比下降了-8%,从2022年第一季度的54.44亿元人民币下滑…

Shell基础

目录 第1章 Shell概述 第2章 Shell脚本入门 第3章 变量 3.1 系统预定义变量 3.2 自定义变量 3.3 特殊变量 3.3.1 $n 3.3.2 $# 3.3.3 $*、$ 3.3.4 $? 第4章 运算符 第5章 条件判断 第6章 流程控制(重点) 6.1 if判断 6.2 case语…

广和通携手有人物联网完成5G SUL辅助上行功能验证

近日,广和通5G模组FM650-CN已在商用网络中实现5G SUL上行能力增强,助力有人物联网工业路由器在仿真网络环境中完成SUL辅助上行功能的验证。本次验证成功,意味着FM650-CN已具备SUL辅助上行商用能力,有利于推动更多5G终端支持SUL特性…

AI工具第三期:本周超16款国内精选AI工具分享!

1. 未来百科 未来百科,是一个知名的AI产品导航网站——为发现全球优质AI工具而生。目前已聚集全球2500优质AI工具产品,旨在帮助用户发现全球最好的AI工具,同时为研发AI垂直应用的创业公司提供展示窗口,迎接未来的AI时代。未来百科…

Netty编解码机制(一)

1.编码和解码基本介绍 1>.编写网络应用程序时,因为数据在网络中传输的都是二进制字节码数据,在发送数据时就需要编码,接收数据时就需要解码; 2>.codec(编解码器)的组成部分有两个: decoder(解码器)和 encoder(编码器).encoder(编码器)负责把业务数据转换成字节码数据,而…

什么是数字化?企业为什么要数字化转型

一、什么是数字化? 什么是数字化?在我理解,数字化是一个基于时代科技发展所产生的概念,首先它是一个工具,在企业的经营发展中将信息技术融入到传统的企业模式中,起到了转型的作用。 其次数字化转型是企业…

从复杂到简单:通用CRM客户管理系统改变企业管理方式

一、概述 CRM客户管理系统是通过对客户生命周期的有效管理,是一种重要的客户管理工具,可以帮助企业更好的了解客户的需求,提升客户满意度,优化销售流程、提高销售业绩等,随着数字经济的不断发展和普及,CRM…

第03章 流程控制语句

流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。 程序设计中规定的三种流程结构,即: 顺序结构 程序从上到下逐行地执行,中间没有任何判断和跳转。 分支结构 根据条件&#xff0…

mjpg-streamer实现细节分析

mjpg-streamer实现细节分析 文章目录 mjpg-streamer实现细节分析输入初始化input_initinit_videoIninit_v4l2 启动摄像头输入线程cam_threaduvcGrabcompress_yuyv_to_jpegmemcpy_picture 输出初始化output_init启动摄像头输出线程server_thread设置 SO_REUSEADDR 选项。设置 IP…

uvc驱动ioctl分析下

uvc驱动ioctl分析下 文章目录 uvc驱动ioctl分析下uvc_ioctl_enum_input枚举输入uvc_query_ctrl__uvc_query_ctrluvc_ioctl_g_input 获取输入uvc_ioctl_s_input 设置输入uvc_query_v4l2_ctrluvc_ioctl_queryctrl查询控制器uvc_ioctl_query_ext_ctrl查询扩展控制器 uvc_ioctl_g_c…

爬虫基本原理

爬虫基本原理 1.1获取网页1.1.1提取信息1.1.2保存数据 1.2请求1.2.1 请求方法1.2.2 请求网址1.2.3 请求头1.2.4请求体1.3响应 1.1获取网页 爬虫首先要做的工作就是获取网页,这里就是获取网页的源代码。源代码里包含了网页的部分有用信息,所以只要把源代…

【航空和卫星图像中检测建筑物】使用gabor特征和概率的城市区域和建筑物检测研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…