Linux标准I/O

linux-开发与管理 P9 标准I/O

在这里插入图片描述

系统调用

在这里插入图片描述

什么是系统调用?

用户程序操作系统提出请求的接口称为系统调用

所有的操作系统都会提供系统调用接口,只不过不同的操作系统提供的系统调用接口各不相同。

在这里插入图片描述

为什么要进行系统调用?

为了更好地服务于应用程序,因为操作系统负责管理和分配所有的计算机资源,所以操作系统提供了一组特殊的接口,通过这组接口,用户程序可以使用操作系统内核提供的各种功能,如分配内存创建进程实现进程之间的通信等。

为什么不直接访问计算机资源?

因为直接访问内存等资源是不安全的,当嵌入式系统有了操作系统之后,操作系统基本上都支持多任务,即同时可以运行多个程序,如果允许程序直接访问系统资源,肯定会带来很多问题;因此所有的软硬件资源的管理和分配都由操作系统负责,程序要获取资源必须通过操作系统来完成,即用户程序向操作系统发出服务请求,操作系统收到请求后执行相关的代码来处理。

系统调用了系统的哪些功能?

系统调用按照功能大致可分为进程控制进程间通信文件系统控制存储管理网络管理套接字控制用户管理等。

用户程序编程接口(API)

在这里插入图片描述

什么是API?

API就是用户程序编程接口,通俗的解释就是各种库中的函数;
为了提高开发效率,C库中实现了很多函数,这些函数实现了常用的的功能,供调用所用;
API在实现时,通常都要依赖系统调用接口,很多API函数需要通过多个系统调用来完成其功能,还有一些API函数不需要调用任何系统调用。

API的优势

系统调用可以访问各种资源,但实际开发中程序并不直接使用系统调用接口,而是使用用户程序编程接口(API)

优点

  1. 系统调用口功能非常简单,无法满足程序的要求

  2. 不同操作系统的系统调用接口不兼容,程序移植时工作量大

  3. 而API程序具有良好的可移植性,几乎所有的操作系统上都实现了C库,所以程序通常只需要重新编译一下就可以在其他操作系统上运行。

POSIX标准

POSIX是用户程序编程接口(API)遵循了UNIX中最流行的应用编辑界面标准

POSIX标准是由IEEE和ISO/IEC共同开发的标准系统,该标准基于当时的UNIX实践和经验,描述了操作系统的系统调用编程接口,用于保证应用程序可以在源代码一级上在多种操作系统上移植运行,具有更好的可移植性。

标准I/O概述

在这里插入图片描述

什么是标准I/O?

ANSI C中定义的用于I/O操作的一系列函数称为标准I/O

具有更好的可移植性,只要操作系统中安装了C库,标准I/O函数就可以调用,源代码不需要修改就可以在其他操作系统下编译运行。

标准I/O文件类型
常规文件 r
目录文件 d
字符设备文件 c
块设备文件 b
管道文件 p
套接字文件 s
符号链接文件 l

流(stream)

当用标准I/O打开一个文件时,就会创建一个FILE结构体描述文件,把这个创建的FILE结构体称为(stream),标准I/O都是基于流进行操作的。

流的缓冲类型

全缓冲:当填满标准I/O缓冲区后才进行实际I/O操作;标准I/O打开时是默认为全缓冲的,当缓冲区已满或执行flush操作时才会进行磁盘操作。
行缓冲:当在输入或输出中遇到换行符时执行I/O操作。
无缓冲:不对I/O操作进行缓冲,即在对流的读写时会立刻操作实际的文件。

文件与流的对比

文件:用一个结构体类型来存放打开的文件的相关信息
:文本流/二进制流

标准I/O预定义的三个流

流名称编号函数名表示
标准输入流0STDIN_FILENOstdin
标准输出流1STDOUT_FILENOstdout
标准错误流2STDERR_FILENOstderr

标准I/O编程

在这里插入图片描述

流的打开与关闭

流的打开(fopen())

