Chinaunix首页 | 论坛 | 博客
  • 博客访问: 210020
  • 博文数量: 55
  • 博客积分: 1305
  • 博客等级: 中尉
  • 技术积分: 350
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-11 15:18
文章分类

全部博文(55)

文章存档

2012年(1)

2011年(54)

分类: LINUX

2011-09-26 14:16:21

一、区分/dev/tty/dev/console/dev/pts/dev/ttyn /dev/ttySn

通常我们在linux下看到的控制台(console)是由几个设备完成的。分别是/dev/ttyN.通常使用热键 alt+Fn来在这些虚拟终端之间进行切换。所有的这些tty设备都是由linux/drivers/char/console.c和vt.c对应。

控制终端 /dev/tty指的是当前所处的终端,输出到此的内容只会显示在当前工作的终端显示器上,如果当前进程有控制终端(Controlling Terminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。可以使用命令”ps –ax”来查看进程与哪个控制终端相连。对于你登录的shell,/dev/tty就是你使用的终端,设备号是(5,0)。使用命令”tty”可以查看它具体对应哪个实际终端设备。/dev/tty有些类似于到实际所使用终端设备的一个联接。这个终端文件可以由各个用户共享

控制台终端 /dev/ttyn  n(0到6)  tty1,tty2就是不同的虚拟终端(virtual console).

/dev/console 就是tty0 ,tty0则是当前所使用虚拟终端即激活的虚拟终端的一个别名,系统所产生的信息会发送到该终端上,实际上机器只有一个屏幕,也就是我们看到的这个屏幕,可以理解为console指向激活的那个tty,准确地说是激活的那个tty才将输出显示到console。历史上,console指主机本身的屏幕键盘,而tty指用电缆链接的其它位置的控制台(仅包含屏幕和键盘)。tty0是系统自动打开的,但不用于用户登录

伪终端 /dev/pts是远程登陆(telnet,ssh等)后创建的控制台设备文件所在的目录。

由于可能有好几千个用户登陆,所以/dev/pts其实是动态生成的,不象其他设备文件是构建系统时就已经产生的硬盘节点(如果未使用devfs) 。第一个用户登陆,console的设备文件为/dev/pts/0,第二个为/dev/pts/1,以此类推。这里的0、1、2、3不是具体的标准输入或输出,而是整个控制台。你可尝试 echo "aaaaaa" > /dev/pts0、1、2……。

串行端口终端(/dev/ttySn 
串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。有段时间这些串行端口设备通常被称为终端设备,因为 那时它的最大用途就是用来连接终端。这些串行端口所对应的设备名称是/dev/tts/0(或/dev/ttyS0)、/dev/tts/1(或/dev /ttyS1)等,设备号分别是(4,0)、(4,1)等,分别对应于DOS系统下的COM1、COM2等。若要向一个端口发送数据,可以在命令行上把标 准输出重定向到这些特殊文件名上即可。例如,在命令行提示符下键入:echo test > /dev/ttyS1会把单词”test”发送到连接在ttyS1(COM2)端口的设备上。

二、ioct1函数操纵虚终端设备文件

虚终端,也叫虚屏,它的英文名字为virtual terminal,缩写为VT或vt。在Unix系统用户中,虚终端有着广泛的应用。它解决了主控台单一交互界面的限制,使用户可在保护当前界面的情况下启用另一界面去做另一工作。我们可利用Unix系统提供的系统调用来编制虚终端程序,并可把它加入到我们的应用程序中去。本人就在此虚终端程序的基础上编写了图形软件,它能够保存和恢复先前的界面。可利用ioct1函数操纵虚终端设备文件,实现与Unix系统内核的交互,得到我们所需要的服务。使用ioct1的具体形式如下: 
int ioct1(int filedes,int request,…/*参数*/) 
其中filedes为打开的虚终端设备文件描述符,request为请求的服务,随后的参数可为各种数据类型,视具体情况而定。与虚终端有关的用于ioct1调用中request值主要有以下几个: 
VT_OPENQRY 查找一个可利用的虚终端。用于ioct1系统调用的参数是一个指向长整数的指针。该长整数的值将被置为第一个可利用的无进程在其上打开的虚终端的序号。如果没有可利用的虚终端,则该长整数的值被置为-1。 
VT_GETMODE 获取活动虚终端当前所在的状态。用于ioct1系统调用的参数是一个指向 vt_mode结构的指针。结构vt-mode定义如下: 
struct vt-mode { 
char mode;/* VT mode */ 
char waitv;/* if set,hang on writes when not active */ 
short relsig;/*signal to use for release request */ 
short acqsig; /*signal to use for display acquired */ 
short frsig; /*not use set to 0 */ 

在结构vt_mode中,mode字段的值可为VT_AUTO和VT_PROCESS,它们的宏定义如下: 
#define VT_AUTO 0x00 /*自动切换*/ 
#define VT_PROCESS 0x01 /*进程控制切换*/ 
VT_SETMODE 设置虚终端模式(自动或进程控制)。用于ioctl系统调用的参数是一个″vt_mode″结构的指针(结构定义见VT_GETMODE)。 
VT_GETSTATE 获取全部虚终端的状态信息。用于ioctl的系统调用的参数是一个指向vt_stat结构的指针,该结构定义如下: 
struct vt_stat { 
ushort v_active;/*活动的vt*/ 
ushort v_signal;/*要发送的信号(用于VT_SENDSIG)*/ 
ushort v_state; /*vt位掩码(VT_SENDSIG和VT_GETSTATE)*/ 

该调用在v_active字段返回活动虚终端号,在v_state字段中可获得全部虚终端状态的位掩码(v_state的位x是虚终端x的状态,该位为1说明对应的虚终端是打开状态,否则为可利用状态)。 
VT_SENDSIG 指定要发送给虚终端(在v_state中)的位屏蔽的信号(在v_signa1中)。用于ioct1的系统调用的参数是一个指向vt_stat结构的指针(结构定义见前面VT_GETSTATE)。 
VT_RELDISP 用于告诉虚终端管理器进程是否已经释放了显示。一个零值指示拒绝释放显示。 
VT_ACTIVATE 使在参数中指定的虚终端号为活动虚终端。″VT″管理器将产生一个切换,如同在键盘上按组合热键一样。如果指定的虚终端不处于打开状态或者不存在,调用将失败,并置errno的值为ENXI0。 
VT_WAITACTIVE 等待虚终端被激活,不需要参数。

有了上面的介绍,现在我们就可以实现虚终端了: 
1?查找是否有可利用的虚终端,如没有,则结束。 
2?打开可利用虚终端设备文件,以便进行。 
3?利用ioct1的TCSETSW功能设置虚终端参数,其作用同Unix的stty命令一样。 
4?利用ioct1的VT_ACTIVATE功能激活虚终端,并利用VT_WAITACTIVE功能等待其可用。 
5?用putenv函数设置环境变量。 
至此,一个虚终端程序就实现了(当然,是利用Unix系统提供的功能,但它与Unix提供的newvt命令的实现并无区别)。在这个虚终端里,我们可方便地实现我们自己想要的功能,而不必担心会破坏原来的环境。

三 、虚拟控制台的切换过程

1. 1) 虚拟终端的切换在控制台软中断中运行,当按"ALT F1" 时,键盘中断设置变量want_console 为0,然后激发控制台软中断(console_softint),如果请求的控制台存在并且不等于当前控制台,这时调用change_console(want_console)切换控制台。 
2) 当前控制台就是直接操作物理屏幕的控制台,用fg_console变量指示。控制台的切换就是物理屏幕在虚拟控制台之间的切换,与CPU在进程之间的切换有些类似,当前物理显示屏的内容被保存在当前控制台的局部屏幕缓冲区之中,新控制台成为当前控制台,新当前控制台的局部屏幕被恢复到物理屏幕。当输出到背景控制台时, 文本被缓冲在该控制台的局部屏幕缓冲区中。 
3) 当应用程序在某个虚拟控制台中使显示设备处于图形状态时,内核无法正常切换到另一文本控制台,这时可以用KDSETMODE ioctl将控制台设置为KD_GRAPHICS状态,这样可防止控制台输出和切换操作。为了在图形状态下也能切换控制台,可以采用进程屏幕切换机制(VT_PROCESS)。当某个控制台被某个进程设置为VT_PROCESS模式时,当离开该控制台时, 内核向该进程生成"释放"信号(relsig),当进入该控制台时,内核向该进程发送"获得"信号(acqsig)。该信息由vt_mode结构描述,用VT_SETMODE ioctl设置。 
4) 对于X窗口来说,X服务器启动时切换到第一个未分配的控制台来使用显示器,当离开该控制台时,内核在X服务器中产生信号,X服务器将显示器恢复为文本状态,然后向内核发出"显示器已释放"(VT_RELDISP)设备控制消息,内核再接着将显示器切换到新的控制台。反之,当从文本控制台进入X窗口的图形控制台时,内核保存当前文本控制台的屏幕现场后向X服务器发出信号,X服务器再将屏幕恢复到图形状态。

