Linux - 文件描述符 | 文件系统 | 软硬链接

文章目录

    • 一、文件描述符
      • 1、补充知识
      • 2、文件描述符是什么?
      • 3、处理文件的系统调用接口
      • 4、文件描述符的分配规则
      • 5、简单理解Linux下一切皆文件
      • 6、FILE
      • 7、重定向
    • 二、文件系统
    • 三、软硬链接
      • 1、软连接
      • 2、硬链接
      • 3、软硬链接对比


一、文件描述符

1、补充知识

(1)文件 = 属性 + 文件内容
(2)想要访问文件就需要先打开文件,而文件本身在磁盘中,如果想要打开文件就需要将文件加载到内存上(冯诺依曼体系结构决定的。
(3)管理文件:先描述,再组织( 就会像进程那样被管理起来),所以文件在内存中:文件内核数据结构+文件内容。
(4)linux下一切皆文件。

2、文件描述符是什么?

在进程中每打开一个文件,都会创建有相应的文件描述信息struct file,这个描述信息被添加在pcb的struct files_struct中,以数组的形式进行管理,随即向用户返回数组的下标作为文件描述符,用于操作文件,其中默认打开的三个文件标准输入(stdin)、标准输出(stdout)和标准错误(stderr)分别分配为文件描述符0、1和2 。

在这里插入图片描述

3、处理文件的系统调用接口

(1)open
功能:打开文件。
函数原型:

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode); 

头文件:

#include <fcntl.h>

参数:

  1. pathname:要打开或创建的文件的路径名。这个参数是一个字符串,指定了文件的绝对路径或相对路径。
  2. flags:文件的打开方式,这是一个整数,由一系列标志位组成,如果需要选择多个选项可以使用位运算符或上即可。常用的标志位包括:
    O_RDONLY:只读方式打开文件。
    O_WRONLY:只写方式打开文件。 O_RDWR:读写方式打开文件。
    O_CREAT:如果文件不存在,则创建新文件。此时需要同时指定第三个参数mode来设置新文件的权限。
    O_TRUNC:如果文件已存在且为只写或读写方式打开,则将其长度截断为0。
    O_APPEND:以追加方式打开文件。写入的数据会被追加到文件末尾,而不是覆盖原有数据。
    其他标志位还包括O_NONBLOCK、O_SYNC等,用于控制文件的打开行为和I/O操作的同步性。
  3. mode(可选):当flags包含O_CREAT标志时,需要指定此参数来设置新文件的权限。mode是一个整数,表示文件的访问权限和文件类型。通常使用八进制数来表示权限,如0644表示rw-r–r–。

返回值:

成功时,open接口返回一个非负整数的文件描述符。
失败时,返回-1,并设置全局变量errno以指示错误类型。

(2)write
功能:向文件写入数据。
函数原型:

ssize_t write(int fd, const void *buf, size_t count);

头文件:

<unistd.h> 

参数:

  1. fd:文件描述符,标识了要写入数据的文件或设备。
  2. buf:指向包含要写入数据的缓冲区的指针。
  3. count:要写入的数据字节数。

返回值:

成功时返回实际写入的字节数,失败时返回 -1 并设置 errno。

(3)read
功能:从文件中读取数据。
函数原型:

ssize_t read(int fd, void *buf, size_t count);

头文件:

<unistd.h> 

参数:

  1. fd:文件描述符,标识了要从中读取数据的文件或设备。
  2. buf:指向用于存储读取数据的缓冲区的指针。
  3. count:希望读取的数据字节数。

返回值:

成功时返回实际读取的字节数(可能小于请求的字节数,表示已到达文件末尾或读取过程中发生错误),失败时返回 -1 并设置 errno。

(4)close
功能:关闭文件。
函数原型:

int close(int fd);

头文件:

<unistd.h> 

参数:
fd:文件描述符。

返回值:

成功时返回0。
失败时返回-1,并设置errno以指示错误类型。

(5)综合使用
写文件:

  1 #include <stdio.h>                                                                                                          2 #include <fcntl.h>                                                              3 #include <unistd.h>                                                             4 #include <string.h>                                                             5                                                                                 6 int main()                                                                      7 {                                                                               8     int fd = open("bite.txt",O_WRONLY|O_CREAT,0666); //打开                           9                                                                                 10     if(fd < 0)                                                                  11         return -1;                                                              12                                                                                 13     const char *s = "i like linux!";                                            14                                                                                 15     write(fd,s,strlen(s));            //写入                                          16                                                                                 17     close(fd);                        //关闭文件                                          18     return 0;                                                                   19 } 

