1.文件流指针和文件描述符的产生
fopen函数打开文件成功后会返回文件流指针,open函数打开文件成功后返回的是文件描述符.他俩的相同点是通过文件流指针和文件描述符都可以对文件进行操作.
2.fopen函数和open函数的介绍
fopen函数(库函数)
path:带有的路径的文件名,如果没有路径默认在当前文件下.
mode:
'r' 只读方式打开,将文件指针指向文件头,如果文件不存在,则返回空。
'r+' 读写方式打开,将文件指针指向文件头,如果文件不存在,则返回空。
'w' 写入方式打开,将文件指针指向文件头并将文件内容清空。如果文件不存在则创建。
'w+' 读写方式打开,将文件指针指向文件头并将文件内容清空。如果文件不存在则创建。
'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则创建。
'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则创建。
例如:FILE* fp = fopen("1.txt", "w+");
open函数(系统调用函数)
pathname:带有的路径的文件名,如果没有路径默认在当前文件下.
flags:打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数
:
O_RDONLY:
只读打开
O_WRONLY:
只写打开
O_RDWR :
读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT :
若文件不存在,则创建它。需要使用
mode
选项,来指明新文件的访问权限
O_APPEND:
追加写
返回值: 成功:新打开的文件描述符,失败返回-1
例如:int p=open("1.txt",
O_RDONLY|O_CREAT,0664);两个宏之间用
位图运算,0664是打开的文件的权限
3.文件描述符的介绍和怎么查看文件描述符
文件描述符是打开文件后返回的值,通过文件描述符可以操作文件,而每一个进程在运行时都会默认打开标准输入,标准输出,表述错误.这三个文件描述符.
打开一个文件然后进入死循环
int p=open("11.txt",O_RDWR | O_CREAT,0664);
if(p<0)
{
return 0;
}
while(1)
{
}
用pa aux | grep mytext查看进程号
ll .proc/进程号/fd 查看进程打开的文件描述符.
0:标准输入
1:标准输出
2:标准错误
3:程序里打开的文件的文件描述符
文件描述符就相当于文件的标记:标记的规则是最小数规则
在打开文件之前关闭标准输入文件,
0代表的文件被关闭,所以打开文件后1.txt文件的文件描述符就是0;
4.从内核角度理解文件流指针和文件描述符
文件描述符:
每一个进程在内核里都是一个struct task_struct结构体:
结构体里看到了我们熟悉的pid
这是一个struct files_struct指针(描述的是当前进程打开文件的信息)
这个结构体指针指向的struct files_struct类型的变量,变量里里有一个struct file_rcu*fd_array[NR_OPEN_DEFAULT],这个结构体指针数组里的数组下表就是文件描述符,数组当中的元素是指针类型,指向了文件,所以通过文件描述符,就可以找到对应的文件.
图文关系如下:
文件流指针:
FILE可以在stdio.h的头文件里使用说明这个指针在这个文件里存在.直接cd /usr/include
打开包含头文件的文件夹,vim stdio.h.就能看到这个头文件里有啥了...(.h文件里基本上都是声明)
第一个struct _IO_FILE是一个结构体的声明;
第二个是FILE指针是被重命名出来的,他的本来面目是struct _IO_FILE这个结构体
找到struct _IO_FILE结构体的办法:
在include文件下面进行搜索,grep struct _IO_FILE . -R(意思是在当前文件下进行递归搜索)
打开结构体定义对应的文件libio.h,找到结构体的定义:
char* _IO_read_ptr; /* Current read pointer */ 表示当前读到了哪个位置
char* _IO_read_end; /* End of get area. */ 表示当前读区域的末尾
char* _IO_read_base; /* Start of putback+get area. */ 表示读区域的起始位置
char* _IO_write_base; /* Start of put area. */ 写缓冲区的起始位置
char* _IO_write_ptr; /* Current put pointer. */ 写到了哪个位置
char* _IO_write_end; /* End of put area. */ 写缓冲区的末尾位置
文件描述符里包含这些指针,在文件进行读写的时候告诉函数应该从哪读;
int _fileno; 保存文件描述符的数值,
代码验证
#include<stdio.h>
int main()
{
FILE*fp=fopen("1.text","w");
printf("%d\n",fp->_fileno);
}
结果是
标准输入标准输出和标准错误分别是0,1,2,根据最小值规则,文件的文件标识符就是3
图文匹配
struct _IO_FILE{...}这个结构体是标准库当中的结构体,该结构体里上述的指针维护的缓冲区是标准库的缓冲区
5.文件描述符和文件流指针的关联
上述说到文件描述符是PCB里的一个数组的的下标,所以一个PCB里可以有多个文件描述符.等同于,PCB里包含进程打开的所有文件...而文件流指针的范围就比较小了,一个文件流指针只能保存一个文件的文件描述符,就是文件流指针只能代表一个文件.所以一个进程至少要打开三个文件,标准输入,标准输出,标准错误.
图文对比
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)