、基本的读写FrameBuffer的步骤:

1 打开framebuffer设备;

2 通过ioctl取得fixed screen information;

3 通过ioctl取得variable screen information;

4 通过mmap映射设备内存到进程空间;

5 写framebuffer;

6 关闭framebuffer设备;

五 、在DirectFBPicoGL以独占方式操作FrameBuffer

打开了framebuffer,你可以在其上画图,写字。屏幕上就及时能显示你往framebuffer里填充的内容。但是在多进程操作framebuffer的环境下,比如在一个拥有窗口管理环境下,操作framebuffer显示了全屏的一幅图片,此时窗口管理器有个进程在不断的更新系统当前时间,这样就存在当前图片显示不完整的情况。此时实际上只需要当前进程显示完整的一幅图片,改图片的显示区域不希望被其他操作framebuffer的进程所干扰。 
如何避免这种情况的发生?方法就是操作tty设备。原理很简单,就是打开一个新的终端tty设备,并把该设备激活,设为图形模式,让改终端独占 framebuffer设备,然后再输出图形,这样,即使有其他进程在操作framebuffer,当前终端的framebuffer就不会被重刷,从而实现了稳定的输出。 
一般来说linux系统中会存在7个tty设备,tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上.tty1--tty6都称为虚拟终端设备,那么打开哪一个新的tty设备呢?先用ioctl(ConsoleFD, VT_OPENQRY, &vtnumber)查询一下当前打开的虚拟终端数量,一般的发行版都是打开6个,即tty1~tty6,这个可以在/etc/inittab里面控制。另外,tty0是系统自动打开的,但不用于用户登录,所以查询的结果是一共打开7个,vtnumber=7,这个数字也就是下一次可用的终端号,即 tty7。