读文件:

  1 #include <stdio.h>                                                              2 #include <fcntl.h>                                                                                                          3 #include <unistd.h>                                                             4 #include <string.h>                                                             5                                                                                 6 int main()                                                                      7 {                                                                               8     int fd = open("bite.txt",O_RDONLY,0666);   //打开                                 9                                                                                 10     if(fd < 0)                                                                  11         return -1;                                                              12                                                                                 13     char s[1024];                                                               14     read(fd,s,1024);                          //读文件                            15                                                                                 16     write(1,s,strlen(s));                     //向显示器输入                                  17                                                                                 18     close(fd);             //关闭文件                                                     19     return 0;                                                                   20 }

4、文件描述符的分配规则

文件描述符分配:指针数组从开始查找第一个空缺的位置的下标。
如:关闭输入流,再打开一个文件。

  1 #include <stdio.h>                                                                                                          2 #include <fcntl.h>                                                              3 #include <unistd.h>                                                             4 #include <string.h>                                                             5                                                                                 6 int main()                                                                      7 {                                                                               8     //关闭输出流                                                                9     close(0);                                                                   10                                                                                 11     //打开文件                                                                  12     int fd = open("test1.txt",O_WRONLY|O_CREAT,0666);                           13     if(fd < 0)                                                                  14         return -1;                                                              15                                                                                 16     const char *s = "linux!";                                                   17                                                                                 18     printf("fd : %d\n%s\n",fd,s);                                               19                                                                                 20     close(fd);//关闭文件                                                        21     return 0;                                                                   22 } 

在这里插入图片描述

5、简单理解Linux下一切皆文件

在这里插入图片描述

6、FILE

(1)补充:

  1. c语言的处理文件的库函数封装了系统调用(fopen对open进行了封装)。
  2. FILE是结构体,并且封装了文件描述符。

(2)缓冲区
文件内核缓冲区:
使用系统调用接口如write时,会将输入的内容输入到该缓冲区,等到一定时机操作系统会自动刷新如关闭文件。

语言级缓冲区(用户级缓冲区):
存在哪里?
存在FILE结构体中(使用字符数组储存),如当使用fwrite接口时,先将输入的内容存到该数组中,等到一定数组满的时候就会调用系统接口write输入到文件内核缓冲区中(全缓冲),但是如果时写入显示器文件时是行缓冲。
在这里插入图片描述
为什么存在缓冲区?
减少调用,提高I/O效率。

(3)刷新缓冲区接口
fflush
功能:

对于C语言中的标准I/O操作,fflush 函数可以用来刷新缓冲区。它适用于文件指针(FILE *)类型。

头文件:

#include <stdio.h>

函数原型:

int fflush(FILE *stream);

参数:

fflush函数的参数是一个文件指针(FILE *stream),用于指定需要刷新的。

文件流。
返回值:

fflush函数的返回值是一个整数,表示函数调用的结果状态。如果成功刷新,fflush返回0;如果指定的流没有缓冲区或者只读打开,也返回0值;如果发生错误,返回EOF。

fsync
功能:

fsync 函数用于刷新文件描述符(int fd)的缓冲区,确保数据从内核缓冲区写入到磁盘。

头文件:

unistd.h

函数原型:

int fsync(int fd);

参数:

fsync函数的参数是一个文件描述符(int fd),表示需要同步的文件。文件描述符是一个整数,用于在程序中唯一标识一个打开的文件。

返回值:

fsync函数的返回值是一个整数,表示函数调用的结果状态。如果同步成功,fsync函数返回0;如果同步失败,返回-1,并设置errno为错误码,以便进一步诊断问题。

7、重定向

(1)向看下面例子:

  1 #include <stdio.h>                                                              2 #include <fcntl.h>                                                              3 #include <unistd.h>                                                             4 #include <string.h>                                                             5                                                                                 6 int main()                                                                      7 {                                                                               8     //关闭输出流                                                                9     close(1);                                                                   10                                                                                 11     //打开文件                                                                  12     int fd = open("test.txt",O_WRONLY|O_CREAT,0666);                            13     if(fd < 0)                                                                  14         return -1;                                                              15                                                                                 16     const char *s = "linux!";                                                   17                                                                                 18     printf("fd : %d\n%s\n",fd,s);   //此时不向显示器输入,向test.txt                                                        19     fflush(stdout);//刷新缓冲区                                               20                                                                                 21     close(fd);//关闭文件                                                        22     return 0;                                                                   23 }  

