Linux(高级编程)4————基础IO

什么是IO?
I/O即对输入输出设备的操作,在Linux中一切硬件设备都被当做文件来管理,输入/输出也不例外,这所谓Linux下一切皆文件思想,通过对输入输出设备的操作即为IO。
回顾C语言中的IO操作:
在C语言中我们一IO流的方式进行对文件读写。

  • C语言默认会打开三个输入输出流:stdin(标准输入流)、stdout(标准输出流)、stderr(标准出错)。
  • 这三个流的类型都为file*类型,fopen返回值类型,文件指针。

下面是C语言实际操作文件的实例:
w_hello.c(往文件hello.txt中写hello fwrite):

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

int main(void)
{
	FILE* fin = fopen("hello.txt","w");
	if(fin == NULL)
	{
		printf("fopen error!\n");
		exit(-1);
	}
	char buf[] = "hello fwrite!\n";
	int count = 5;
	while(count--)
		fwrite(buf,strlen(buf),1,fin);
	fclose(fin);
	return 0;
}

r_hello.c(读取刚才写入hello.txt中的字符串):

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

int main(void)
{
	FILE* fout = fopen("hello.txt","r");
	if(fout == NULL)
	{
		printf("fopen error!\n");
		exit(-1);	
	}
	char buf[1024];
	char* msg = "hello fwrite!\n";
	while(1)
	{
		size_t s = fread(buf,1,strlen(msg),fout);
		if(s > 0)
		{
			buf[s] = 0;
			printf("%s",buf);
		}
		if(feof(fout))
			break;
	}
	fclose(fout);
	return 0;
}

文件描述符:
通过回忆C语言下我们对文件的操作,那么学习系统编程,就得了解和学习一下Linux下的IO操作;在此之前我们回忆一下进程的内容,进程描述PCB有一个重要的内容:文件描述符表(即就是用来管理文件的)与IO操作有密切关系。来看一下关系图吧:
在这里插入图片描述
在task_struct(PCB)中有一个指向文件描述符标的指针,而它它里面有一个指针数组(file* fd_array[]),数组里面存放的是指向文件的指针,而这个数组的下标就是这片博客的重点操作对象(文件描述符)。

  • 文件描述符的实质:就是一个正整数。(在此之前我们了解了重定向应该对文件描述符早有所了解)。
  • 文件描述符分配规则:当我们调用系统接口open时(后面认识),会为我们所打开的文件分配一个文件描述符,系统会遍历文件描述符表找到一个空位分给当前文件。
    5个底层系统调用接口:
    • open打开文件接口:
 	   #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>
       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);
       int creat(const char *pathname, mode_t mode);

pathname文件路径
falgs打开方式
mode权限位(用于文件建立时,存在就不需要)。
flags常用的几个打开方式:
O_RDONLY:以只读的方式打开
O_WRONLY:以只写的方式打开
O_RDWR:以读写的方式打开
O_CREAT:当文件不存在时,创建该文件
O_APPEND:已追加的方式写

成功返回文件描述符,失败返回-1:

  • read&write读写文件接口:
	#include <unistd.h>
	ssize_t read(int fd, void *buf, size_t count);
	ssize_t write(int fd, const void *buf, size_t count);

fd:文件描述符
buf:缓冲区
count:期望读写的文件字节数。
成功返回读取或写入的字节数,失败返回:-1

  • close关闭文件接口:
int close(int fd);

成功返回:0;失败返回-1;

  • lseek用来移动文件指针的函数,可以通过文件来更改文件当前读写位置。
 off_t lseek(int fd, off_t offset, int whence);

offset参数:
偏移whence位置的字节数。
whence参数:
SEEK_SET:文件指针指向文件开始位置。
SEEK_CUR:文件指针指向文件当前位置。
SEEK_END:文件指针指向文件末尾。
open_read使用实例:

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

int main(void)
{
	//1.先打开文件
	int fd = open("hello.txt",O_RDONLY);
	if(fd<0)
	{
		perror("open error!\n");
		exit(-1);
	}
	//2.缓冲区
	char buf[1024];
	//3.读取文件到缓冲区
	int s = read(fd,buf,sizeof(buf)-1);
	buf[s] = 0;
	printf("%s\n",buf);
	close(fd);
	return 0;
}

open_write使用实例:

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

int main(void)
{
	//1.打开文件
	int fd = open("hello.txt",O_WRONLY);
	if(fd<0)
	{
		perror("open error!\n");
		exit(-1);
	}
	char* buf = "hello open_write!\n";
	//2.写入文件
	int s = write(fd,buf,strlen(buf));
	if(s>0)
		printf("write success!\n");
	close(fd);
	return 0;
}

我们目前文件hello.txt中已有数据,当我们想以追加的模式写数据时有两种方式,一种open打开文件时在flags参数中加上O_APPEND参数即可。那么上面我们还提到了lseek函数不防在下面用的试一下。
lseek函数使用实例:

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

int main(void)
{
	//1.打开文件
	int fd = open("hello.txt",O_WRONLY);
	if(fd<0)
	{
		perror("open error!\n");
		exit(-1);
	}
	char* buf = "hello lseek!\n";
	//2.更改当前文件指针位置
	lseek(fd,0,SEEK_END);
	//2.写入文件
	int s = write(fd,buf,strlen(buf));
	if(s>0)
		printf("write success!\n");
	close(fd);
	return 0;
}

运行结果:
在这里插入图片描述
可以看到我们把文件指针更改到文件末尾,这样效果就和O_APPEND追加模式一样了。
缓冲区概念:
由于内核和IO设备之间的交互是比较耗时,而且低效的,linux系统使用缓冲区来减少内核和IO之间的切换,以保证IO操作的高效。
缓冲区分为:
全缓冲:每次缓冲区写满了在回写内核,普通文件的读写就是全缓冲。
行缓冲:每次写满一行就回写到内核,当缓冲区写满了也会回写到内核,标准输入输出对应到终端就是行缓冲。如(printf)。
无缓冲:当用户每次通过系统调用写回内核时。如(write)。
fflush函数可以用来刷新缓冲
可以确保数据回写到内核,防止进程因为异常终止而丢失数据,作为一个特例,fflush(NULL)可以针对所有文件的IO操作的缓冲区进行FLUSH操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值