Linux基础IO——文件的系统调用与文件描述符的本质

在Linux系统下有句名言是,Linux中一切皆文件

C语言中的文件接口

在C语言中有三个数据流,分别是stdin、stdout、stderr,这三个标准文件是交给程序员来输入输出的

可以从键盘读入,显示器输出,也可以输出到文件中,那么其实在操作系统内部,他是把显示器、键盘等外设也看作是文件,向显示器输出和向磁盘文件中输出写入是没有本质区别的

C语言打开文件的函数是fopen,读取是fread、fscanf、fgets,写入是fwrite、fprintf、fputs,和基础的scanf、gets使用都是一致的,只需要在末尾加上写入的文件指针即可

fopen的返回值和三个数据流都是文件指针类型的,是FILE*

操作文件的系统调用

每一种语言都有各自不同的文件操作函数,但不管语言如何改变,想要对文件进行读写都需要让操作系统帮忙,使用系统调用才能对文件进行操作

操作系统有四个系统调用

open、close、write、read

open

在这里插入图片描述

我们主要看第一个定义,他的返回值是文件描述符fd,第一个参数是打开文件的路径,flags是你想要打开文件的方式

因为文件的打开方式比较繁多,不能每一个都设置一个参数,于是就想到使用位图来表示,通过判断某一位是否为1来查看是否有这个选项

在这里插入图片描述

具体有这么些

  • O_RDONLY:只读
  • O_WRONLY:只写
  • O_RDWR:读写打开

上面这三个必有并且只有一个

  • O_CREAT:若文件不存在则创建
  • O_APPEND:追加写

具体用法如下

int fd = open("/home/leaf/test", O_WRONLY|OCREAT)

能这么用实际上就是因为这些选项是用宏定义来的,直接按位或就能确保选上了

close

在这里插入图片描述

close没什么好说的,如果成功关闭则返回0

write

在这里插入图片描述

write是写入数据,写入的内容是buf,写入的字节数是count,调用成功就返回文件中的字节数

char* buffer = "写入数据";
int fd = open("/home/leaf/test",O_WRONLY);
write(fd, buffer, sizeof(buffer));

read

在这里插入图片描述

read就是从文件中读取数据,读取到buff中,大小是count,调用成功则返回读取到的字节数

char buffer[1000];
int fd = open("/home/leaf/test",O_WRONLY);
ssize_t n = read(fd, buffer, sizeof(buffer));
if(n>0)
    	buffer[n] = '\0';

需要注意的是,文件是什么就会读到什么,我们需要手动添加’\0’

文件描述符详解

为什么文件描述符的类型是整数呢,整数的内容是否有规律

我们可以试试看

int main()
{
  int fd1 = open("/home/leaf/code/24_8_5/text1.txt",O_WRONLY|O_CREAT);
  int fd2 = open("/home/leaf/code/24_8_5/text2.txt",O_WRONLY|O_CREAT);
  int fd3 = open("/home/leaf/code/24_8_5/text3.txt",O_WRONLY|O_CREAT);
  printf("fd1 = %d; fd2 = %d; fd3 = %d\n",fd1, fd2, fd3);     
  return 0;
}

在这里插入图片描述

这里其实是从3、4、5依次向后的

那么缺少的0、1、2其实就对应着前面的三个文件描述符stdin、stdout、stderr,之后我们创建的文件描述符也就依次创建

文件描述符的本质

文件描述符其实是对应着数组下标

操作系统要管理就需要先描述后组织,管理文件就需要管理这些结构体,也就是文件的内容、属性等,再使用链表将这些结构体链接起来

文件描述符对应的是数组下标,什么数组呢,其实就是文件结构体的指针数组,我们称之为文件描述符表

每个进程都需要知道自己打开了哪些文件,所以进程PCB中就会保存一张这个表,这样再对其中的内容做增删查改就容易许多了

Linux中一切皆文件

对于这句话不好理解的其实就是为什么硬件也是文件

磁盘、显卡、磁盘等其实对应了不同的方法,但他们的核心功能也是读写,也就是IO

操作系统会为每一个底层硬件创建file结构体,这个结构体一定包含两个函数指针,分别指向硬件的读写方法,这样文件和硬件的访问就变成了和结构体中指针的访问了

因此当进程想要使用硬件资源时,只需要访问对应文件结构体的函数指针即可

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栖林_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值