Linux IO系统
标准库 和 系统调用
标准库
遵守ISO标准,基于流的IO,对文件指针进行操作
系统调用
兼容POSIX标准,基于文件描述符操作
标准库 IO 操作
特性
FILE 结构体,包含文件描述符
带缓存功能
stderr 无缓存,更快看到错误
常用api 以及 示例代码
1、fopen
FILE *fopen(const char *path, const char *mode);
2、fclose 关闭文件
文件一旦使用完毕,应该用 fclose() 函数把文件关闭,以释放相关资源,避免数据丢失。
int fclose(FILE *fp);
3、fgetc 与 fputc(以字符形式读写文件)
int fgetc (FILE *fp);
fp 为文件指针。fgetc() 读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回
EOF
。EOF 是 end of file 的缩写,表示文件末尾,是在 stdio.h 中定义的宏,它的值是一个负数,往往是 -1。fgetc() 的返回值类型之所以为 int,就是为了容纳这个负数(char不能是负数)。
EOF 不绝对是 -1,也可以是其他负数,这要看编译器的实现。
int fputc ( int ch, FILE *fp );
ch 为要写入的字符,fp 为文件指针。fputc() 写入成功时返回写入的字符,失败时返回 EOF,返回值类型为 int 也是为了容纳这个负数。
4、fgets / fputs(以字符串形式读写文件)
5、fread/fwrite(以数据块的形式读写文件)
6、fprintf/fscanf(格式化读写文件)
7、rewind/fseek(随机读写文件)
8、ftell(获取文件大小)
系统调用 IO 操作
特性
内核提供的系统调用,不带缓存
基于文件描述符,非负整数
errno
errno 错误编码,分析这个错误,strerror(error)
或者直接使用perror(“open error”);,它会调用strerror,对错误码进行解释
perror定义在stdio.h中,如果程序中要使用errno,需要包含errno.h
常用api 以及 示例代码
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);
参数:
pathname: 要打开或者创建的文件路径
flags: 分为两类:主类 和 副类
主类:
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
副类:
O_CREAT 如果文件不存在则创建该文件
O_EXCL 如果使用O_CREAT选项且文件存在,则返回错误消息
O_TRUNC 如果文件已经存在则截断文件内容
O_APPEND 以追加的方式打开
O_NONBLOCK 非阻塞方式打开
mode:新建文件的访问权限,对于open函数而言,仅当创建新文件时才使用第三个参数
返回值:
成功返回文件描述符
失败返回-1
示例代码:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "usage: %s newfile\n", argv[0]);
exit(1);
}
int fd = open(argv[1], O_RDONLY | O_CREAT | O_TRUNC, 0644);
// int fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0777); // 创建文件权限 ~umask & mode
// int fd = open(argv[1], O_RDONLY | O_CREAT | O_EXCL); //当O_EXCL 与 O_CREAT同事使用时,如果文件存在open失败
if (fd < 0) {
perror("open error");
exit(1);
}
printf("fd = %d\n", fd);
close(fd);
return 0;
}
creat
使用creat函数创建一个新文件,如果原来该文件存在,会将这个文件的长度截短为0。函数定义如下:
#include <fcntl.h>
int creat(const char *pathname, mode_t mode);
如果成功则返回为只写打开的文件描述符,出错则返回-1。
等价于open函数的O_WRONLY|O_CREAT|O_TRUNC
close
这里要注意下,open函数定义在fcntl.h文件中,和close不一样。
#include <unistd.h>
int close(int filedes);
read
ssize_t 实际是无符号的整数类型。
返回实际读到的字节数,> 0表示成功
网路中读取,有可能传输的文件很大,可能需要读好多次
write
lseek
文件的"读"、"写"使用同一偏移位置。
应用场景:
- 求文件大小
- 扩展文件大小(lssek, 10, SEEK_END) + IO操作
高级部分
设置非阻塞模式
-
open方式打开,设置O_NONBLOCK标志
-
如果文件已经打开,通过fcntl设置
int flag = fcntnl(fd, F_GETFL);
flag |= O_NONBLOCK;
fcntl(fd, F_SETFL, flag);
dup 和 dup2函数
#include <unistd.h>
int dup(int oldfd); 复制文件描述符
int dup2(int oldfd, int newfd); 复制文件描述符 ; 重定向
返回:成功返回新文件描述符,出错返回-1
功能:文件描述符的复制(其实是复制指针),如果newfd已经打开,会先进行关闭
在进程间通信时可用来改变进程的标准输入和标准输出设备
文件权限
access函数 判断文件是否存在、可读、可写、可执行
umask
chmod
fchmod 对已经打开的文件进行操作
文件结构
目录项 i节点 数据块