linux之操作磁盘文件与tty设备文件

   stty用于改变和显示终端的设置信息,准确的说是改变终端驱动程序的设置信息.tty的驱动程序位于内核,内核用于连接外部世界(磁盘文件、设备文件)与进程间的数据交换.而tty也属于设备文件中的一种,

   现在介绍两种操作磁盘文件的方式,分别采用系统的函数调用和C语言的库函数调用.

     第一种:系统库函数

  

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define LENGTH 100

int main()
{

	int fd,len;
	char str[LENGTH];
	char *content="undergrowth";
	fd=open("un.txt",O_CREAT | O_RDWR,S_IRUSR|S_IWUSR);
 	if(fd)
	{
		write(fd,content,strlen(content));
		close(fd);
	}else
	{
		exit(0);
	}
	fd=open("un.txt",O_RDONLY);
	len=read(fd,str,LENGTH);
	printf("%s\n",str);
	close(fd);
	return 0;
}
 使用 gcc -Wall hello.c -o un 编译即可 运行 ./un

  上面使用open以所有者可读可写的权限来操作un.txt文件  使用write写完数据后 关闭文件描述符


第二种方式:C语言的库函数

  

#include <stdio.h>

#define  LENGTH 100


int main()
{
	FILE *fd;
	char str[LENGTH];
	char *content="undergrowth";
	fd=fopen("un.txt","w+");
	if(fd)
	{
		fputs(content,fd);
		fclose(fd);
	}

	fd=fopen("un.txt","r");
	fgets(str,LENGTH,fd);
	printf("%s\n",str);
	fclose(fd);
	return 0;
}

   使用 gcc -Wall hello.c -o un 编译即可 运行 ./un

上面使用fopen以读写的方式打开un.txt,如果不存在,则进行创建,然后使用fputs向磁盘文件中写入数据,之后在使用fgets从磁盘文件中获取LENGTH长度的字符放入str字符数组中


  接下来介绍tty设备文件

   磁盘文件与设备文件有很多相似的地方,比如都有文件的属性、文件的大小、文件的修改时间、文件的节点等等之类的,都可用系统的库函数与C语言的库函数来进行open、read、write、close、ioctl来进行操作。

  那么内核如何区分文件时磁盘文件还是设备文件呢?

    这里就要看磁盘文件和设备文件共有的一个属性即文件节点,当内核要准备为文件读数据时,首先会看文件的文件节点属性,如果文件节点对应的是磁盘文件的话,则直接根据文件系统的映射表读取数据,如果是设备文件的话,则会调用设备文件的驱动程序的read方法进行读取.

  磁盘文件在进行读写的时候是有缓冲区的,而设备文件是没有缓冲区的.

  而对于tty设备文件,我们可以通过tcgetattr、tcsetattr来对其驱动程序的属性进行读取和重新设置,从而影响其正常的工作.

下面是一个显示tty驱动设备的属性的小程序,只显示了几个比较重要的属性,更多的可以使用man tcgetattr来进行查看

#include <stdio.h>
#include <termios.h>
#include <stdlib.h>


#define eops(s,x) {perror(s); exit(x);}

int main()
{
	struct termios ttyinfo;
	void showbaud(int);
	void show_someflag(struct termios *);
	if((tcgetattr(0,&ttyinfo))==-1) eops("tcgetattr",1); //获取到当前终端的设置信息保存在ttyinfo结构体中
	showbaud(cfgetospeed(&ttyinfo)); //显示输出波特率
	printf("the erase charcter is ascii %d,Ctrl-%c\n",ttyinfo.c_cc[VERASE],ttyinfo.c_cc[VERASE]);
	show_someflag(&ttyinfo); //显示当前终端的一些设置信息
	return 0;
}


void showbaud(int speed)
{
	printf("the baud rate is %d .\n",speed);
}

struct flaginfo { //用于保存属性名及其描述
	int fl_value;
	char *fl_desc;
};

struct flaginfo input_flag[]={  //构建输入属性
	{IGNBRK,"ignore break condition"},
	{INLCR,"map nl to cr on input"},
	{IXOFF,"enable start/stop input control"},
	{0,NULL}
};


struct flaginfo output_flag[]={ //构建输出属性
	{OLCUC,"map lowercase character to uppercase character on output"},
	{0,NULL}
};

struct flaginfo local_flag[]={//构建本地属性
	{ECHO,"echo input character"},
	{ISIG,"when any on character intr,quit,susp or dsusp are received,generate the corresponing the signal"},	
	{0,NULL}
};

struct flaginfo control_flag[]={//构建控制属性
	{CREAD,"enalbe receiver"},
	{CRTSCTS,"enable rts/cts flow control"},
	{0,NULL}
};



void show_flagset(int thevalue,struct flaginfo fi[]) 
{
	int i;
	for(i=0;fi[i].fl_value;i++)
		{
			printf(" %s is ",fi[i].fl_desc);
			if(fi[i].fl_value&thevalue) printf("on.\n");  //判断该属性是否已经打开
			else printf("off.\n");
		}
}

void show_someflag(struct termios *termios_p) 
{
	printf("display some flag as follow:\n");
	show_flagset(termios_p->c_iflag,input_flag);
	show_flagset(termios_p->c_oflag,output_flag);
	show_flagset(termios_p->c_lflag,local_flag);
	show_flagset(termios_p->c_cflag,control_flag);
}


  还有一个是两个终端进行相互通信

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>


//#define BUFSIZ 30

int main(int argc,char *argv[])
{
	int fd;
	char buf[BUFSIZ];
	if(argc!=2)
	{
		perror("usage:write ttyname.\n");
		exit(1);
	}
	fd=open(argv[1],O_WRONLY); //获取另外一个终端的名字
	if(fd==-1)
		{
		 perror(argv[1]);
		exit(1);
		}
	while(fgets(buf,BUFSIZ,stdin)!=NULL)//从当前终端获取信息
	{
	if(write(fd,buf,strlen(buf))==-1) break; //将信息写入到另外一个终端
	}
	close(fd);
	return 0;
}


posted on 2013-09-04 16:11  liangxinzhi  阅读(784)  评论(0编辑  收藏  举报