Linux终端tty设备驱动

合集下载

udev

udev

如果你使用Linux比较长时间了,那你就知道,在对待设备文件这块,Linux改变了几次策略。

在Linux早期,设备文件仅仅是是一些带有适当的属性集的普通文件,它由mknod命令创建,文件存放在/dev目录下。

后来,采用了devfs,一个基于内核的动态设备文件系统,他首次出现在2.3.46内核中。

Mandrake,Gentoo等Linux分发版本采用了这种方式。

devfs创建的设备文件是动态的。

但是devfs有一些严重的限制,从2.6.13版本后移走了。

目前取代他的便是文本要提到的udev--一个用户空间程序。

目前很多的Linux分发版本采纳了udev的方式,因为它在Linux设备访问,特别是那些对设备有极端需求的站点(比如需要控制上千个硬盘)和热插拔设备(比如USB摄像头和MP3播放器)上解决了几个问题。

下面我我们来看看如何管理udev设备。

实际上,对于那些为磁盘,终端设备等准备的标准配置文件而言,你不需要修改什么。

但是,你需要了解udev配置来使用新的或者外来设备,如果不修改配置,这些设备可能无法访问,或者说Linux可能会采用不恰当的名字,属组或权限来创建这些设备文件。

你可能也想知道如何修改RS-232串口,音频设备等文件的属组或者权限。

这点在实际的Lin ux实施中是会遇到的。

为什么使用udev在此之前的设备文件管理方法(静态文件和devfs)有几个缺点:*不确定的设备映射。

特别是那些动态设备,比如USB设备,设备文件到实际设备的映射并不可靠和确定。

举一个例子:如果你有两个USB打印机。

一个可能称为/dev/usb/lp0,另外一个便是/dev/usb/lp1。

但是到底哪个是哪个并不清楚,lp0,lp1和实际的设备没有一一对应的关系,因为他可能因为发现设备的顺序,打印机本身关闭等原因而导致这种映射并不确定。

理想的方式应该是:两个打印机应该采用基于他们的序列号或者其他标识信息的唯一设备文件来映射。

linux的bus、device、driver介绍

linux的bus、device、driver介绍

linux的bus、device、driver介绍 linux 通过device和driver分别管理系统中的设备和驱动,⽤bus将设备和驱动关联起来,bus可以看成是设备和驱动的媒介,可以匹配设备和驱动。

这样设备和驱动可以独⽴加载,互不影响。

sysfs是⼀个基于内存的⽂件系统,它的作⽤是将内核信息以⽂件的⽅式提供给⽤户程序使⽤。

我们都知道设备和对应的驱动都是由内核管理的,这些对于⽤户空间是不可见的。

现在通过sysfs,可以在⽤户空间直观的了解设备驱动的层次结构。

