目录
序言
一、基本概念
由于Linux系统下“一切皆文件”,也就是Linux系统下的数据和程序都是以文件的形式存储的,所以Linux内核会提供一组操作文件的函数接口,这组函数接口也被称为系统IO。
二、系统IO和标准IO的区别
标准I/O可以看成是在系统I/O的基础上封装了缓冲机制。这样可以先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数,提高访问效率。
三、文件描述符
文件描述符本质就是一个非负整数,从内核源码角度分析,这个整数实际上是内核中的一个称为fd_array 的数组下标。
打开文件时,内核产生一个指向 file{} 的指针,并将该指针放入一个位于 file_struct{} 中的数组 fd_array[] 中,而该指针所在数组的下标,就被 open() 返回给用户,所以内核把这个数组下标称为文件描述符。
文件描述符从0开始分配,每打开一个文件,就产生一个新的文件描述符。当然,用户可以重复打开同一个文件,每次打开文件都会使内核产生新的结构体,并得到不同的文件描述符。系统在每个进程开始运行时,都默认打开了一次键盘、两次屏幕,因此0、1、2描述符分别代表标准输入(stdin)、标准输出(stdout)和标准出错(stderr)三个文件(两个硬件)

Linux常用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_APPEND 把文件的读写位置调整到文件末尾(追加模式)
O_TRUNC 如果文件已存在并且是以写入模式打开的,则截断文件为零长度
O_ASYNC 设置信号驱动
O_CREAT 如果文件不存在则自动创建文件 (当需要创建文件时,第三个参数启动mode )
O_EXCL 和O_CREAT一块使用,如果文件存在则报错
O_NONBLOCK 使用非阻塞模式
@ mode : 指定文件权限(只有在open函数的第二个参数flags使用 O_CREAT 或者 O_TMPFILE 才会使用)
返回值:
成功 返回文件的描述符(一个非负整数 文件描述符从最低数字0开始分配,从小到大)
失败 返回-1 并设置错误码(通过perror可得到具体的错误原因)
备注: 注意:mode参数应该采用八进制。
-
Linux系统下的文件权限
二、关闭文件 close
功能:关闭文件
头文件:
#include <unistd.h>
函数原型:
int close(int fd);
参数分析:
@ fd : 要关闭的文件描述符
返回值:
成功 返回0
失败 返回-1 并设置错误码(通过perror可得到具体的错误原因)
备注: 无
三、文件读取 read
功能:从fd对应的文件中读取最多count个字节的数据并存储到buf指向的缓冲区中
头文件:
#include <unistd.h>
函数原型:
ssize_t read(int fd, void * buf, size_t count);
参数分析:
@ fd : 指定要读取数据的文件描述符
@ buf : 自定义缓冲区
@ count : 要读取的数据的个数(以字节为单位)
返回值:
成功 返回读取的字节数量 (如果返回值是0,说明读取到文件末尾)
失败 返回-1 并设置错误码(通过perror可得到具体的错误原因)
备注: 无
四、文件写入 write
功能:文件写入
头文件:
#include <unistd.h>
函数原型:
ssize_t write(int fd, const void * buf, size_t count);
参数分析:
@ fd : 指定要写入数据的文件描述符
@ buf : 自定义缓冲区
@ count : 要写入的数据的个数(以字节为单位)
返回值:
成功 返回写入的字节数量 (如果返回值是0表示写入0个数据)
失败 返回-1 并设置错误码(通过perror可得到具体的错误原因)
备注: 无
五、位置偏移 lseek
功能:设置文件的位置指示器的偏移量
头文件:
#include <sys/types.h>
#include <unistd.h>
函数原型:
int lseek(int fd, off_t offset, int whence);
参数分析:
@ fd : 需要设置位置偏移量的文件描述符
@ offset : 新位置偏移量相对基准点的偏移
@ whence : 基准点 :
SEEK_SET -->文件开头处
SEEK_CUR -->当前位置
SEEK_END -->文件末尾处
返回值:
成功 返回文件指示器相较于文件开头的偏移量(以字节为单位)
失败 返回-1 并设置错误码(通过perror可得到具体的错误原因)
备注: 无
六、文件控制 ioctl
功能:文件控制 (一个专用于设备输入输出操作的系统调用,该调用传入一个跟设备有关的请求码,系统调用的功能完全取决于请求码)
头文件:
#include <sys/ioctl.h>
函数原型:
int ioctl(int fd, unsigened long request, ...);
参数分析:
@ fd : 要控制的文件描述符
@ request : 和具体硬件相关的请求码,针对不同文件的各种控制命令字
@ argp : 一个指针,指针类型由请求码决定
返回值:
成功 返回0
失败 返回-1 并设置错误码(通过perror可得到具体的错误原因)
备注: 请求码是通过宏定义的方式写入到硬件的驱动程序中,当驱动安装成功后,用户就可以通过头文件中的请求码向内核中的驱动程序发出请求,然后内核通过请求码去访问硬件,再把访问结果返回给用户。
思维碎片与问题集
练习:利用open函数测试默认情况下程序最多可以打开多少个文件。提示:同一个文件可以被多次打开。
思考:使用 ulimit命令可以知道一个程序中能打开的文件的数量最大为1024个,使用ulimit -n可以修改这个值。