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

news2024/11/24 20:30:53

第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。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能AI会话+文字转为markdown格式/思维导图的工具的介绍和使用

AI会话工具和文字转换为markdown格式 1、这里首先要有一个xmind思维导图软件,下载链接在下方。XMind: 2、本章中列举的AI工具是近期国内交火的prompt(文心一言 作者还没排上队) https://chat.givemeprompt.com/3、首先运用此工具生成你想要的…

leetcode刷题之数组问题总结,二分法,移除元素,

目录 一、二分查找相关应用704.二分查找35.搜索插入位置方法一:二分法暴力解法 34.在排序数组中查找元素的开始位置和最后一个位置方法一:暴力解法方法二:二分法,确定左右两侧的边界 69.x的平方根方法一:二分法方法二:暴力解法错解…

k8s1.26.1部署 ingress-nginx-controller(1.6.4)

文章目录 参考ingress-nginx git地址ingress-nginx 的 deployment的地址: 参考 1.24版本k8s集群配置Nginx-Ingressrancher配置https域名访问图文教程 ingress-nginx git地址 https://github.com/kubernetes/ingress-nginx ingress-nginx 的 deployment的地址&a…

cdn配置(超详细+图解+原理)

具体的详细配置在右侧目录翻到“三”,前面的一二是将原理 以腾讯云的cdn为例,其它家的大同小异 一、cdn作用和配置思路 (一)cdn作用 1.加速访问 cdn服务通常有多个节点缓存,用户可以就近获取,延迟较低 …

得物App万米高空WiFi拦截记

0.前情摘要 在一次飞行途中,我司客户遭遇到了得物App在飞机上的WiFi网络访问异常的问题。这让我们意识到在特定场景下,用户可能面临无法使用得物App的困扰。经过SRE团队与无线团队、网络团队联合全力排查与优化,最终成功解决了这一问题&…

PAN(Pyramid Attention Network for semantic segmentation)paper解读

Pyramid Attention Network for Semantic Segmentation讲PAN用于语义分割,网络结构类似encoder-decode, u-shape。 背景 encoder-decoder结构, 在encoding到高维度特征的过程中,原始的纹理信息会遭遇空间分辨率损失,例如FCN。 P…

Spring Boot进阶(39):SpringBoot之Jackson配置全局时间日期格式 | 超级详细,建议收藏

1. 前言🔥 不知道小伙伴对于日期字段,在项目中都是如何处理的,是单独给每个字段都自定义日期格式还是做全局格式设置?这个我之前啊,是对日期都是有做单独配置,给每个Entity带有日期字段的都配JsonFormat注解…

SolVES 模型与多技术融合【QGIS、PostgreSQL、ARCGIS、MAXENT、R】实现生态系统服务功能社会价值评估及拓展案例分析

生态系统服务是人类从自然界中获得的直接或间接惠益,可分为供给服务、文化服务、调节服务和支持服务4类,对提升人类福祉具有重大意义,且被视为连接社会与生态系统的桥梁。自从启动千年生态系统评估项目(Millennium Ecosystem Asse…

编译器设计(十四)——寄存器分配

文章目录 一、简介二、背景问题2.1 内存与寄存器2.2 分配与指派2.3 寄存器类别 三、局部寄存器分配和指派3.1 自顶向下的局部寄存器分配3.2 自底向上的局部寄存器分配3.3 超越单个程序块 四、全局寄存器分配和指派4.1 了解图着色4.2 找到全局活跃范围4.3 估算全局逐出代价4.4 冲…

前端列表页+element-puls实现列表数据弹窗功能

效果图: 这是一个修改的弹窗,我们要实现的功能是,在列表,点击修改按钮时,将数据带入到弹窗里面,点击保存时关闭弹窗。 1,点击修改展开弹窗 使用 eldialog组件,v-model绑定的值为tru…

fluent-operator在kubesphere中的实战详解

前言 最近收到一个小任务:熟悉kubesphere实现一个日志平台。基于这样的机会,将最近所整理的笔记进行汇总。 kubesphere开启日志收集 根据官网介绍只需要将 enabled 的 false 改为 true即可 执行kubectl get pod -n kubesphere-logging-system命令来检查…

QT课程 QT介绍

QT介绍(了解) Qt是一个基于C开发语言的图形用户界面开发(GUI)框架。界面开发知识Qt的一部分,实际上Qt也可以支持很多其他的功能,比如:网络编程、文件IO、图形图像处理等。 Qt在嵌入式领域最大…

Vue之插值表达式,v-bind(单向绑定),v-model(双向绑定)

文章目录 前言一、插值表达式二、v-bind指令三、v-model指令总结 前言 插值表达式{{…}} v-bind v-model 一、插值表达式 插值表达式支持匿名变量、三目运算符、四则运算符、比较运算符、数值类型的一些内置方法&#xff0c;还有数组的索引取值方法和对象属性。 <!DOCTYPE…

安全工具 | CMSeeK [指纹识别]

0x00 免责声明 本文仅限于学习讨论与技术知识的分享&#xff0c;不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;本文作者不为此承担任何责任&#xff0c;一旦造成后果请自行承担…

2023年北京.NET线下技术沙龙圆满落幕!

5月20日&#xff0c;MASA技术团队在北京举办的“2023年北京.NET线下技术沙龙”圆满落幕&#xff01;整个活动气氛热烈&#xff0c;嘉宾们的分享内容丰富多彩&#xff0c;现场观众都受益匪浅。我们期待着更多这样的技术交流活动&#xff0c;让.NET社区不断发展和进步。 本次活动…

材料电磁参数综合测试解决方案 材料吸波、屏蔽性能测试系统 (10MHz~500GHz)

材料吸波、屏蔽性能测试系统测试频率范围可达10MHz&#xff5e;500GHz&#xff0c;可实现材料反射率、屏蔽性能特性参数测试。系统由矢量网络分析仪、测试夹具、系统软件等组成&#xff0c;根据用户不同频率、材料性能测试需求&#xff0c;可选用弓形框法、便携式反射率测试法进…

如何快速实现接口自动化测试,常规接口断言封装实践

目录 前言&#xff1a; 一、框架设计思路 1. 封装请求方法 2. 断言封装 3. 接口封装 4. 接口统一管理 二、框架使用 三、总结 前言&#xff1a; 在当今互联网行业中&#xff0c;接口自动化测试已经成为了非常重要的测试手段之一。而在这个过程中&#xff0c;接口自动化…

3年外包裸辞,面试阿里、字节全都一面挂,哭死.....

测试员可以先在外包积累经验&#xff0c;以后去大厂就很容易&#xff0c;基本不会被卡&#xff0c;事实果真如此吗&#xff1f;但是在我身上却是给了我很大一巴掌... 所谓今年今天履历只是不卡简历而已&#xff0c;如果面试答得稀烂&#xff0c;人家根本不会要你。况且要不是大…

性能优化 面试

性能分析 1.页面加载性能&#xff08;加载时间&#xff1b;用户体验&#xff09; 2.动画与操作性能&#xff08;是否流畅无卡顿&#xff09; 3.内存占用&#xff08;内存占用过大&#xff0c;浏览器崩掉等&#xff09; 4.电量消耗&#xff08;游戏方面&#xff0c;暂不考虑&…

【SpringBoot】九:Web服务---文件上传

文章目录 1.MultipartFile API2.上传文件 1.MultipartFile API 在 Controller 的方法加入形参RequestParam MultipartFile。 MultipartFile 表示上传的文件&#xff0c;提供了方便的方法&#xff0c;保存文件到磁盘。 方法作用getName()参数名称&#xff08;upfile&#xff0…