所需头文件#include <stdio.h>
函数原型FILE fopen(const char path,const char* mode)
函数参数path:包含要打开的文件路径及文件名
mode:文件打开方式
函数返回值成功:指向FILE的文件
失败:NULL

Mode的取值说明

r或rb打开只读文件,该文件必须存在
r+或r+b打开可读写的文件,该文件必须存在
w+或wb打开只写文件,若文件存在则文件长度为0;若文件不存在则建立该文件(原先的内容不保留)
W+或w+b打开可读写文件,若文件存在则文件长度为0;若文件不存在则建立该文件(原先的内容不保留)
a或ab以附加的方式打开只写文件。若文件不存在,则会建立该文件;若果文件存在,写入的数据会被加到文件尾(原先的内容保留)
a+或a+b以附加方式打开可读写的文件。若文件不存在,则会建立该文件;如果文件存在,写入的数据会被加到文件尾(原先内容保留)

文件权限

fopen()创建的文件访问权限是0666(rw-rw-rw-)

Linux系统中umask设定会影响文件的访问权限,其规则为(0666&~umask)

Root用户是022,普通用户是002

用户可以通过umask函数或者命令修改相关设定

举个栗子

在这里插入图片描述

#include <stdio.h>

int main(int argc, const char *argv[])
{
	FILE *fp;
	if((fp = fopen("test.txt","r+")) == NULL){
		printf("fopen error\n");
		return -1;
	}
	return 0;
}

在这里插入图片描述

流的关闭(fclose())

所需头文件#include <stdio.h>
函数原型Int fclose(FILE *stream);
函数参数Stream:已打开的流指针
函数返回值成功:0
失败:EOF

举个栗子

在这里插入图片描述

#include <stdio.h>

int main(int argc, const char *argv[])
{
	FILE *fp;
	fp = fopen("file.txt","w");

	fprintf(fp,"%s","hello cage!");
	fclose(fp);
	
	return 0;
}

在这里插入图片描述

流的读写

字符输入

所需头文件#include <stdio.h>
函数原型int getc(FILE *stream) ;
int fgetc(FILE *stream);
int getchar(void);
函数参数Stream:要输入的文件流
函数返回值成功:读取的字符
失败:EOF

字符输出

所需头文件#include <stdio.h>
函数原型int putc(int c,FILE * stream);
int fputc(int c,FILE *stream);
int putchar(int c);
函数参数Stream:要输入的文件流
函数返回值成功:输出的字符
失败:EOF

举个栗子

在这里插入图片描述

#include <stdio.h>

int main(int argc, const char *argv[])
{
	FILE *fp;
	int ch;

	fp = fopen("file.txt","w");
	for(ch = 1;ch <= 50;ch++){
		fputc(ch,fp);
	}
	fclose(fp);

	return 0;
}

在这里插入图片描述

#include <stdio.h>

int main(int argc, const char *argv[])
{
	FILE *fp;
	int c;

	fp = fopen("file.txt","r");
	while(1){
		c = fgetc(fp);
		if(feof(fp)){
			break;
		}
		printf("%c",c);
	}
	fclose(fp);
	return 0;
}

在这里插入图片描述

feof(测定流结束标识符)

检测当前文件是否检测到了结束的标识符

所需头文件#include <stdio.h>
函数原型int feof(FILE *stream)
函数参数Stream:要输入的文件流
函数返回值成功:输出的字符
失败:EOF

按行输入

所需头文件#include <stdio.h>
函数原型Char * gets(char *s);
Char * fgets(char *s,int size,FILE * stream);
函数参数S:存放输入字符串的缓冲区首地址
Size:输入的字符串长度
Stream:对应的流
函数返回值成功:返回s
失败:NULL

按行输出

所需头文件#include <stdio.h>
函数原型Int puts(const char *s);
Int fputs(const char *s,FILE * stream);
函数参数S:存放输出字符串的缓冲区首地址
Stream:对应的流
函数返回值成功:s
失败: NULL

单位大小读文件

