波奇学Linux: 文件描述符

文件和操作系统的关系

操作系统控制进程,文件的打开是在进程中进行。意味着用来控制进程的PCB必然有文件的信息,操作系统通过控制PCB的信息来控制文件的读写。

波奇学Linux: 文件描述符_第1张图片

Q1:如何证明文件打开是在进程中进行?

波奇学Linux: 文件描述符_第2张图片

编写c文件调用fopen来操作文件,c文件会被编译成可执行程序执行,即进程,实现进程中对文件操作。

C的文件操作和系统调用

文件调用必须通过系统调用

fopen,fclosed等库函数是用户接口,从硬盘读取文件时,对硬件操作时,必须调用操作系统的函数底层

波奇学Linux: 文件描述符_第3张图片

文件操作库函数和底层函数的关系 

c文件操作库函数主要有fopen,fclose等

其中fopen第一个参数是文件名,第二个参数是打开模式

r:只读

r+:可读可写

w:只写,清空再写

w+:可读可写,清空再写,文件不存在创建

a:只写,追加写

a+:可读可读写,追加写

系统调用则用open函数 

波奇学Linux: 文件描述符_第4张图片

波奇学Linux: 文件描述符_第5张图片 

其中 open函数中的 flags参数表示选项, mode表示文件权限

flags参数表示文件操作读,写,可读可写,参数是宏

#include
#include
#include
#include
int main()
{
//设置掩码为0
umask(0);
//创建只写文件,如果文件不存在时创建,新文件掩码是0666
int fd=open("log.txt",O_CREAT|O_WRONLY,0666); 
// 关闭文件
fclose(fd);
return 0;
}

因此我们可以推断 fopen的w+模式 必然是对open的封装,且对应的宏参数为O_WRONLY|O_CREAT|O_TRUNC

而不同的模式对应不同的宏参数组合。

宏参数控制的方法叫做比特位控制法

#define ONE (1<<0)
#define TWO (1<<1)
#define THREE (1<<2)
#define FOUR (1<<3)
void show(int flags)
{
if (flags&ONE) printf("hello function1");
if (flags&TWO) printf("hello function2");
if (flags&THREE) printf("hello function3");
if (flag&FOUR) printf("hello function4");
}
int main()
{
show(ONE);
ShoW(TWO);
show(ONE|THREE); // function3 和function1都打印
return 0;
}

 文件调用本质

在task_struct的指针中有files_struct的指针

波奇学Linux: 文件描述符_第6张图片

files_struct结构体含有一个数组,数组中有file*指针,数组的下标就是fd,open的返回值file descriptor。

fd为1和为2都指向显示器文件,用引用计数解决这个问题。

file指针管理着文件,包含基本信息

波奇学Linux: 文件描述符_第7张图片

关闭文件就是引用计数减一,同时释放file结构体

在Linux下一切皆文件

fd=0 stdin流,对应键盘文件

fd=1 stdout流 对应显示器文件

fd=2 stderr 显示器文件

向fd为1的文件,即向显示器输出hello Linux。

C语言的FILE* 必然会封装fd

同理库函数的printf等调用fd为1的文件。

你可能感兴趣的:(Linux,c++)