终端连接控制(stty的编写)

终端连接控制(stty的编写)

一、背景

文件与目录在之前已经学习过了。文件中包含着数据,这些数据可以被读出、写入,也可以用以操作。但文件不仅仅是计算机唯一的数据来源,计算机的数据还可以来自于许多的外部设备,比如扫描仪、照相机、鼠标等输入设备,还有扬声器、打印机等输出设备。总之数据来源多种多样,并不仅局限于文件。那么这些外部设备的连接是怎么样的呢,其与进程协同工作时的方式(属性)如何来修改呢。这就是本文所要探究的。

二、外部设备与磁盘文件的联系

文件我们都已经很熟悉了,文件通过目录中的文件名来定位,文件名有一个i-节点与之对应。而i-节点中有文件的属性且包含着指针列表(此指针列表指向文件的数据内容)。而实际上,外部设备在unix系统中也是以文件的形式存储的。我们可以从文件中读数据也可以写数据。同样,我们也可以向设备文件写数据或从中读出数据。

外部设备的文件一般存储于/dev中。

 

这里显示的是我的一些设备文件。但是并不是说所有的设备文件必须要存储于/dev下,并不是这样的,只是一种约定成俗的习惯,当然也可以在别的目录下创建设备文件。

三、终端文件

要想看自己的终端文件名,只需输入tty即可。我的(root)终端文件是这样的。

 

而在另一个终端的用户的终端文件是这样的。

 

如此,如我前面所述,如果我可以使用root用户往/dev/pts/1文件中写入数据,那么应该就可以在用户pf的屏幕上显示出我所写入的数据。这样,我写了一段代码用于此功能,实际上这个即是命令write的功能。

如下所示:

  

这就很清楚的演示了设备文件(终端文件)的操作方法与磁盘文件十分类似,许多的系统调用也都是通用的。

四、外部设备与磁盘文件的不同

第二节讲了它们是十分相似的,都是以文件形式来进行操作。并且系统调用往往也是通用的。但它们却不可能是完全相同的。不同之处主要体现在连接属性上。对于文件来说,它们与进程进行数据的传输是需要缓冲的,缓冲用于文件数据的传输上好处很多,最突出的是缓冲可以容错,而且缓冲是以块为单位传输的,比起字节为单位传输,效率要高很多。但这是文件的连接属性之一,可以开启也可以关闭。但对于终端来说(以终端为例),当然是不需要缓冲,数据需要尽快的从进程传输到终端上来。并且终端也有其许多的连接属性是文件连接属性所没有的,比如回显、奇偶位、暂停位。

五、终端连接的属性

文件连接的属性这里就不啰嗦了,我主要想讨论一下终端连接的属性。

命令stty用于显示或修改终端的连接属性。

显示全部的终端连接属性用-a参数。如下所示:

 

这里有三种类型的属性,一种是开关型,一种是数字型、一种是字符控制型。类型是这么分的,在修改对应类型的属性时也是不同的。具体如何修改?对于开关型的属性,只需输入stty  (-)属性名,括号中的减号可加可不加,若不加,则是打开此属性开关,若加,则是关闭此属性开关。对于数字型与字符控制型,只需输入stty 属性名 修改值,当然,需要修改什么属性就输入什么属性名,而修改值根据自己的需求来定。

六、stty的编程

stty的编程并不复杂,主要会使用两个系统调用:tcgetattrtcsetattr。前一个用来将设备文件的信息传出来,后一个用来将修改过后的信息传回去。并使用掩码来进行测试、置位与清除位。

这里我先编写了一个简单的echo的开关文件。结果如下所示:

 

代码如下:

#include<stdio.h>

#include<termios.h>

#include<stdlib.h>

int main()

{

  struct termios info;

  if(tcgetattr(0,&info)==-1){

    perror("tcgetattr");

    exit(1);

    }

  else{

    if(info.c_lflag&ECHO)

      info.c_lflag&=~ECHO;

    else

      info.c_lflag|=ECHO;

    if(tcsetattr(0,TCSANOW,&info)==-1)

      perror("tcsetattr");

    }

}

  

