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

2023-11-19

终端连接控制(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刻录机来说,属性有刻录速度、颜色深度等等。我这里只大概的分析了一下终端的连接属性。往后会更多的分析其它的设备文件连接属性。





 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

终端连接控制(stty的编写) 的相关文章

随机推荐

  • 基于SSM框架的多文件上传Controller类编写

    前端代码
  • Spring Boot 从Json静态文件中读取数据

    Spring Boot 从Json静态文件中读取数据 在实体中 通常使用类似字典表的文件来表示属性 文件大都配置在配置文件中 也可以是静态文件 本次记录如何从静态json文件中读取所需字段 1 文件格式以及路径 2 加载文件 import
  • QT进程间通信 详细介绍

    在QT中 信号和槽的机制取代了这种繁杂的 易崩溃的对象通信机制 信号是当对象状态改变时所发出的 槽是用来接收发射的信号并响应相应事件的类的成员函数 信号和槽的连接是通过connect 函数来实现的 AD 1 QT通信机制 为了更好的实现QT
  • MVC三层架构

    1 什么是MVC Model View Controller 模型 视图 控制器 模型就是Java对应数据库的那些字段 实体类 视图 就是JSP页面 控制器 就是Servlet负责跳转页面 Controller作用 Controller其实
  • Android addview—动态添加view

    一 前言 在日常的开发中经常遇到需要动态添加子view的情况 addview是ViewGroup的特有方法 可以在布局中动态添加view 而view是不存在这个方法的 二 使用方式 1 方法介绍 addview有以下几种方式 addView
  • vue+websocket+express+mongodb实战项目(实时聊天)(二)

    原项目地址 vue websocket express mongodb实战项目 实时聊天 一 http blog csdn net blueblueskyhua article details 70807847 github地址 https
  • JAVA按钮编程_Java编程实现swing圆形按钮实例代码

    Swing是一个为Java设计的GUI工具包 Swing是JAVA基础类的一部分 Swing包括了图形用户界面 GUI 器件如 文本框 按钮 分隔窗格和表 Swing提供许多比AWT更好的屏幕显示元素 它们用纯Java写成 所以同Java本
  • Linux——pthread_create()

    1 pthread create pthread create是 Unix Linux Mac OS X 等操作系统的创建线程的函数 它的功能是创建线程 实际上就是确定调用该线程函数的入口点 在线程创建以后 就开始运行相关的线程函数 函数原
  • KITTI SOTA!Dual Fusion:减少Lidar-Camera融合特征不对齐问题

    点击下方卡片 关注 自动驾驶之心 公众号 ADAS巨卷干货 即可获取 点击进入 自动驾驶之心 多传感器融合 技术交流群 后台回复 多传感器融合综述 获取图像 激光雷达 毫米波雷达融合综述等干货资料 摘要 融合来自相机和激光雷达传感器的数据是
  • 基于ICL8038的正弦波、方波和三角波发生器protues仿真设计

    一 设计任务与要求 设计 组装 调试信号发生器电路 使它能输出正弦波 方波和三角波 可采用集成芯片ICL8083 其频率在20HZ 20KHZ范围内连续可调 输出正弦波 方波 三角波 正弦波 二 原理电路设计 1 设计方案 方案的结构框图如
  • ToBase64String方法 - 理想的地方的日志 - 网易博客

    用ToBase64String方法可以在不丢失数据的情况下将字节数组转成字符串 在ToBase64String方法中 会对字节数组中的连续三字节进行一次编码 编码得的字符串长度为4位 而且得出来的4位的字符串里面的字符肯定是由大小写字母 数
  • 如何发现系统改进点,优化点,提高点,新系统 边界感不要太强

    技术人员规划能力 如何规划新的系统 技术规划能力 个人渣记录仅为自己搜索用的博客 CSDN博客 1 协作中 双方系统对接 边界感不要太强 肯定会不爽 不爽的点里可以挖掘改进点 肯定会有很多冲突 对方技能欠缺 对方耽误你的时间 可以想下有没有
  • 三分钟阿里云服务器u1通用算力型性能、使用限制及费用说明

    阿里云服务器u1是通用算力型云服务器 CPU采用2 5 GHz主频的Intel R Xeon R Platinum处理器 通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景 比如业务HA
  • 关于人脸识别的心得随笔(持续更新)

    2020 4 25 目前 在监控系统图像中 可以将肤色作为人脸识别的依据 RGB颜色空间是由三基色组成 亮度色度混合 肤色聚集效果差 需要转换到亮度与色度分离的模型 HSV模型 其中的脸部区域像素H分量中 效果最佳 已知的数据降维的算法有
  • Connection.setAutoCommit使用的注意事项

    setAutoCommit总的来说就是保持数据的完整性 一个系统的更新操作可能要涉及多张表 需多个SQL语句进行操作 循环里连续的进行插入操作 如果你在开始时设置了 conn setAutoCommit false 最后才进行conn co
  • Spring-messaging (STOMP) @SendTo 与 @SendToUser的区别

    SendTo 与 SendToUser 是Spring的STOMP协议中注解的标签 SendTo 会将接收到的消息发送到指定的路由目的地 所有订阅该消息的用户都能收到 属于广播 SendToUser 消息目的地有UserDestinatio
  • QRegexp、QRegularExpression的用法学习

    QRegexp QRegularExpression的用法学习 文章目录 QRegexp QRegularExpression的用法学习 QRegexp QRegularExpression 模式选项 QRegexp Regexp 由表达式
  • 11.Linux下Spark的安装配置以及spark-shell的启动和 Spark集群环境搭建

    本案例软件包 链接 https pan baidu com s 1zABhjj2umontXe2CYBW DQ 提取码 1123 若链接失效在下面评论 我会及时更新 目录 1 安装Spark 1 先用xftp将安装包传到home hadoo
  • 2.HTTP协议(Requset、Response)

    目录 http协议 http报文解析 Http请求报文 浏览器 gt 服务器 1 请求行 2 请求头 3 空行 java处理http请求的常用方法 Http响应报文 服务器 gt 浏览器 1 响应行 2 响应头 3 响应正文 实体内容 ja
  • 终端连接控制(stty的编写)

    终端连接控制 stty的编写 一 背景 文件与目录在之前已经学习过了 文件中包含着数据 这些数据可以被读出 写入 也可以用以操作 但文件不仅仅是计算机唯一的数据来源 计算机的数据还可以来自于许多的外部设备 比如扫描仪 照相机 鼠标等输入设备