所需头文件#include <stdio.h>
函数原型Size_t fread(void * ptr,size_t size,size_t nmemb,FILE *stream);
函数参数Ptr:存放读入记录的缓冲区
Size:读取的每个记录的大小
Nmemb:读取的记录数
Stream:要读取的文件流
函数返回值成功:返回实际读取到的nmemb数目
失败:EOF

单位大小写文件

所需头文件#include <stdio.h>
函数原型Size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE *stream m);
函数参数Ptr:存放写入记录的缓冲区
Size:写入的每个记录的大小
Nmemb:写入的记录数
Stream:要写入的文件流
函数返回值成功:返回实际写入的nmemb数目
失败:EOF

举个栗子
在这里插入图片描述

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

int main(int argc, const char *argv[])
{
	FILE *fp;
	char c[] = "fread and fwrite test";
	char buf[20];

	fp = fopen("file.txt","w+");
	fwrite(c,strlen(c)+1,1,fp);
	fseek(fp,0,SEEK_SET);

	fread(buf,strlen(c)+1,1,fp);
	printf("%s\n",buf);
	fclose(fp);

	return 0;
}

在这里插入图片描述

fseek查找文件的开头


格式化输入

所需头文件#include <stdio.h>
函数原型Int scanf(const char *format,…);
Int fscanf(FILE *fp,const char *format,…);
Int sscanf(char *buf,const char *format,…);
函数参数Format:输入的格式
Fp:作为输入的流
Buf:作为输入的缓冲区
函数返回值成功:输出字符数
失败:EOF

格式化输出

所需头文件#include <stdio.h>
函数原型Int printf(const char *format,…);
Int fprintf(FILE *fp,const char *format,…);
Int sprintf(char *buf,const char *format,…);
函数参数Format:输出的格式
Fp:作为输出的流
Buf:作为输出的缓冲区
函数返回值成功:输出字符数
失败:EOF

错误处理

标准I/O函数执行时如果出现错误,会把错误码保存在全局变量errno中,可以通过相应的函数将错误打印出来。

perror函数

所需头文件#include <stdio.h>
函数原型Void perror*(const char *s);
函数参数S:在标准错误流上输出的信息
函数返回值

strerror函数

所需头文件#include <stdio.h>
#include <errno.h>
函数原型Void *strerror(int errnum);
函数参数错误码
函数返回值错误码对应的错误信息

举个栗子
在这里插入图片描述

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

extern int errno;

int main(int argc, const char *argv[])
{
	FILE *pf;
	int errnum;
	pf = fopen("file.txt","rb");
	if(pf == NULL){
		errnum = errno;
		fprintf(stderr,"错误号:%d\n",errno);
		perror("通过perror输出错误");
		fprintf(stderr,"打开文件错误:%s\n",strerror( errnum ));
	}else{
		fclose(pf);
	}
	return 0;
}

在这里插入图片描述

流的定位

每个打开的流内部都有一个当前读写位置,流在打开时,当前读写位置为0,表示文件的开始位置。每读写一次后,当前读写位置自动增加实际读写的大小。在读写之间可先对流进行定位,即移动到指定的位置再操作。

移动到指定位置

所需头文件#include <stdio.h>
函数原型Int fseek(FILE * stream,long offset,int whence);
函数参数Stream:要定位的文件流
Offset:相对于基准值的偏移量
Whence:基准值 SEEK_SET:代表文件的起始位置 SEEK_END:代表文件结束位置 SEEK_CUR:代表文件当前读写位置
函数返回值成功:0
失败:EOF

获取当前的定位

所需头文件#include <stdio.h>
函数原型Long ftell(FILE * stream);
函数参数Stream:要定位的文件流
函数返回值成功:返回当前的读写位置
失败:EOF

举个栗子
在这里插入图片描述

#include <stdio.h>

int main(int argc, const char *argv[])
{
	FILE *fp;
	fp = fopen("file.txt","w+");
	fputs("fseek just test now",fp);

	fseek(fp,6,SEEK_SET);
	fputs("C is Programming Langauge",fp);
	fclose(fp);

	return 0;
}

在这里插入图片描述

更多内容

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CagePan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值