⼀、bus注册过程bus_type结构体代表⼀条总线,如下所⽰:struct bus_type {const char *name; //名称const char *dev_name;struct device *dev_root;struct device_attribute *dev_attrs; /* use dev_groups instead */const struct attribute_group **bus_groups;const struct attribute_group **dev_groups;const struct attribute_group **drv_groups;int (*match)(struct device *dev, struct device_driver *drv); //device和driver的匹配函数int (*uevent)(struct device *dev, struct kobj_uevent_env *env);int (*probe)(struct device *dev);int (*remove)(struct device *dev);void (*shutdown)(struct device *dev);int (*online)(struct device *dev);int (*offline)(struct device *dev);int (*suspend)(struct device *dev, pm_message_t state);int (*resume)(struct device *dev);const struct dev_pm_ops *pm;const struct iommu_ops *iommu_ops;struct subsys_private *p; struct lock_class_key lock_key;};struct subsys_private {struct kset subsys; //对应/sys/bus⽬录struct kset *devices_kset; //对应/sys/bus/devices⽬录struct list_head interfaces;struct mutex mutex;struct kset *drivers_kset; //对应/sys/bus/drivers⽬录struct klist klist_devices; //该bus下的所有devicestruct klist klist_drivers; //该bus下的所有driverstruct blocking_notifier_head bus_notifier;unsigned int drivers_autoprobe:1;struct bus_type *bus;struct kset glue_dirs;struct class *class;};向系统添加⼀条bus_type总线时,改总线会⾃动添加到/sys/bus⽬录下,bus⽬录是系统⾃动创建的,这个bus⽬录为static struct kset *bus_kset,定义在kernel/drivers/base/bus.c中。

Linux下的硬件驱动——USB设备

Linux下的硬件驱动——USB设备

Linux下的硬件驱动——USB设备什么是USB设备?USB即Universal Serial Bus,翻译过来就是通用串行总线。

它是一种规范化的、快速的、热插拔的串行输入/输出接口。

USB接口常被用于连接鼠标、键盘、打印机、扫描仪、音频设备、存储设备等外围设备。

Linux下的USB驱动在Linux系统中,每个USB设备都需要一个相应的驱动程序来驱动。

从Linux 2.4开始,内核提供了完整的USB设备支持。

对于每个USB设备,内核都会自动加载对应的驱动程序。

Linux下的USB设备驱动程序主要分为以下几个部分:USB核心驱动程序USB核心驱动程序是操作系统内核中处理USB设备的核心模块,负责与各种类型的USB设备进行通信,包括主机控制器、USB总线、USB设备等。

它与驱动程序和应用程序之间起到了桥梁的作用,为驱动程序提供了USB设备的基础支持。

USB设备驱动程序USB设备驱动程序是与特定USB设备相对应的驱动程序,为USB设备提供具体的读写功能和其他控制功能。

USB核心驱动程序和USB设备驱动程序之间的接口USB核心驱动程序和USB设备驱动程序之间的接口是指USB层和应用程序层之间的接口,负责传递各种USB操作的命令和数据。

如何编译一个USB设备驱动编译一个USB设备驱动程序需要按照以下步骤进行:步骤一:安装必要的软件包首先需要安装编译和调试USB设备驱动所需的软件包,包括编译工具链、内核源代码、内核头文件等。

sudo apt-get install build-essential linux-source linux-headers-`una me -r`步骤二:编写代码现在可以编写USB设备驱动程序的代码,此处不做详细介绍。

步骤三:编译代码在终端窗口中进入USB设备驱动程序所在的目录下,输入以下命令进行编译:make此命令将会编译USB设备驱动程序,并生成一个将驱动程序与内核进行连接的模块文件。

Linux视频设备驱动编程(v4l2编程)

Linux视频设备驱动编程(v4l2编程)

Linux视频设备驱动编程(v4l2编程)一.什么是video4linuxVideo4linux2(简称V4L2),是linux中关于视频设备的内核驱动。

在Linux 中,视频设备是设备文件,可以像访问普通文件一样对其进行读写,摄像头在/dev/video0下。

二、一般操作流程(视频设备):1. 打开设备文件。

int fd=open(”/dev/video0″,O_RDWR);2. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。

VIDIOC_QUERYCAP,struct v4l2_capability3. 选择视频输入,一个视频设备可以有多个视频输入。

VIDIOC_S_INPUT,struct v4l2_input4. 设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。

VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format5. 向驱动申请帧缓冲,一般不超过5个。

struct v4l2_requestbuffers6. 将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制。

mmap7. 将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer8. 开始视频的采集。

VIDIOC_STREAMON9. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。

VIDIOC_DQBUF10. 将缓冲重新入队列尾,这样可以循环采集。

VIDIOC_QBUF11. 停止视频的采集。

VIDIOC_STREAMOFF12. 关闭视频设备。

close(fd);三、常用的结构体(参见/usr/include/linux/videodev2.h):struct v4l2_requestbuffers reqbufs;//向驱动申请帧缓冲的请求,里面包含申请的个数struct v4l2_capability cap;//这个设备的功能,比如是否是视频输入设备struct v4l2_input input; //视频输入struct v4l2_standard std;//视频的制式,比如PAL,NTSCstruct v4l2_format fmt;//帧的格式,比如宽度,高度等struct v4l2_buffer buf;//代表驱动中的一帧v4l2_std_id stdid;//视频制式,例如:V4L2_STD_PAL_Bstruct v4l2_queryctrl query;//查询的控制struct v4l2_control control;//具体控制的值下面具体说明开发流程(网上找的啦,也在学习么)打开视频设备在V4L2中,视频设备被看做一个文件。

关于linuxmtd的理解

关于linuxmtd的理解

关于linuxmtd的理解MTD 设备是象闪存芯片、小型闪存卡、记忆棒等之类的设备,它们在嵌入式设备中的使用正在不断增长。

MTD 驱动程序是在 Linux 下专门为嵌入式环境开发的新的一类驱动程序。

相对于常规块设备驱动程序,使用 MTD 驱动程序的主要优点在于 MTD 驱动程序是专门为基于闪存的设备所设计的,所以它们通常有更好的支持、更好的管理和基于扇区的擦除和读写操作的更好的接口。

Linux 下的 MTD 驱动程序接口被划分为两类模块:用户模块和硬件模块。

MTD 驱动程序设置为了访问特定的闪存设备并将文件系统置于其上,需要将 MTD 子系统编译到内核中。

这包括选择适当的 MTD 硬件和用户模块。

当前,MTD 子系统支持为数众多的闪存设备― 并且有越来越多的驱动程序正被添加进来以用于不同的闪存芯片。

有两个流行的用户模块可启用对闪存的访问:MTD_CHAR 和MTD_BLOCK 。

MTD_CHAR 提供对闪存的原始字符访问,而 MTD_BLOCK 将闪存设计为可以在上面创建文件系统的常规块设备(象IDE 磁盘)。

与MTD_CHAR 关联的设备是/dev/mtd0、mtd1、mtd2(等等),而与MTD_BLOCK 关联的设备是/dev/mtdblock0、mtdblock1(等等)。

由于 MTD_BLOCK 设备提供象块设备那样的模拟,通常更可取的是在这个模拟基础上创建象 FTL 和 JFFS2 那样的文件系统。

为了进行这个操作,可能需要创建分区表将闪存设备分拆到引导装载程序节、内核节和文件系统节中。

Linux 中 MTD 子系统的主要目标是在系统的硬件驱动程序和上层,或用户模块之间提供通用接口。

硬件驱动程序不需要知道象JFFS2 和FTL 那样的用户模块使用的方法。

所有它们真正需要提供的就是一组对底层闪存系统进行 read 、 write 和 erase 操作的简单例程。

MTD 驱动程序是专门针对嵌入式Linux的一种驱动程序,相对于常规块设备驱动程序(比如PC中的IDE硬盘)而言,MTD驱动程序能更好的支持和管理闪存设备,因为它本身就是专为闪存设备而设计的。

嵌入式linux按键驱动程序的设计

嵌入式linux按键驱动程序的设计

数 结 有 个, 一 据 构 三 第 个fileo peration 结
构, 这里终端设备为他提供的值是tty_fops 第一个tty_driver , 终端设备为他提供的值
add_timer(&scant imer),/ / 这里启 动时
间队例 。
一层是键盘扫描码 ,这是根据键盘的不同而 是console ,另一个是 t t y l disc 数据结构。 不同的,第二层是系统扫描码,这是对键盘 比较统一的编码,第三层是 ASI C C 码, 从 控制台为他提供的值是ttyl disc_NT TY, 在一个进程需要从键盘上读取值时 , 系统扫描码到 ASI C C 码的转换,我们可以 照抄标准PS / 2 键盘的码表转换函数,从第 li n u x 首先通过控制台的读操作函数,然后 调用tty- disc的read_chan 函数从链路规则中 一层,到第二层的转换 ,我们需要自己提 J 读数据 ,如果终端 设备的缓冲区中有数据 , 供。这里由于我们只设计了8 个按键,因此 可以简单的用一个swich case 语句完成,不 则将数据回显出来 ,如果缓冲区中没有数 需要复杂的转换。值的注意的是这几函数都 据 ,则进程睡眠等待中断发生。
初始化键盘。这里要参考硬件手册,如初始 化LH7A404 的GPIOF 的第一个引脚, 通过 相关的寄存器配置把他设置为中断上升沿触 发方式,然后通过l i n u x 内核提供的函数
/ / wait- for- release () 是定义 好的每
10 秒要执行的函数,就是在这个函数中检测 GP IOF I 引脚是否断开。
是scan-code 的回 数, 须 态 译 调函 必 静 编 进
内核 。
的驱动程序, 以让我们的系统更加的简捷高 效。本文在研究了与终端相关的驱动程序 后, 给出了 在lh 7a404 下设计按键驱动程序

linux 安装virtio驱动的方法

linux 安装virtio驱动的方法一、什么是virtio驱动virtio驱动是一种用于虚拟化环境中的通用驱动程序,它提供了一种标准的接口,使得虚拟机可以与宿主机之间进行高效的数据传输和通信。

virtio驱动支持各种不同的设备类型,如网络适配器、磁盘控制器等,可以提高虚拟机的性能和稳定性。

二、安装virtio驱动的准备工作在安装virtio驱动之前,需要先准备以下工作:1. 确认虚拟化环境:确保已经在虚拟机中安装了KVM或者其他虚拟化软件,并且虚拟机已经开启了virtio设备的支持。

2. 下载virtio驱动:从官方网站或其他可信来源下载virtio驱动的安装包,一般以ISO镜像的形式提供。

三、安装virtio驱动安装virtio驱动的具体步骤如下:1. 将virtio驱动ISO镜像挂载到虚拟机中,可以通过以下命令挂载: ```# mount /dev/cdrom /mnt```其中,/dev/cdrom是ISO镜像所在的设备,/mnt是挂载点。

2. 进入virtio驱动的安装目录,一般是/mnt目录,可以通过以下命令进入:```# cd /mnt```3. 根据需要安装相应的virtio驱动,如网络适配器驱动、磁盘控制器驱动等。

执行以下命令安装网络适配器驱动:```# ./install.sh -n```执行以下命令安装磁盘控制器驱动:```# ./install.sh -d```其中,-n表示安装网络适配器驱动,-d表示安装磁盘控制器驱动。

根据实际需要选择对应的选项。

4. 完成安装后,重新启动虚拟机以使驱动生效。

四、验证virtio驱动是否安装成功安装完成后,可以通过以下方法验证virtio驱动是否成功安装:1. 检查设备:执行以下命令查看是否存在virtio设备:```# lspci | grep Virtio```如果输出中存在virtio设备,则说明驱动安装成功。

2. 检查驱动模块:执行以下命令查看是否加载了virtio驱动的模块: ```# lsmod | grep virtio```如果输出中存在virtio驱动的模块,则说明驱动加载成功。

linux驱动工程师面试题整理.doc

1、字符型驱动设备你是怎么创建设备文件的,就是/dev/下面的设备文件,供上层应用程序打开使用的文件?答:niknod命令结合设备的主设备号和次设备号,可创建一个设备文件。

评:这只是其中一种方式,也叫手动创建设备文件。

还有UDEV/MDEV自动创建设备文件的方式,UDEV/MDEV是运行在用户态的程序,可以动态管理设备文件,包括•创建和删除设备文件,运行在用八态意味着系统要运行Z后。

那么在系统启动期间还有dcvfs创建了设备文件。

一共有三种方式可以创建设备文件。

2、写一个中断服务需要注意哪些?如果中断产生之后要做比较多的事情你是怎么做的?答:中断处理例程应该尽量短,把能放在后半段(tasklet,等待队列等)的任务尽量放在后半段。

评:写一个屮断服务程序要注意快进快出,在中断服务程序里面尽量快速釆集信息,包括硬件信息,然后推出中断,要做其它事情可以使用工作队列或者tasklet方式。

也就是中断上半部和下半部。

第二:中断服务程序中不能有阻塞操作。

为什么?大家可以讨论。

第三:屮断服务程序注意返回值,要用操作系统定义的宏做为返回值,而不是自己定义的OK, FAIL 之类的。

3、自旋锁和信号量在互斥使用时需要注意哪些?在中断服务程序里面的互斥是使用自旋锁还是信号量?还是两者都能用?为什么?答:使用自旋锁的进程不能睡眠,使用信号暈的进程可以睡眠。

屮断服务例程屮的互斥使用的是白旋锁,原因是在屮断处理例程屮,硬屮断是关闭的,这样会丢失可能到来的屮断。

4、原子操作你怎么理解?为了实现一个互斥,自己定义一个变量作为标记来作为一个资源只有一个使用者行不行?答:原子操作指的是无法被打断的操作。

我没懂第二句是什么意思,口己定义一个变量怎么可能标记资源的使用情况?其他进程又看不见这个变量评:第二句话的意思是:定义一个变量,比如int flag =0;if (flag == 0){flag = 1;操作临界区;flag = 0;}这样对否?5、insmod 一个驱动模块,会执行模块中的哪个函数?rmmod呢?这两个函数在设计上要注意哪些?遇到过卸载驱动出现异常没?是什么问题引起的?答:insmod调用init函数,rmmod调用exit函数。

串口调试利器--Minicom配置及使用详解

串⼝调试利器--Minicom配置及使⽤详解⽬录Minicom是Linux下应⽤⽐较⼴泛⼀个串⼝通信⼯具,就像Windows下的超级终端,可⽤来与串⼝设备通信,如调试交换机和Modem等。

因为现在笔记本电脑基本不配备串⾏接⼝,所以,usb转串⼝成为硬件调试时的必然选择。

准备及安装minicom串⼝设备及⽂件权限Linux内核已经集成PL2303的驱动,在dev下的名称是ttyUSB*。

如果没有显⽰设备,打开内核配置相关选项,重新编译内核。

lsusb查看设备详情lsusbBus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 004 Device 009: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial PortBus 005 Device 002: ID 046d:c05a Logitech, Inc. Optical Mouse M90Bus 006 Device 002: ID 046d:c31d Logitech, Inc.usb 004正是我们挂上去的usb转串⼝线缆,使⽤的芯⽚是PL2303。

查看ttyUSB*设备权限linux下的所有操作都是⽂件操作,在对串⼝操作之前,我们应该先确认⾃⼰对该⽂件有没有读写权限。

linux下的usb串⼝命名为ttyUSB*,运⾏下⾯命令,可以看到设备挂载及⽂件权限情况。

ls -l /dev/ttyUSB*crw-rw---- 1 root dialout 188, 0 Apr 10 17:10 /dev/ttyUSB0正如上⾯显⽰,ttyUSB0这个设备是root所有的,所以,我们以普通⽤户⾝份打开minicom是没法访问该⽂件的。

linux下串口设备命名规则

linux下串口设备命名规则在Linux操作系统中,串口设备的命名规则是由udev(设备节点管理器)动态分配的,其规则是基于设备的物理路径和设备类别。

Linux系统中的串口设备通常以TTY(teletypewriter)开头命名,具体命名规则如下:1. TTY设备命名规则在Linux系统中,串口设备通常命名为/dev/ttyS[0-3]和/dev/ttyUSB[0-3]。

其中,ttyS表示在主板上的串口设备,ttyUSB表示使用USB转串口适配器的设备。

[0-3]表示可用的串口设备数量,可以根据系统硬件配置的不同而有所变动。

2.物理路径规则串口设备的命名规则还与设备所连接的物理接口有关。

每个串口设备都会在/dev目录下创建一个设备节点。

例如,串口1(第一个串口)会创建/dev/ttyS0设备节点,串口2(第二个串口)会创建/dev/ttyS1设备节点,以此类推。

对于使用USB转串口适配器连接的设备,udev会根据USB总线和端口的信息进行命名。

例如,如果一个USB转串口适配器插入到了USB2.0总线上的第1个端口,那么它将被命名为/dev/ttyUSB0设备节点。

3.设备类别规则Linux系统将串口设备分为两个类别:主板上的物理串口设备和通过USB转串口适配器连接的设备。

主板上的物理串口设备包括集成在主板上的串口接口,这些接口通常标记为COM1、COM2等。

通过USB转串口适配器连接的设备需要通过udev进行识别和命名。

4. udev规则udev是Linux系统中的设备节点管理器,通过udev规则可以定制设备的命名和属性等。

udev规则通常存储在/etc/udev/rules.d目录下的文件中。

在udev规则中,可以根据设备的属性(例如设备的Vendor ID和Product ID)对设备进行过滤,从而指定设备的命名规则。

例如,可以通过以下udev规则将某个Vendor ID和Product ID 的设备命名为/dev/my_serial_device:```SUBSYSTEM=="tty", ATTRS{idVendor}=="xxxx",ATTRS{idProduct}=="yyyy", NAME="my_serial_device"```总结:Linux系统下串口设备的命名规则是由udev动态分配的,其命名规则基于设备的物理路径和设备类别。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux终端tty设备驱动

在Linux系统中,终端设备非常重要,没有终端设备,系统将无法向用户反馈信息,Linux中包含控制台、串口和伪终端3类终端设备。 14.1节阐述了终端设备的概念及分类,14.2节给出了Linux终端设备驱动的框架结构,重点描述tty_driver结构体及其成员。14.3~14.5节在14.2节的基础上,分别给出了Linux终端设备驱动模块加载/卸载函数和open()、close()函数,数据读写流程及tty设备线路设置的编程方法。在Linux中,串口驱动完全遵循tty驱动的框架结构,但是进行了底层操作的再次封装,14.6节描述了Linux针对串口tty驱动的这一封装,14.7节则具体给出了串口tty驱动的实现方法。14.8节基于14.6和14.7节的讲解给出了串口tty驱动的设计实例,即S3C2410集成UART的驱动。 14.1终端设备 在Linux系统中,终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备。tty是Teletype的缩写,Teletype是最早出现的一种终端设备,很像电传打字机,是由Teletype公司生产的。Linux中包含如下几类终端设备: 1、串行端口终端(/dev/ttySn) 串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。这些串行端口所对应的设备名称是 /dev/ttyS0(或/dev/tts/0)、/dev/ttyS1(或/dev/tts/1)等,设备号分别是(4,0)、(4,1)等。 在命令行上把标准输出重定向到端口对应的设备文件名上就可以通过该端口发送数据,例如,在命令行提示符下键入: echo test > /dev/ttyS1会把单词“test”发送到连接在ttyS1端口的设备上。 2.伪终端(/dev/pty/) 伪终端(Pseudo Terminal)是成对的逻辑终端设备,并存在成对的设备文件,如/dev/ptyp3和/dev/ttyp3,它们与实际物理设备并不直接相关。如果一个程序把ttyp3看作是一个串行端口设备,则它对该端口的读/写操作会反映在该逻辑终端设备对应的ptyp3上,而ptyp3则是另一个程序用于读写操作的逻辑设备。这样,两个程序就可以通过这种逻辑设备进行互相交流,使用ttyp3的程序会认为自己正在与一个串行端口进行通信。 以telnet 为例,如果某人在使用telnet程序连接到Linux系统,则telnet程序就可能会开始连接到设备ptyp2上,而此时一个getty程序会运行在对应的ttyp2端口上。当telnet从远端获取了一个字符时,该字符就会通过ptyp2、ttyp2传递给 getty程序,而getty程序则会通过ttyp2、ptyp2和telnet程序返回“login:”字符串信息。这样,登录程序与telnet程序 就通过伪终端进行通信。通过使用适当的软件,可以把2个或多个伪终端设备连接到同一个物理串行端口上。 3.控制台终端(/dev/ttyn, /dev/console) 如果当前进程有控制终端(Controlling Terminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。可以使用命令“ps –ax”来查看进程与哪个控制终端相连使用命令“tty”可以查看它具体对应哪个实际终端设备。/dev/tty有些类似于到实际所使用终端设备的一个联接。 在UNIX系统中,计算机显示器通常被称为控制台终端(Console)。它仿真了类型为Linux的一种终端(TERM=Linux),并且有一些设备特殊文件与之相关联:tty0、tty1、tty2等。当用户在控制台上登录时,使用的是tty1。使用Alt+[F1—F6]组合键时,我们就可以切换到tty2、tty3等上面去。tty1–tty6等称为虚拟终端,而tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上。因此不管当前正在使用哪个虚拟终端,系统信息都会发送到控制台终端上。用户可以登录到不同的虚拟终端上去,因而可以让系统同时有几个不同的会话期存在。只有系统或超级用户root可以向/dev/tty0进行写操作。 在Linux 中,可以在系统启动命令行里指定当前的输出终端,格式如下: console=device, options device指代的是终端设备,可以是tty0(前台的虚拟终端)、ttyX(第X个虚拟终端)、ttySX(第X个串口)、lp0(第一个并口)等。options指代对device进行的设置,它取决于具体的设备驱动。对于串口设备,参数用来定义为:波特率、校验位、位数,格式为BBBBPN,其中BBBB表示波特率,P表示校验(n/o/e),N表示位数,默认options是9600n8。 用户可以在内核命令行中同时设定多个终端,这样输出将会在所有的终端上显示,而当用户调用open()打开/dev/console时,最后一个终端将会返回作为当前值。例如: console=ttyS1, 9600 console=tty0 定义了2个终端,而调用open()打开/dev/console时,将使用虚拟终端tty0。但是内核消息会在tty0 VGA虚拟终端和串口ttyS1上同时显示。 通过查看/proc/tty/drivers文件可以获知什么类型的tty设备存在以及什么驱动被加载到内核,这个文件包括一个当前存在的不同 tty 驱动的列表,包括驱动名、缺省的节点名、驱动的主编号、这个驱动使用的次编号范围,以及 tty 驱动的类型。例如,下面给出了一个/proc/tty/drivers文件的例子:

14.2终端设备驱动结构 Linux内核中 tty的层次结构如图14.1所示,包含tty核心、tty线路规程和tty驱动,tty 线路规程的工作是以特殊的方式格式化从一个用户或者硬件收到的数据,这种格式化常常采用一个协议转换的形式,例如 PPP 和 Bluetooth。tty设备发送数据的流程为:tty核心从一个用户获取将要发送给一个 tty设备的数据,tty核心将数据传递给tty线路规程驱动,接着数据被传递到tty驱动,tty驱动将数据转换为可以发送给硬件的格式。接收数据的流程为: 从tty硬件接收到的数据向上交给tty驱动,进入tty线路规程驱动,再进入 tty 核心,在这里它被一个用户获取。尽管大多数时候tty核心和tty之间的数据传输会经历tty线路规程的转换,但是tty驱动与tty核心之间也可以直接传输数据。

图14.1 tty分层结构 图14.2显示了与tty相关的主要源文件及数据的流向。tty_io.c定义了tty 设备通用的file_operations结构体并实现了接口函数tty_register_driver()用于注册tty设备,它会利用 fs/char_dev.c提供的接口函数注册字符设备,与具体设备对应的tty驱动将实现tty_driver结构体中的成员函数。同时 tty_io.c也提供了tty_register_ldisc()接口函数用于注册线路规程,n_tty.c文件则实现了tty_disc结构体中的成员。

图14.2 tty主要源文件关系及数据流向 从图14.2可以看出,特定tty设备驱动的主体工作是填充tty_driver结构体中的成员,实现其中的成员函数,tty_driver结构体的定义如代码清单14.1。 代码清单14.1 tty_driver结构体 1 struct tty_driver 2 { 3 int magic; 4 struct cdev cdev; /* 对应的字符设备cdev */ 5 struct module *owner; /*这个驱动的模块拥有者 */ 6 const char *driver_name; 7 const char *devfs_name; 8 const char *name; /* 设备名 */ 9 int name_base; /* offset of printed name */ 10 int major; /* 主设备号 */ 11 int minor_start; /* 开始次设备号 */ 12 int minor_num; /* 设备数量 */ 13 int num; /* 被分配的设备数量 */ 14 short type; /* tty驱动的类型 */ 15 short subtype; /* tty驱动的子类型 */ 16 struct termios init_termios; /* 初始线路设置 */ 17 int flags; /* tty驱动标志 */ 18 int refcount; /*引用计数(针对可加载的tty驱动) */ 19 struct proc_dir_entry *proc_entry; /* /proc文件系统入口 */ 20 struct tty_driver *other; /* 仅对PTY驱动有意义 */ 21 ... 22 /* 接口函数 */ 23 int(*open)(struct tty_struct *tty, struct file *filp); 24 void(*close)(struct tty_struct *tty, struct file *filp); 25 int(*write)(struct tty_struct *tty, const unsigned char *buf, int count); 26 void(*put_char)(struct tty_struct *tty, unsigned char ch); 27 void(*flush_chars)(struct tty_struct *tty); 28 int(*write_room)(struct tty_struct *tty); 29 int(*chars_in_buffer)(struct tty_struct *tty); 30 int(*ioctl)(struct tty_struct *tty, struct file *file, unsigned int cmd, 31 unsigned long arg); 32 void(*set_termios)(struct tty_struct *tty, struct termios *old); 33 void(*throttle)(struct tty_struct *tty); 34 void(*unthrottle)(struct tty_struct *tty); 35 void(*stop)(struct tty_struct *tty); 36 void(*start)(struct tty_struct *tty); 37 void(*hangup)(struct tty_struct *tty); 38 void(*break_ctl)(struct tty_struct *tty, int state); 39 void(*flush_buffer)(struct tty_struct *tty); 40 void(*set_ldisc)(struct tty_struct *tty);

相关文档
最新文档