8设备文件

设备文件

Linux把所有设备都映射成了文件

设备文件一般存储在 /dev 目录下

我们可以像操作文件一样操作他们

ls /dev –l

brw-rw----  1 root disk      8,   0 Dec 21 20:00 sda

crw--w----  1 root tty         4,   0 Dec 21 20:00 tty0

b 表示块设备文件

c  表示字符设备文件

区别:

块设备

1.主要用于随机存取。

2.将信息存储在定长块内,IO操作通过内核IO缓冲完成,可以对文件任意位置进行任意长度的 IO操作。

3.比如磁盘。

字符设备

1.主要用于顺序存取。

2.无内核缓冲,只能顺序存取。IO操作的长度为设备要求的块长的整数倍。

3.比如终端,打印机,网络接口等

设备文件操作流程

打开: fd = open(devName, O_RDWR)

备份: ioctl(fd, TCGETA, &oldAttr);

设置: ioctl(fd,  TCSETA, &newAttr);

读:     read(fd, buf, len);

写:     write(fd, buf, len);

恢复: ioctl(fd, TCSETA, &oldAttr);

关闭: close(fd)

终端设备操作

include<unistd.h>

ioctl(int fd, int cmd, struct termio *arg)

cmd 参数

TCGETA        获取终端信息

TCSETA        写入终端信息

TCSETAW     先将当前输入队列发送完毕,再写入设置

TCSETAF      先将当前输入队列清空,再写入设置

include<termio.h>

struct termio 解析:

struct termio

{

unsigned short c_iflag;   //终端输入方式

unsigned short c_oflag;  //终端输出方式

unsigned short c_cflag;  //终端控制方式

unsigned short c_lflag;   //行规则模式

char                  c_line;   

unsigned char  c_cc[NCC];  //控制字符

}

例子:只允许输入小写,大写变小写

void Test_iflag ()

{

      int fd;

      struct termio  new,old;

      char buf[128];

      //获取当前的设备old

      ioctl(STDIN_FILENO,TCGETA,&old);

      //用new接受old,否则new=NULL;

      new=old;

      //设置小写风格,所有输入均为小写

      new.c_iflag|=IUCLC;

      ioctl(STDIN_FILENO,TCSETA,&new);

     

scanf("%s",buf);

      printf("change buf:%s ",buf);

      //恢复原来的设备

      ioctl(STDIN_FILENO,TCSETA,&old);

      scanf("%s",buf);

      printf("resume buf:%s ",buf)

}

例子:只允许输出大写,小写变大写

void Test_oflag()

{

      struct termio  new,old;

      char *buf="hello world";

      printf("oginal buf:%s ",buf);

     

      ioctl(STDOUT_FILENO,TCGETA,&old);

     

      new=old;

      new.c_oflag|=OLCUC;

      ioctl(STDIN_FILENO,TCSETA,&new);

      printf("big buf:%s ",buf);

     

      ioctl(STDIN_FILENO,TCSETA,&old);

     

      printf("resume buf:%s ",buf);

}

注意:

默认ICANON,输入模式为标准模式,有缓冲

设置为 ~ICANON,则输入模式为原始输入,无缓冲

例子1:按下字符,立马输出对应的ASCII,不需要按回车,回车键结束

void Test_lflag()

{

      struct termio  new,old;

     

      ioctl(STDOUT_FILENO,TCGETA,&old);

     

      new=old;

      new.c_lflag&=~ICANON;

     

      ioctl(STDIN_FILENO,TCSETA,&new);

      char ch=0;

      while(ch!=' ')

      {

           scanf("%c",&ch);

           printf("-->%d ",ch);

      }   

      ioctl(STDIN_FILENO,TCSETA,&old);

}

例子2:模拟密码,无显示密码的输入。

      new.c_lflag&=~ECHO;

      ioctl(STDIN_FILENO,TCSETA,&new);

                  

      char pPassWd[16];

      printf("input password :");

      scanf("%s",pPassWd);

      printf("password :%s ",pPassWd);

      ioctl(STDIN_FILENO,TCSETA,&old);

 

例子:当输入超过5个字符或输入字符且超过5秒无操作,提示超时。

注意:输入的字符要在缓冲区中为准。即“sdsasddsad”没有按下回车,只在终端显示,该属性不响应。因此new.c_lflag&=~ICANON;设置为原始输入且使用read(STDIN_FILENO,buf,128),而不是scanf();

void Test_cc()

{

      struct termio  new,old;

      char buf[128];

      ioctl(STDIN_FILENO,TCGETA,&old);

     

      new=old;

      new.c_lflag&=~ICANON;

      new.c_cc[VMIN]=5;       //5个字符

      new.c_cc[VTIME]=50;    //单位是0.1秒,50即5秒

     

      ioctl(STDIN_FILENO,TCSETA,&new);

      read(STDIN_FILENO,buf,128);

      printf(" over time");    

      ioctl(STDIN_FILENO,TCSETA,&old);

     

}

补充:

printf在终端输出时改变颜色

终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关。

转义序列是以 ESC 开头,可以用 33 完成相同的工作(ESC 的 ASCII 码用十进制表示就是 27, = 用八进制表示的 33)。

注意:

[:开始设置的标识;m:结束设置的标志;设置之间使用分号。

33[显示方式;前景色;背景色m

显示方式:0(默认值)、1(高亮)、22(非粗体)、4(下划线)、24(非下划线)、5(闪烁)、25(非闪烁)、7(反显)、27(非反显)

前景色:30(黑色)、31(红色)、32(绿色)、 33(黄色)、34(蓝色)、35(洋红)、36(青色)、37(白色)

背景色:40(黑色)、41(红色)、42(绿色)、 43(黄色)、44(蓝色)、45(洋红)、46(青色)、47(白色)

33[0m 默认

33[1;32;40m 绿色

033[1;31;40m 红色

例子:

printf( "33[1;31;40m 输出红色字符 33[0m" )

原文地址:https://www.cnblogs.com/gd-luojialin/p/9215961.html