在这里插入图片描述
上述操作从输入到显示器文件转到输入test.txt文件中,实现了重定向,重定向操作:< 、> 、 >>。

(2)本质
原本printf想向文件描述符为1指向的file(输出流)输入的,但是现在被
test.txt替换了,从而向test.txt文件输入了。
在这里插入图片描述

(3) dup2系统调用
函数原型:

int dup2(int oldfd, int newfd);

参数

oldfd:要复制的文件描述符。
newfd:目标文件描述符。

返回值:

成功时,返回 newfd 的值。
失败时,返回 -1 并设置 errno 以指示错误。可能的错误包括: EBADF:oldfd 或newfd 不是有效的文件描述符。 EINTR:调用被信号中断。

功能:

dup2 会将 oldfd 复制到 newfd 上。 如果 newfd 已经被打开,dup2 会首先关闭它,这样可以确保没有资源泄漏。 然后,newfd 将会变成 oldfd 的一个副本,也就是说,newfd 和 oldfd 指向相同的文件表项(file table entry)。 如果 oldfd 和 newfd 是相同的,那么 dup2 什么都不做,直接返回 newfd。

使用:

  1 #include <stdio.h>                                                                                                          2 #include <fcntl.h>                                                              3 #include <unistd.h>                                                             4 #include <string.h>                                                             5                                                                                 6 int main()                                                                      7 {                                                                               8     //打开文件                                                                  9     int fd = open("test2.txt",O_WRONLY|O_CREAT,0666);                           10     if(fd < 0)                                                                  11         return -1;                                                              12                                                                                 13     dup2(fd,1); //1是输出显示器的文件描述符的值                                 14     const char *s = "linux!";                                                   15                                                                                 16     printf("fd : %d\n%s\n",fd,s);   //此时不向显示器输入,向test2.txt           17     fflush(stdout);//刷新语言缓冲区                                             18                                                                                 19     close(fd);//关闭文件                                                        20     return 0;                                                                   21 } 

在这里插入图片描述
(4)进程替换为什么不会影响重定向?

  1. 文件描述符的独立性:在Linux系统中,每个进程都有一个独立的文件描述符表,用于管理该进程打开的文件和相关的输入输出操作。当进程进行替换时,虽然进程的代码和数据被新程序替换,但文件描述符表(除了被明确关闭的文件描述符)通常会被保留下来。因此,之前设置的重定向操作仍然有效。
  2. 进程属性的保留:尽管exec函数族改变了进程的内容,但进程ID和大多数属性(如文件描述符和信号处理程序)保持不变。这种特性使得exec成为实现各种高级进程控制技巧的基础,同时也保证了重定向等文件操作在进程替换后的连续性。
  3. 重定向的实现方式:重定向是通过修改文件描述符表来实现的,而不是通过修改进程的代码或数据。因此,无论进程的内容如何变化(包括进程替换),只要文件描述符表保持不变或相应的文件描述符未被关闭,重定向就会继续生效。

二、文件系统

