您的位置:首页 > 其它

系统调用----初步了解文件描述符

2018-03-27 22:34 309 查看
在学习操作系统之前,我们在操作文件时会使用一些C接口,比如说,fwrite fread fopen fclose 这些,但是除了这些C接口(其他语言也有),我们还可以使用一些系统调用接口来进行文件访问。

例如:

写文件(write)

代码实现:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>
//往名为“myfile”的文件里写入5条hello,world
int main()
{
umask(0);
//fd为文件描述符
//O_WRONLY:只写,O_CREATE:如果想要打开的文件不存在则创建该文件
//0644:权限
int fd = open("myfile",O_WRONLY|O_CREAT,0644);
if(fd < 0)
{
perror("open");
return 1;
}
int count = 5;
const char *msg = "hello,world\n";
int len = strlen(msg);
while(count--)
{
//fd:文件描述符
//msg:缓冲区首地址
//len:本次读取,期望写入多少个字节的数据
//返回值:实际写了多少字节的数据
write(fd,msg,len);
}
close(fd);
return 0;
}




读文件(read)

代码实现:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
//往buf里读入5个
int main()
{
//O_RDONLY:只读
int fd = open("myfile",O_RDONLY);
if(fd < 0)
{
perror("open");
return 1;
}
int count = 5;
const char *msg = "hello,world\n";
char buf[1024];
while(count--)
{
//fd:文件描述符
//buf:指定内存
//strlen(msg):一次读取这么多字节
//返回值:返回0表示已到达文件尾或是无可读取的数据
//返回非0的正数则为实际读取到的字节数
ssize_t s = read(fd,buf,strlen(msg));
if(s > 0)
{
printf("%s",buf);
}
else
{
break;
}
}
close(fd);
return 0;
}




之前我们使用C接口操作文件是总会用到 FILE* ,而现在我们使用系统调用接口发现有一个自称是文件描述符的 fd 。下面我们就来说一说这个文件描述符。

文件描述符:是一个取值为0,1,2,3,4,5,6,7,8,,9,10……的数(没有负值)

另外,我们的C总是默认打开3个输入输出流,分别是:

stdin:标准输入
stdout:标准输出
stderr:标准错误


三者分别对应于我们的键盘,显示器,显示器

这三个流的类型都是FILE*,也就是说他们的返回值类型都是文件指针

回到文件描述符来说,这三个对应的文件描述符分别是:

stdin->0
stdout->1
stderr->2


Linux进程默认这3个缺省打开的文件描述符,分别是标准输入0,标准输出1,标准错误2

当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件,于是就有了file结构体,表示一个已经打开的文件对象,而进程执行open系统调用,所以必须让进程和文件关联起来,每个进程都有一个指针*files,指向一张表files_struct,该表最重要的部分就是包含一个指针数组,每个元素都是一个指向打开文件的指针,所以,本质上,文件描述符就是该数组的下标,所以只要拿着文件描述符,就可以找到对应的文件。



对于新打开的文件的文件描述符的分配规则就是:在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符

IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上,访问文件都是通过fd访问的,所以说C库当中的FILE结构体内部,必定封装了fd
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: