系统调用
IO
,是系统调用函数,不再是库函数的一部分,而是系统的一部分
文件IO
,每次都是直接操作具体的文件,
没有用户读写缓冲区
标准IO与文件IO的区别
标准
IO:
有缓冲区,提高效率 ,尽量减少内核read/write
操作文件的次数
文件
IO
: 每次read/write
都要调用内核的文件操作的系统调用
1、open() ---打开文件
#include <sys/types.h> //头文件
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
参数:
参数1:const char *pathname//:字符地址,字符串首地址,表示要打开文件的文件名
参数2:int flags//:整型,表示打开文件的权限,在整数每一位都是固定了一个权限,有这一位 就为1,没有就为0
可填写的参数有必须与选择
必须(三选一):
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:读写打开
选择可以为0,或者为多个
O_TRUNC:如果文件存在,则在打开文件时把文件清空
O_APPEND:以追加的方式打开,所有写操作都在文件的末尾执行
O_NOCTTY:如果是终端,就是操作终端文件
O_CREAT:如果文件不存在,则创建文件,文件存在就没有任何作用
O_EXCL:如果文件不存在,就创建文件,如果文件存在就报错(和O_CREAT)
当有 O_CREAT参数时,则需要第三个参数,mode_t mode,如下所示
int open(const char *pathname, int flags, mode_t mode);
参数3:mode_t mode:创建文件的权限
实际权限: (mode & ~umask)
umask:文件权限掩码,为了防止普通用户设置的文件权限过高
返回值: int
成功:返回打开的文件的文件描述符(打开的文件)
失败:返回-1,且设置错误码
文件描述符
只要内核打开了文件,就向程序返回一个文件描述符-----标识文件
一般都是从3开始:
因为默认会打开3个文件:
标准输入文件:0
标准输出文件:1
标准错误输出文件:2
2、read() --- 读操作(从文件中读取指定大小字节的数据,输入到程序)
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
参数:
参数1:int fd//:整型,文件描述符,表示从哪个打开的文件中读取数据
参数2:void *buf//:指针,地址,读取的数据存储到程序的哪个内存地址(必须要有空间)
参数3:size_t count//:整型,从文件中读取多少个字节
返回值:int
成功:返回读取成功的字节数 0:读取到文件末尾,没有数据可读
失败:返回 -1, 且设置错误码
3、write() --- 写操作
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
参数:
参数1:int fd//:文件描述符,写入到哪个文件中
参数2:const void *buf//:指针,内存地址,要写入文件的内容的地址,把哪个地址的内容写入 文件
参数3:size_t count//:写入多少个字节
返回值:int
成功:返回写入的字节数
失败:返回-1,且设置错误码
4、close() --- 关闭文件
int close(int fd);
参数:
参数1:int fd:文件描述符,关闭打开的文件
返回值:
成功:返回0
失败:返回-1
5、lseek() --- 文件读写偏移量(修改文件当前操作位置)
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
参数:
参数1:int fd//:打开的文件,文件描述符,表示要偏移移动哪个文件的当前操作位置
参数2:off_t offset//:偏移多少个字节
< 0 :向前偏移
> 0 :向后偏移
= 0 :偏移0个字节
参数3:int whence//:偏移的基准位置
SEEK_SET:从文件开始位置
SEEK_CUR:文件当前操作位置 S
EEK_END:文件结束位置
返回值:
成功:从文件开始到偏移之后的位置,相隔多少个字节
失败:-1.且设置错误码
空洞文件(既申请了大小但里面什么没有全部为0)
文件位置偏移,偏移出文件大小,在文件大小以外的位置进行操作(写),中间空洞位置全为0