自己编写的stty结果如下:

 

 

我这里还是拿echo来做测试的,因为结果很明显。


实现stty的代码如下:

#include<stdio.h>

#include<termios.h>

#include<stdlib.h>

#include<string.h>

 

struct termios execute_1(struct termios buff,char *av);

struct termios execute_2(struct termios buff,char *av_1,char *av_2);

 

int main(int argc,char *argv[])

{

  struct termios info;

  struct termios buf;

  if(argc!=2 && argc!=3){

    printf("Usage error\n");

    exit(1);

    }

  if(tcgetattr(0,&info)==-1){

    perror("tcgetattr");

    exit(1);

    }

  if(argc==2){

    buf=execute_1(info,argv[1]);

    tcsetattr(0,TCSANOW,&buf);

    }

  if(argc==3){

    buf=execute_2(info,argv[1],argv[2]);

    tcsetattr(0,TCSANOW,&buf);

    }

}

 

struct termios execute_1(struct termios buff,char *av)

{

  if(strcmp(av,"ignbrk")==0)

    buff.c_iflag|=IGNBRK;

  if(strcmp(av,"-ignbrk")==0)

    buff.c_iflag&=~IGNBRK;

  if(strcmp(av,"brkint")==0)

    buff.c_iflag|=BRKINT;

  if(strcmp(av,"-brkint")==0)

    buff.c_iflag&=~BRKINT;

  if(strcmp(av,"ignpar")==0)

    buff.c_iflag|=IGNPAR;

  if(strcmp(av,"-ignpar")==0)

    buff.c_iflag&=~IGNPAR;

  if(strcmp(av,"parmrk")==0)

    buff.c_iflag|=PARMRK;

  if(strcmp(av,"-parmrk")==0)

    buff.c_iflag&=~PARMRK;

  if(strcmp(av,"inpck")==0)

    buff.c_iflag|=INPCK;

  if(strcmp(av,"-inpck")==0)

    buff.c_iflag&=~INPCK;

  if(strcmp(av,"istrip")==0)

    buff.c_iflag|=ISTRIP;

  if(strcmp(av,"-istrip")==0)

    buff.c_iflag&=~ISTRIP;

  if(strcmp(av,"inlcr")==0)

    buff.c_iflag|=INLCR;

  if(strcmp(av,"-inlcr")==0)

    buff.c_iflag&=~INLCR;

  if(strcmp(av,"igncr")==0)

    buff.c_iflag|=IGNCR;

  if(strcmp(av,"-igncr")==0)

    buff.c_iflag&=~IGNCR;

  if(strcmp(av,"icrnl")==0)

    buff.c_iflag|=ICRNL;

  if(strcmp(av,"-icrnl")==0)

    buff.c_iflag&=~ICRNL;

  if(strcmp(av,"iuclc")==0)

    buff.c_iflag|=IUCLC;

  if(strcmp(av,"-iuclc")==0)

    buff.c_iflag&=~IUCLC;

  if(strcmp(av,"ixon")==0)

    buff.c_iflag|=IXON;

  if(strcmp(av,"-ixon")==0)

    buff.c_iflag&=~IXON;

  if(strcmp(av,"ixany")==0)

    buff.c_iflag|=IXANY;

  if(strcmp(av,"-ixany")==0)

    buff.c_iflag&=~IXANY;

  if(strcmp(av,"ixoff")==0)

    buff.c_iflag|=IXOFF;

  if(strcmp(av,"-ixoff")==0)

    buff.c_iflag&=~IXOFF;

  if(strcmp(av,"imaxbel")==0)

    buff.c_iflag|=IMAXBEL;

  if(strcmp(av,"-imaxbel")==0)

    buff.c_iflag&=~IMAXBEL;

  if(strcmp(av,"opost")==0)

    buff.c_oflag|=OPOST;

  if(strcmp(av,"-opost")==0)