在这里插入图片描述

  1. Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。
  2. 超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量, 未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的 时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个 文件系统结构就被破坏了
  3. GDT,Group Descriptor Table:块组描述符,描述块组属性信息。
  4. 块位图(BlockBitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没 有被占用
  5. inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
  6. i节点表:存放文件属性 如文件大小,所有者(但是不存在文件名),最近修改时间等数据区:存放文件内容

目录文件
目录文件 = inode + datablock = 属性 + 内容,而内容储存的是文件名和inode的映射关系,所以通过路径找到文件名就能找到相应的inode了。

文件描述符和进程的关系

在这里插入图片描述
创建新文件过程
在这里插入图片描述

  1. 存储属性 内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。
  2. 存储数据 该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第一块数据 复制到300,下一块复制到500,以此类推。
  3. 记录分配情况 文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。
  4. 添加文件名到目录 新的文件名abc。linux如何在当前的目录中记录这个文件?内核将入口(263466,abc)添加到目录文 件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。

三、软硬链接

1、软连接

(1)什么是软链接

软链接(也称为符号链接或symlink)是一种特殊的文件类型,它指向另一个文件或目录。软连接类似于Windows中的快捷方式。通过使用软连接,你可以在不复制文件内容的情况下,为文件或目录创建多个访问路径,软连接有独立的inode,内容保存的是目标文件的路径。

(2)建立软链接

ln -s [目标文件或目录] [软链接名称]

如:
在这里插入图片描述
(3)删除
使用rm命令。

(4)应用场景
快捷方式。

2、硬链接

(1)什么是硬链接

硬链接(Hard Link)是一种文件链接方式,它允许你为文件系统中的同一个文件创建多个目录项(也称为文件名或入口)。这些硬连接共享相同的inode(索引节点)和数据块(不同文件名映射同一inode),因此它们实际上是同一个文件的多个访问点。

(2)建立硬链接

ln [源文件] [硬连接名称]

在这里插入图片描述

(3)删除
使用rm命令。

(4)应用场景
备份。

3、软硬链接对比

(1)inode
软链接有独立的inode,硬链接与源文件一样。

(2)删除源文件后
软链接不能使用,硬链接可以。

(3)文件的权限
软链接的权限和多个方面有关,一般来说设置为:777,硬链接和源文件的权限一样。

(4)跨文件系统
软连接可以跨文件系统进行连接(因为保存的是文件的路径,通过路径找到源文件的inode),硬链接不可以(使用同一个inode,只能在同一个文件系统中)。

(5)目录
软链接可以链接目录文件,硬链接一般不行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/457962.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5G NR:BWP入门

简介 5G NR 系统带宽比4G LTE 大了很多&#xff0c;4G LTE 最大支持带宽为20MHz&#xff0c; 而5G NR 的FR1 最大支持带宽为100MHz&#xff0c; FR2 最大支持带宽为 400MHz。 带宽越大&#xff0c;意味了终端功耗越多。为了减少终端的功耗&#xff0c;5G NR 引入了BWP(Band Wid…

从零实现数据结构:一文搞定所有排序!(下集)

1.快速排序 思路框架&#xff1a; 在有了前面冒泡选择插入希尔排序之后&#xff0c;人们就在想能不能再快一点&#xff0c;我们知道排序算法说人话就是把大的往后放小的往前放&#xff0c;问题就在于如何更快的把大的挪到数组队尾小的挪到数组前面。这里我们先总结一下上集前…

NVR录像机汇聚管理EasyNVR多品牌NVR管理工具/设备视频报警功能详解

在科技日新月异的今天&#xff0c;视频监控系统作为现代社会的“第三只眼”&#xff0c;正以前所未有的方式深刻影响着我们的生活与社会结构。从公共场所的安全监控到个人生活的记录分享&#xff0c;视频监控系统以其独特的视角和功能&#xff0c;为社会带来了诸多好处&#xf…

【Linux】————磁盘与文件系统

作者主页&#xff1a; 作者主页 本篇博客专栏&#xff1a;Linux 创作时间 &#xff1a;2024年10月17日 一、磁盘的物理结构 磁盘的物理结构如图所示&#xff1a; 其中具体的物理存储结构如下&#xff1a; 磁盘中存储的基本单位为扇区&#xff0c;一个扇区的大小一般为512字…

Python 自动化运维:Python基础知识

Python 自动化运维&#xff1a;Python基础知识 目录 &#x1f4ca; Python 基础复习 数据类型、控制结构与常用函数面向对象编程&#xff08;OOP&#xff09;与类的使用函数式编程概念与 lambda 表达式异常处理与日志记录的基本实践 1. &#x1f4ca; Python 基础复习 数据…

二十二、Python基础语法(模块)

模块(module)&#xff1a;在python中&#xff0c;每个代码文件就是一个模块&#xff0c;在模块中定义的变量、函数、类别人都可以直接使用&#xff0c;如果想要使用别人写好的模块&#xff0c;就必须先导入别人的模块&#xff0c;模块名须满足标识符规则&#xff08;由字母、数…

SwiftUI(三)- 渐变、实心形状和视图背景

引言 在现代的应用的UI设计中&#xff0c;渐变和形状背景为界面带来了丰富的层次与视觉效果&#xff0c;而SwiftUI提供了一系列简单且强大的API&#xff0c;可以轻松实现这些效果。在这篇文章中&#xff0c;我们将介绍SwiftUI中的渐变、实心形状和视图背景的基础用法&#xff…

【论文阅读】Learning persistent homology of3D point clouds

摘要 motivation&#xff1a;PD计算过程非常耗时&#xff0c;严重限制了TDA的应用 本文提出了一种端到端的神经网络模型TopologyNet&#xff0c;用于直接从3D点云数据中拟合拓扑表示。TopologyNet显著减少了生成拓扑表示的计算时间&#xff0c;并在实际实例中保持了较小的近似…

Python4

4. 更多控制流工具 除了刚介绍的 while 语句&#xff0c;Python 还用了一些别的。我们将在本章中遇到它们。 4.1. if 语句 if elif else if x<0: x 0 print(Negative changed to zero) elif x0: print( zero) else: print(More) 4.2. for 语句 Pyth…

2024.7最新子比主题zibll7.9.2开心版源码+授权教程

授权教程&#xff1a; 1.进入宝塔搭建一个站点 绑定 api.zibll.com 域名 并上传 index.php 文件 2.设置伪静态 3.开启SSL证书&#xff0c;找一个能用的域名证书&#xff0c;将密钥(KEY)和证书(PEM格式)复制进去即可 4.在宝塔文件地址栏中输入 /etc 找到 hosts文件并打开&a…

【Docker】docker | 部署nginx

一、概述 记录下nginx的部署流程&#xff1b;将conf配置文件映射到宿主机 前提依赖&#xff1a;自行准备nginx的镜像包 二、步骤 1、运行、无映射 docker run --name nginx -p 80:80 -d nginx:1.18.0-alpine 80&#xff1a;80&#xff0c;前面是宿主机端口&#xff1b;如果冲…

uniapp:上拉加载更多、下拉刷新、页面滚动到指定位置

提醒 本文实例是使用uniapp进行开发演示的。 一、需求场景 在开发商品&#xff08;SKU&#xff09;列表页面时&#xff0c;通常有三个需求&#xff1a; 页面下拉刷新&#xff0c;第一页展示最新数据&#xff1b;上拉加载更多数据&#xff1b;列表页面可以滚动到指定位置&#x…

Liunx权限概念及权限管理

目录 一&#xff1a;shell命令以及运行原理 二&#xff1a;Linux权限的概念 三&#xff1a;Linux的权限管理 3.1文件访问者的分类 3.2文件类型和访问权限&#xff08;事物属性&#xff09; 3.3文件权限的表达方式&#xff1a; 3.4文件访问权限的相关设置方法 四&…

前沿技术与未来发展第一节:C++与机器学习

第六章&#xff1a;前沿技术与未来发展 第一节&#xff1a;C与机器学习 1. C在机器学习中的应用场景 C在机器学习中的应用优势主要体现在高效的内存管理、强大的计算能力和接近底层硬件的灵活性等方面。以下是 C 在机器学习领域的几个主要应用场景&#xff1a; 1.1 深度学习…

Vue3 学习笔记(七)Vue3 语法-计算属性 computed详解

#1024程序员节|征文# 1、计算属性 computed 在 Vue.js 中&#xff0c;计算属性&#xff08;computed properties&#xff09;是一种特殊的响应式属性&#xff0c;它们根据依赖的响应式数据自动更新。计算属性非常适合用于当你需要根据现有数据派生出一些状态时。 (1)、基本用法…

IntelliJ IDEA 查看类class的结构Structure轮廓outline窗口, 快捷键是Alt+7

IntelliJ IDEA 查看类class的结构Structure轮廓outline窗口, 快捷键是Alt7 idea的结构Structure窗口相当于Eclipse的outline 快捷键是: Alt7 或者点击左上角主菜单面包屑,打开主菜单 然后菜单找到-视图&#xff08;View&#xff09;→ 工具窗口&#xff08;Tool Windows&…

基于大数据 Python+Vue 酒店爬取可视化系统(源码+LW+部署讲解+数据库+ppt)

&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 会持续一直更新下去 有问必答 一键收藏关注不迷路 源码获取&#xff1a;https://pan.baidu.com/s/1aRpOv3f2sdtVYOogQjb8jg?pwdjf1d 提取码: jf1d &#…

FineReport 分栏报表

将报表中的数据根据所需要的展示的样式将数据进行分栏展示列分栏 报表中数据是横向扩展的,超过一页的数据会显示在下一页,而每页下面会有很大的一片空白区域,不美观且浪费纸张。希望在一页中第一行扩展满后自动到下一行继续扩展 1、新建数据集 SELECT * FROM 公司股票2、内…

前端代码分享--爱心

给对象写的&#xff0c;顺便源码给大家分享一下 就是简单的htmlcssjs&#xff0c;不复杂 xin1.html <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <title>写你自己的</title> <lin…

深入解析机器学习算法

深入解析机器学习算法 机器学习已经成为当今技术进步的核心推动力量&#xff0c;推动了众多行业的创新。其背后依赖的是各种各样的算法&#xff0c;帮助计算机通过从数据中学习来完成任务。这篇文章将对常见的几类机器学习算法进行深入探讨&#xff0c;帮助你理解其工作原理、…