APUE—UNIX文件系统
在linux系统中——一切都是文件。
1. 磁盘物理结构
磁盘的物理结构如下:
磁盘由很多盘面组成,而盘面上则是由很多同心圆环组成的磁道,每个磁道又被切割成许多扇区。所有磁盘面的同一个磁道构成一个柱面,同一柱面的所有磁道写完后,才会移入下一柱面。
磁盘的最小组成单位可以看成扇区,每个扇区的大小逻辑上看起来是512字节,但实际上底层的物理扇区是4096字节,可以通过如下方式去得到:
gqx@gqx-Lenovo-Product:~$ sudo fdisk -l
Disk /dev/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
由于扇区太小了,如果实际操作的时候按扇区为单位去读写数据的效率比较低,就比如10M的文件,磁头就需要读取(1024*10/512)20480次移动操作,所以一般都是用块(多个扇区)这个逻辑概念来实现具体的读写操作,一个块的大小通常是4096个字节:
gqx@gqx-Lenovo-Product:~$ sudo tune2fs -l /dev/sda4 | grep "Block size"
Block size: 4096
2. 文件系统的结构
在UNIX系统里当我们将上述的磁盘结构上升一层到具体的文件层面时,就会将磁盘划分成很多个分区,每个分区对应一个文件系统,磁盘、分区和文件系统的结构如下:
自举块:也称为引导块,分区中文件系统自身引导程序存放的地方。
超级块:超级块在每个文件系统的根上,超级块描述和维护文件系统的状态。
......
这里只关注柱面组里的i节点和数据块部分结构,其中数据块存放着文件的具体内容,如下图:
每个i节点都有一个链接计数标记,表示指向该i节点的文件/目录的数量,只有当链接计数标记减少到0时,才会释放该文件所占用的数据块,可以从图中看到有两个目录项指向同一个i节点。
i节点包含了文件的所有信息,包含文件的权限位信息,文件类型文件长度等(文件名保存在目录项中)。
在不更换文件系统的情况下为一个文件重命名,该文件的实际位置并没有更改,只需在目录块中构造一个新的目录项指向原先的i节点,并将原来的目录项删除即可。
可以举个栗子,假设我现在在一个空的工作目录中创建了一个目录(testdir),则现在这个目录中有三个子目录——("." , ".." 和 "testdir"),这三个目录以及testdir目录在柱面组里目录块和数据块的结构如下:
图中,最右侧部分是工作目录的目录项,中间部分是testdir目录的目录项,通过这种组织结构可以从工作目录跳到testdir目录(i节点2549),也可以从testdir目录回到原先的工作目录(i节点1267)。
i节点一般存放的是一些状态信息,所以影响到i节点的操作有很多,比如更改文件的访问权限,更改用户ID,更改链接数等,一些涉及到文件实际内容相关的操作都不会影响到节点。
3.文件I/O
首先可以来看看Unix系统的体系结构如下图,所谓的内核,通常也是指操作系统(当然一般意义上的操作系统还包含了一些更加易于操作的交互功能等,如果忽略这些次要的东西,操作系统其实就是内核)。从图中可以看出应用程序既可以通过直接系统调用(内核对外提供的接口)来访问内核,也可以通过shell,公用函数库来达到一些目的。
在I/O函数这里,根据程序所使用的方式不同——系统调用还是公用函数库调用,可以将I/O函数分成两类,带缓冲的I/O函数和不带缓冲的I/O函数。(严格意义上讲,传统的UNIX系统在内核中都会设有缓冲高速缓存或页高速缓存,当向文件写数据时,通常都会先把数据放入高速缓存中,然后在将其落盘,而此处的流缓存区是在公用函数库上做了又加了一层缓存区)
无缓存IO操作数据流向路径:数据——内核缓存区——磁盘:不带缓冲的I/O函数——open,read,write,lseek和close。
标准IO操作数据流向路径:数据——流缓存区——内核缓存区——磁盘:带缓冲的I/O函数——通常是以f为开头的操作函数等,比如fopen,fputs等。
输入输出
文件描述符:内核用一个非负整数来标志一个特定进程正在访问的文件。
每当运行一个程序的时候,所有shell都会为这个程序打开三个文件描述符——标准输入,标准输出,以及标准错误。
/* Standard file descriptors. POSIX 标准中 (unistd.h文件中定义) */
#define STDIN_FILENO 0 /* Standard input.STDIN_FILENO的值是0,表示标准输入文件描述符 */
#define STDOUT_FILENO 1 /* Standard output.STDOUT_FILENO的值是1,表示标准输出文件描述符*/
#define STDERR_FILENO 2 /* Standard error output. */
stdin和STD××_FILENO的区别
STDIN_FILENO是系统级API定义的变量,而stdin则是属于标准库处理的输入流
数据类型不一样 stdin是FILE*类型的,STDIN_FILENO是int类型。
使用stdin的函数主要有:fread、fwrite、fclose等,基本上都以f开头。而使用STDIN_FILENO的函数有:read、write、close等。
文件共享
unix内核使用三种数据结构——进程表项,文件表项和v节点表项来表示打开的文件。
上图表示一个进程打开了标准文件输入(0)、一个标准输出打开(1)等。每个进程都会维护一个进程表项记录了①文件描述符的标志;②指向文件表项的指针。而文件表项则包含①文件状态标志(读、写、追加、阻塞等);②当前文件的偏移量;③v节点指针(v节点指针指向v节点表项)。v节点表项包含了对文件的操作函数指针,同时v节点还包含了指向i节点的指针,i节点的相关介绍由在前面已经说过。
现在如果两个独立的线程打开了同一个文件,这个时候,该文件的v节点表项会被共享,他们所共享的也就是v节点表项,如图,这样就可以维护多个不同的文件打开状态,同时又保证底层数据的空间开销最小,但也会带来一些新的问题,如何避免高并发下的发生文件操作的冲突问题。
4.文件的权限位
这里不再简单的论述九个简单(r,w,x)权限位,而是对其余三个(和三个角色的最后一位执行权限共享位表示)做解释:
setuid:设置使文件在执行阶段具有文件所有者的权限。比如一般用户想要更改自己的登入密码,而这个文件是存放在/etc/shadow下的,但是只有root才有权限去读写,这个时候就需要/usr/bin/passwd文件来帮我们完成。
gqx@gqx-Lenovo-Product:~/桌面$ ll /usr/bin/passwd
-rwsr-xr-x 1 root root 54256 5月 17 2017 /usr/bin/passwd*通过执行该命令,系统看到passwd命令文件的属性有小写s后,表示这个命令的属主权限被gqx用户获得,也就是gqx用户获得文件/etc/shadow的读写权限。
setgid:该权限只对目录有效。目录被设置该位后,任何用户在此目录下创建的文件都具有和该目录所属的组相同的组。
sticky bit(粘着位):该位可以理解为防删除位。 一个文件是否可以被某用户删除,主要取决于该文件所属的组是否对该用户具有写权限。如果没有写权限,则这个目录下的所有文件都不能被删除,同时也不能添加新的文件。 如果希望用户能够添加文件但同时不能删除文件,则可以对文件使用sticky bit位。设置该位后,就算用户对目录具有写权限也不能删除该文件。(比如ubuntu里的目录/tmp和/var/tmp, 除文件所有者外,超级用户也有权限删除,其他用户没有权限)
当前用户可以通过umask(既是C函数,也是shell的一个命令)来控制创建文件的权限:
gqx@gqx-Lenovo-Product:~/shellTest$ umask
0002
gqx@gqx-Lenovo-Product:~/shellTest$ touch a
-rw-rw-r-- 1 gqx gqx 0 7月 3 14:14 a
gqx@gqx-Lenovo-Product:~/shellTest$ umask 0022
gqx@gqx-Lenovo-Product:~/shellTest$ umask
0022
gqx@gqx-Lenovo-Product:~/shellTest$ touch b
gqx@gqx-Lenovo-Product:~/shellTest$ ls -l
-rw-rw-r-- 1 gqx gqx 0 7月 3 14:14 a
-rw-r--r-- 1 gqx gqx 0 7月 3 14:26 b
#创建新文件:读写权限为666-022=644
参考资料:
《UNIX环境高级编程》
APUE—UNIX文件系统的更多相关文章
- [apue] linux 文件系统那些事儿
前言 说到 linux 的文件系统,好多人第一印象是 ext2/ext3/ext4 等具体的文件系统,本文不涉及这些,因为研究具体的文件系统难免会陷入细节,甚至拉大段的源码做分析,反而不能从宏观的角度 ...
- unix文件系统
转自here 我一向坚持的原则,那就是任何东西的根本性的,本质上的原理以及背后的思想都是及其简单的,所谓的复杂性都是优化与策略化的扩展带来的,正如TCP一样,UNIX的文件系统也不例外!我们必须知道, ...
- Unix文件系统的主要特点是什么?
1. 树型层次结构 2. 可安装拆卸的文件系统 3. 文件是无结构的字符流式文件 4. Unix文件系统吧外部设备和文件目录作为文件处理
- 在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据
在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据.如果在创建znode时Flag设置为EPHEMERAL,那么当创建这个znode的节点和Zook ...
- 《Unix&Linux大学教程》学习笔记6——Unix文件系统
1:Unix文件类型——3种 普通文件(常规文件):文本文件(纯文本.脚本.源程序.配置文件.html等).二进制文件(多媒体文件.数据库等) 目录:用于组织文件 伪文件:不存储数据,目的是提供一种服 ...
- [APUE]UNIX进程的环境(下)
一.共享库 共享库使得可执行文件中不再需要包含常用的库函数,而只需在所有进程都可存取的存储区中保存这种库例程的一个副本.程序第一次执行的时候或第一次调用某个库函数的时候,用动态链接方法将程序与共享库函 ...
- Unix 文件系统读写时权限校验
文件系统中的所有文件都是在读出或写入时进行权限校验 一个问题,如果一个用户对一个普通文件有读写权限,在使用vim编辑时,管理员撤销掉此用户对此文件的写入权限 那么,这个普通用户还可以将修改写入文件吗?
- unix文件系统中的硬链接和软连接
硬链接: 一般情况下,文件名和inode号码是"一一对应"关系,每个inode号码对应一个文件名.但是,Unix/Linux系统允许,多个文件名指向同一个inode号码. 这意味着 ...
- APUE(unix环境高级编程)第三版---first day---部署书中实例的运行环境(apue.h)
操作环境:RHEL7.0 部署apue.h实例运行环境 1.下载头文件src.3e.tar.gz 2.解压 tar zxvf src.3e.tar.gz 3.创建普通用户(我仿照书上创建的sar用户) ...
随机推荐
- Retrofit+Okhttp+RxJava打造网络请求之Post
之前一直在准备Android培训的事情,所幸的是终于完事啦,在这过程中真的发现了自身无论从沟通能力还是技术能力上很多的不足,就用一句 路漫漫其修远兮,吾将上下而求索 来勉励自己吧.之前也在项目上用上O ...
- 电信NBIOT 6 - NBIOT实现数据上传及指令接收
电信NBIOT 1 - 数据上行(中国电信开发者平台对接流程) 电信NBIOT 2 - 数据上行(中间件获取电信消息通知) 电信NBIOT 3 - 数据下行 电信NBIOT 4 - NB73模块上行测 ...
- [b0016] python 归纳 (二)_静态方法和类方法
# -*- coding: UTF-8 -*- """ 测试 类的静态方法,类方法 @staticmethod @classmethod 总结: 1. self 指向类对 ...
- Windows | Ubuntu 16.04/18.04 安装Pycharm并永久破解以及安装配置Anaconda3
Ubuntu 18.04下 1.安装python 2._版本,输入 sudo apt install python 命令行输入 python或python3会打开对应的版本. 输入 exit()或C ...
- NLP中的预训练语言模型(四)—— 小型化bert(DistillBert, ALBERT, TINYBERT)
bert之类的预训练模型在NLP各项任务上取得的效果是显著的,但是因为bert的模型参数多,推断速度慢等原因,导致bert在工业界上的应用很难普及,针对预训练模型做模型压缩是促进其在工业界应用的关键, ...
- 如何在docker镜像里安装pycuda和numba?
其实,安装numba还好,直接pip install numba就可以. 但pycuda就不那么友好了. 默认安装时,可能会报如下错误: src/:: fatal error: curand.h: N ...
- sed练习2
[root@node2 ~]# cp /etc/passwd /server/scprits/ [root@node2 ~]# cd /server/scprits/ [root@node2 scpr ...
- Anaconda 下载
Anaconda官网:https://repo.anaconda.com/archive/清华大学镜像站:https://mirrors.tuna.tsinghua.edu.cn/anaconda/a ...
- win10系统易升更新不成功c盘也满了,解决方法
删除临时更新文件: 1)同时按下Windows键和R键,打开运行,输入services.msc 2)找到WindowsUpdate服务项,右键选择禁用. 3)打开c:\windows\Software ...
- MySQL8 修改密码验证插件
MySQL8 修改密码验证插件 查看当前用户使用的密码验证插件 mysql> show variables like '%auth%'; +--------------------------- ...