    buff.c_oflag&=~OPOST;

  if(strcmp(av,"onlcr")==0)

    buff.c_oflag|=ONLCR;

  if(strcmp(av,"-onlcr")==0)

    buff.c_oflag&=~ONLCR;

  if(strcmp(av,"olcuc")==0)

    buff.c_oflag|=OLCUC;

  if(strcmp(av,"-olcuc")==0)

    buff.c_oflag&=~OLCUC;

  if(strcmp(av,"ocrnl")==0)

    buff.c_oflag|=OCRNL;

  if(strcmp(av,"-ocrnl")==0)

    buff.c_oflag&=~OCRNL;

  if(strcmp(av,"onlret")==0)

    buff.c_oflag|=ONLRET;

  if(strcmp(av,"-onlret")==0)

    buff.c_oflag&=~ONLRET;

  if(strcmp(av,"ofill")==0)

    buff.c_oflag|=OFILL;

  if(strcmp(av,"-ofill")==0)

    buff.c_oflag&=~OFILL;

  if(strcmp(av,"ofdel")==0)

    buff.c_oflag|=OFDEL;

  if(strcmp(av,"-ofdel")==0)

    buff.c_oflag&=~OFDEL;

  if(strcmp(av,"nldly")==0)

    buff.c_oflag|=NLDLY;

  if(strcmp(av,"-nldly")==0)

    buff.c_oflag&=~NLDLY;

  if(strcmp(av,"crdly")==0)

    buff.c_oflag|=CRDLY;

  if(strcmp(av,"-crdly")==0)

    buff.c_oflag&=~CRDLY;

  if(strcmp(av,"tabdly")==0)

    buff.c_oflag|=TABDLY;

  if(strcmp(av,"-tabdly")==0)

    buff.c_oflag&=~TABDLY;

  if(strcmp(av,"bsdly")==0)

    buff.c_oflag|=BSDLY;

  if(strcmp(av,"-bsdly")==0)

    buff.c_oflag&=~BSDLY;

  if(strcmp(av,"ffdly")==0)

    buff.c_oflag|=FFDLY;

  if(strcmp(av,"-ffdly")==0)

    buff.c_oflag&=~FFDLY;

  if(strcmp(av,"vtdly")==0)

    buff.c_oflag|=VTDLY;

  if(strcmp(av,"-vtdly")==0)

    buff.c_oflag&=~VTDLY;

  if(strcmp(av,"csize")==0)

    buff.c_cflag|=CSIZE;

  if(strcmp(av,"-csize")==0)

    buff.c_cflag&=~CSIZE;

  if(strcmp(av,"cstopb")==0)

    buff.c_cflag|=CSTOPB;

  if(strcmp(av,"-cstopb")==0)

    buff.c_cflag&=~CSTOPB;

  if(strcmp(av,"cread")==0)

    buff.c_cflag|=CREAD;

  if(strcmp(av,"-cread")==0)

    buff.c_cflag&=~CREAD;

  if(strcmp(av,"parenb")==0)

    buff.c_cflag|=PARENB;

  if(strcmp(av,"-parenb")==0)

    buff.c_cflag&=~PARENB;

  if(strcmp(av,"parodd")==0)

    buff.c_cflag|=PARODD;

  if(strcmp(av,"-parodd")==0)

    buff.c_cflag&=~PARODD;

  if(strcmp(av,"hupcl")==0)

    buff.c_cflag|=HUPCL;

  if(strcmp(av,"-hupcl")==0)

    buff.c_cflag&=~HUPCL;

  if(strcmp(av,"clocal")==0)

    buff.c_cflag|=CLOCAL;

  if(strcmp(av,"-clocal")==0)

    buff.c_cflag&=~CLOCAL;

  if(strcmp(av,"crtscts")==0)

    buff.c_cflag|=CRTSCTS;

  if(strcmp(av,"-crtscts")==0)

    buff.c_cflag&=~CRTSCTS;

  if(strcmp(av,"isig")==0)