DirectFB和PicoGL在使用framebuffer的时候都避免了这种情况的发生,方法就是操作tty设备。原理很简单,就是打开一个新的终端tty设备,把它激活,并设为图形模式,让它独占framebuffer设备,然后再输出图形,这样,即使用户按Alt+Fi也无法切换终端,framebuffer就不会被重刷,从而实现了稳定的输出。

那么打开哪一个新的tty设备呢?先用ioctl(ConsoleFD, VT_OPENQRY, &vtnumber)查一下当前打开的虚拟终端数量,一般的发行版都是打开6个,即tty1~tty6,这个可以在/etc/inittab里面控制。另外,tty0是系统自动打开的,但不用于用户登录,所以查询的结果是一共打开7个,vtnumber=7,这个数字也就是下一次可用的终端号,即tty7。

六、   /dev/tty的妙用

标准的输入输出往往不能够输入到/dev/tty文件中。而是需要通过重定向功能,把一些命令的输出重定向到这个文件中。另外需要说明的是,普通终端的话往往是每个用户之间相互独立的。也就是说,每个用户的输出彼此之间是互不干涉的。但是/det/tty这个文件由其特殊性。这个终端文件可以由各个用户共享。

1. 利用这个文件来屏蔽不需要的结果信息。 
系统工程师可以轻松的通过/dev/tty文件来过滤这些无用的提示信息。如只需要把脚本程序的运行结果通过重定向服务重定向到/dev/tty文件中。在这个重定向的过程中,Unix系统的会采取一定的内部处理机制,会忽略掉echo等命令。也就是说,只要把命令的标准输出重定向到这个文件中,则利用echo命令设置的一些提示信息都会被忽略掉。此时在这个文件中,存储的只有一些必要的运行信息,如错误或者警告信息等等。

2. 当作其他命令的参数。

系统工程师即希望把命令的结果输出到终端中,同时保存到一个文件中,就需要利用tee命令,如who | tee userinfo.txt。(注意,如果利用了tee命令的话,在可以不再使用重定向符号)。到这里为止没有涉及到/dev/tty这个文件。who | tee userinfo.txt这个命令的显示结果,只会显示当前登录的用户明细,而不会显示当前有多少个用户登录到系统中。如果其他脚本程序需要用到当前登录用户的总数而不需要明细,那么该如何处理呢?此时就需要利用/dev/tty文件作为参数了。如可以使用who | tee /dev/tty |wc –l 命令。这个命令可以把当前用户的明细以及总共的用户数量显示出来。以上这个命令其实我们可以分为四个步骤。第一步系统先执行who命令;第二步tee命令把who命令执行对结果保存到/dev/tty文件中;第三步wc命令会统计/dev/tty文件中的行数。由于一个终端对相当于一个文件,故利用wc命令可以统计出当前系统登录用户的数量。第四步再把这个统计的结果显示在终端上。所以说,把/dev/tty文件当作其他命令的一个参数,一个一起组合以实现一些比较复杂的功能。

需要注意的是命令 >/dev/tty与命令> file连个命令其最终的结果有可能相同,也有可能不同。前者在把命令的显示结果保存到/dev/tty文件中的时候,会过滤掉echo等命令设置的信息。而后者这个命令这会把显示的结果一五一十的照搬到file文件中去。也就是说,如果在命令或者脚本程序中没有echo等类似的命令设置信息的话在,则这两个命令重定向文件后所保存文件的内容是一致的。但是如果在命令或者脚本程序中有类似的提示命令的话,则两个文件的显示结果则会不同。为此系统工程师就需要根据自己的实际需要,来选择合适的重定向文件,看看有否必要采用/dev/tty文件。

阅读(3119) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~