文章目录
- 文件系统调用接口
- open
- 系统调用接口和C语言封装
- 文件描述符fd
- 重定向
文件系统调用接口
open
NAME
//打开、创建 - 打开并可能创建文件或设备
open, creat - open and possibly create a file or device
SYNOPSIS
#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);
给定一个文件路径,open返回一个文件描述符,一个小的非负整数,用于后续的系统调用。成功调用返回的文件描述符将是当前未为进程打开的编号最低的文件描述符。
flags
参数标志必须包括以下访问结点之一:O_RDONLY、O_WRONLY、O_RDWR.着三种方式分别表示只读、只读或读/写文件。
- O_APPEND
文件以追加的模式打开。每次写入之前,文件偏移量位于文件的末尾。 - O_CREAT
如果文件不存在,则创建它。将文件的所有者,设置为进程的有效用户ID。组所属者设置为进程的有效组ID,也可以设置为父目录的组ID。 - mode参数,模式指定在创建新文件时要使用的权限。当在flags中指定使用O_CREAT时,必须提供此参数,如果未使用O_CREAT,则忽略mode。
有效的权限由进程的umask按照通常的方式修改。
系统调用接口和C语言封装
- 以写的方式打开,如果文件不存在则创建
fopen("log1.txt",w);
open("log1.txt", O_WRONLY|O_CREAT|O_TRUNC,0666)
- 以追加的方式打开,如果文件不存在则创建
fopen("log1.txt",a);
open("log1.txt",O_WRONLY|O_APPEND|O_CREAT,0666);
库函数:类似fopen
、fclose
、fwrite
、fread
都是C标准库中的函数,库函数
系统调用接口:类似open
、close
、write
、read
都属于系统提供的接口,系统调用接口
C语言库函数中的f*
系列的函数,都是对系统调用的二次封装,方便二次开发。
在操作系统提供了类似open这种调用接口的情况下,C语言仍然对其进行了封装,主要原因是为了保证程序的可移植性和跨平台性。
文件描述符fd
- Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0,标准输出1,标准错误2.
- 0、1、2对应的物理设备一般是:键盘、显示器、显示器
每个打开文件,在内核当中都有file对象那个,保存了文件相关的inode元信息。
文件描述符的本质就是数组的下标。
文件描述符就是从0开始的小整数。
当我们打开文件时操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体,表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files
,指向一张表file_struct,该表最重要的部分就是包含一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的小标。所以,只要拿着文件描述符,就可以找到对应的文件。
文件描述符分配规则
在files_struct数组当中,找到当前没有被使用的最小的一个下标,做为新打开的文件描述符。
重定向
Linux下一切皆文件
对于每一种硬件,操作系统都有对应的系统调用接口
close(1);
const char* buffer = "hello open";
int fd2 = open("log2.txt",O_WRONLY|O_APPEND|O_CREAT,0666);
printf("hello open\n");
上段代码,在执行之后,预期是在显示器上输出hello open
,但是实际上不是。
在实际的运行之后,本应该打印在显示器上的数据,却写入到了log2.txt
文件中。
现象解释:
- 当程序执行close(1)之后,文件描述符数组中的1号下标位置,本应指向的stdout文件(标准输出文件)被关闭,此时文件描述符数组中下标最小的是1号下标。
- 执行到open语句的时候,需要打开当前目录下的
log2.txt
文件,但是不存在,所以此时创建一个新的文件,这个新的文件,在files_struct数组当中,找到当前没有被使用的最小的一个下标,做为新打开的文件描述符。所以此时log2.txt
文件的fd就是1. - 对于printf函数,此函数默认将数据写入到stdout标准输出流文件中,也就是文件描述符的1号下标处。但是此时1号下标已经指向了新打开的文件,所以数据写入到了
log2.txt
文件中。