    buff.c_lflag|=ISIG;

  if(strcmp(av,"-isig")==0)

    buff.c_lflag&=~ISIG;

  if(strcmp(av,"icanon")==0)

    buff.c_lflag|=ICANON;

  if(strcmp(av,"-icanon")==0)

    buff.c_lflag&=~ICANON;

  if(strcmp(av,"echoe")==0)

    buff.c_lflag|=ECHOE;

  if(strcmp(av,"-echoe")==0)

    buff.c_lflag&=~ECHOE;

  if(strcmp(av,"echok")==0)

    buff.c_lflag|=ECHOK;

  if(strcmp(av,"-echok")==0)

    buff.c_lflag&=~ECHOK;

  if(strcmp(av,"echoke")==0)

    buff.c_lflag|=ECHOKE;

  if(strcmp(av,"-echoke")==0)

    buff.c_lflag&=~ECHOKE;

  if(strcmp(av,"echoctl")==0)

    buff.c_lflag|=ECHOCTL;

  if(strcmp(av,"-echoctl")==0)

    buff.c_lflag&=~ECHOCTL;

  if(strcmp(av,"echo")==0)

    buff.c_lflag|=ECHO;

  if(strcmp(av,"-echo")==0)

    buff.c_lflag&=~ECHO;

  if(strcmp(av,"echonl")==0)

    buff.c_lflag|=ECHONL;

  if(strcmp(av,"-echonl")==0)

    buff.c_lflag&=~ECHONL;

  if(strcmp(av,"iexten")==0)

    buff.c_lflag|=IEXTEN;

  if(strcmp(av,"-iexten")==0)

    buff.c_lflag&=~IEXTEN;

  if(strcmp(av,"noflsh")==0)

    buff.c_lflag|=NOFLSH;

  if(strcmp(av,"-noflsh")==0)

    buff.c_lflag&=~NOFLSH;

  if(strcmp(av,"tostop")==0)

    buff.c_lflag|=TOSTOP;

  if(strcmp(av,"-tostop")==0)

    buff.c_lflag&=~TOSTOP;

  if(strcmp(av,"pendin")==0)

    buff.c_lflag|=PENDIN;

  if(strcmp(av,"-pendin")==0)

    buff.c_lflag&=~PENDIN;

  if(strcmp(av,"flusho")==0)

    buff.c_lflag|=FLUSHO;

  if(strcmp(av,"-flusho")==0)

    buff.c_lflag&=~FLUSHO;

  return buff;

}

 

struct termios execute_2(struct termios buff,char *av_1,char *av_2)

{

  if(strcmp(av_1,"intr")==0)

    buff.c_cc[VINTR]=*av_2;

  if(strcmp(av_1,"quit")==0)

    buff.c_cc[VQUIT]=*av_2;

  if(strcmp(av_1,"erase")==0)

    buff.c_cc[VERASE]=*av_2;

  if(strcmp(av_1,"kill")==0)

    buff.c_cc[VKILL]=*av_2;

  if(strcmp(av_1,"eof")==0)

    buff.c_cc[VEOF]=*av_2;

  if(strcmp(av_1,"min")==0)

    buff.c_cc[VMIN]=*av_2;

  if(strcmp(av_1,"eol")==0)

    buff.c_cc[VEOL]=*av_2;

  return buff;

}


七、总结

    这是我第一次从系统的角度来观察设备文件,对于设备文件的学习当然是对比更为熟悉的磁盘文件。从异、同两个角度来观察,相同之处在于两者都是以文件的形式在计算机进行存储,表面来看十分相似,且两者的系统调用也基本通用。不同之处在于连接属性决然不一样。这是理所当然的事情,具体问题具体分析,各个不同的设备文件的连接属性也都不同,对终端来说,属性有回显、奇偶位、暂停位等等,对CD刻录机来说,属性有刻录速度、颜色深度等等。我这里只大概的分析了一下终端的连接属性。往后会更多的分析其它的设备文件连接属性。





 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值