2024年Linux最新Linux系统:基础IO_kernel_write,含BATJM大厂

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

给大家整理的电子书资料:

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

// 如果不close,log.txt会存在内容。 如果close,log.txt不会存在内容


重定向1号文件为普通文件,输出一行后数据仍在用户缓冲区中。此时**直接关闭系统文件流**,会导致用户缓冲区的内容最终无法刷新到文件中。


避免这种情况可以手动 fflush 刷新用户缓冲区,或者关闭C文件流而不是系统文件流。



write(3, “hello write\n”, 12);
fprintf(file_ptr, “hello printf\n”);
close(1); // 关闭文件


* `write`直接输出到内核缓冲区,不会被 close 关闭文件而“拦截”;
* `printf`是语言库函数,要经用户缓冲区再到内核缓冲区,会被 close 关闭文件“拦截”住。


##### 缓冲区和子进程



write(fd, “hello write\n”, 12);
fprintf(fp, “hello printf\n”);

fork(); // 创建子进程



> 
> 执行结果如图所示:
> 
> 
> 



hello write
hello printf # 父进程
hello printf # 子进程


子进程创建时,printf 等库函数输出的数据仍在C缓冲区中。C缓冲区是存在于C语言文件结构体`FILE`中的内存空间。


故C缓冲区属于程序代码和数据,父子进程是共享的。**任意一方刷走C缓冲区的数据就会触发写时拷贝,剩下一方必定也会刷新走属于自己的那一份数据**。



> 
> 也就是说,只要子进程创建之后,数据仍然存在于用户缓冲区中,那么父子进程必然会都刷新一遍。
> 
> 
> 当然,可以在提前刷新缓冲区,fork 之时就不会存在数据写实拷贝了。
> 
> 
> 


 


### 2. 磁盘文件



> 
> 文件没被打开时是存储在磁盘上的,接下来就是探究磁盘如何合理的存储文件。
> 
> 
> 


#### 2.1 硬盘的物理结构


文件就是文件内容和文件属性的集合。文件如果没有被打开,则是存储在磁盘上的。


磁盘是计算机中的唯一的机械设备。虽然机械硬盘几乎退出桌面市场,但它具有容量大,价格便宜,寿命长的优点,所以企业中一般都使用机械硬盘存储数据。


磁盘整体由盘片、主轴、磁头、机械臂以及其他部分组成,其中主轴带动多个盘片高速转动,由机械臂带动磁头在盘片上寻找指定位置进行读写。


* 主轴上套有一摞盘片,每一个盘片有两个面,每个面都有一个磁头。
* 盘片表面多个同心圆划分出“磁道”,半径所在直线划出“扇面”,扇面和磁道划分出“扇区”。每个扇区大小一般为512字节。
* 磁头首先要移动到指定的磁道,盘片不停旋转,等待指定的扇区到来,即可进行读写。



> 
> 这就是CHS定位法。
> 
> 
> 


![在这里插入图片描述](https://img-blog.csdnimg.cn/20fd23305a5c410088e2bd863ed01117.png#pic_center)


##### 抽象逻辑结构



> 
> CHS是磁盘硬件的定位方式,如果直接将该方法写入内核。就会使内核代码冗余度高、耦合度高、难以维护。
> 
> 
> 操作系统会对磁盘这样的块设备,抽象出统一的逻辑结构。
> 
> 
> 


由于磁头很小,可以看成一个点,磁盘虽然是圆形,对于磁头来说,磁道是线性的一条直线。故可以将磁盘抽象成线性结构,如下图所示:


![在这里插入图片描述](https://img-blog.csdnimg.cn/566a5547af0e4c0999841884d83c3e48.png#pic_center)


磁盘可以抽象成元素为磁道的数组,磁道抽象成元素为扇区的数组,通过下标可以定位任意一个扇区。系统IO的基本单位为4KB,我们将8个扇区看作一个块,通过地址也能定位任意一个块,这就是逻辑块地址LBA。



> 
> LBA和CHS地址通过简单数学运算就可以转化,这样系统和磁盘的交互方式就打通了。
> 
> 
> 


#### 2.2 磁盘区域的管理



> 
> 系统是如何按LBA逻辑结构去管理磁盘的呢?以ext2文件系统为例。
> 
> 
> 


1. 将一整块硬盘,划分成多个磁盘分区。
2. 每个磁盘分区都有一个存储磁盘系统加载信息的启动块`Boot Block`和多个分组`Block Group`。


![在这里插入图片描述](https://img-blog.csdnimg.cn/970c56f3470e408f8a0e112308428431.png#pic_center)


##### 磁盘文件的存储


每一个块组`Block Group`内部,又被划分出了不同区域,这里才是存储文件的开始:




| 内容 | 解释 |
| --- | --- |
| `Super Block` | 存储整个分区文件系统的属性信息。 备份于多个分组中,防止故障 |
| `Group Descriptor Table` | 存储本组的使用详细统计信息,如组内 inode 和 data block 的使用情况 |
| `Inode Table` | 实际存储文件属性的区域 |
| `Data Blocks` | 实际存储文件内容的区域 |
| `Block Bitmap` | 便于在`Data Block`查找空`block`的辅助位图 |
| `Inode BitMap` | 便于在`Inode Table`查找空`inode`的辅助位图 |



> 
> Linux 存储文件是将文件的内容和属性分离存储的。
> 
> 
> 


* `Inode Table`:是实际存储文件属性的区域。


	+ 这块区域也被划分成很多`inode`节点,用来存储单个文件的属性,大小一般为128Bytes。
	+ 一个文件一个`inode`,所以`inode`编号可以唯一标识文件。
* `Data Blocks`:是实际存储文件内容的区域。


	+ 这块区域又划分成很多`block`块,用来存储单个文件的内容,大小一般为4KB。
	+ `inode`结构体中有`block`的索引数组。


![在这里插入图片描述](https://img-blog.csdnimg.cn/ea042c488a6047dd9e54fafecb43a2a2.png#pic_center)


* `Block BitMap`,`Inode BitMap`:遍历`Inode Table` 找空余`inode`效率太低。因此使用两个位图来帮助我们查找空余位置。
* 位图的下标对应每个`inode/block`的位置下标。
* 位图的元素值为1表示该`inode/block`被占用、为0表示`inode/block`未使用。


![在这里插入图片描述](https://img-blog.csdnimg.cn/caf71d1cd5114605ad564768dc7d9e77.png#pic_center)


##### 理解inode



//inode结构体,存储文件的属性信息
struct inode {
// 文件的所有属性
int inode_number;
int blocks[NUM]; // 存储该文件所占有的所有block的下标
};



> 
> NUM个block大小终究是有上限的,如何做到一个文件的大小无上限呢?
> 
> 
> 


blocks数组存储的是文件所占用的block的索引下标。其中分为直接索引和二级索引甚至多级索引。


* 直接索引:直接就是存储文件内容的block的下标。
* 二级索引:对应的block中不存储文件内容,存储文件后续使用的block的下标,依此找到后续block。


文件系统会根据文件的大小,来规定一级索引和多级索引的数量。


![在这里插入图片描述](https://img-blog.csdnimg.cn/43d27da255f948c1b3d312cc8394dae8.png#pic_center)


##### 理解文件增删查改



$ ll -i # 查看文件的inode编号
total 16
1320703 -rw-rw-r-- 1 yyx yyx 12 May 22 15:00 hello.c
1320704 drwxrwxr-x 2 yyx yyx 4096 May 22 14:31 tmp


Linux系统只根据文件的 inode 编号来标识文件。


文件的 inode 中并不存储文件名,但文件都存放在某个目录下\*\*。在目录文件的 block 中保存的是该目录下所有文件的 inode 编号和文件名的映射\*\*。


![在这里插入图片描述](https://img-blog.csdnimg.cn/b92d0c4bafe54e8997a23d92f9fbae1e.png#pic_center)



$ touch hello.c # 1. 在inode bitmap中找到空余的inode位置,并创建文件inode
# 2. 再将文件名hello.c和inode的映射,填充到所在目录的block中

$ echo “hello world” > hello.c # 1. 读取所在目录的block,获取hello.c文件映射的inode
# 2. 根据inode找到文件的block,将字符串hello world填入block中

$ cat hello.c # 1. 读取所在目录的block,获取hello.c文件映射的inode
# 2. 遍历inode table找到并打印inode对应的block[]中的内容

$ rm hello.c # 1. 读取所在目录的block,获取hello.c文件映射的inode
# 2. 在inode bitmap中找到对应inode的位置将其置0
# 之后再创建文件会自动覆盖


#### 2.3 软硬连接


软硬链接可以帮助我们在其他目录下建立一个文件的链接,软链接像是 windows 里的快捷方式,硬链接像是直接复制了一份。


##### 软硬链接的创建和取消



$ ln -s mytest mytest_link # 创建软链接
$ ln mytest mytest_hard # 创建硬链接

$ unlink mytest_hard # 取消硬链接
$ unlink mytest_link # 取消软链接


##### 软硬链接的区别



$ ln tmp/test mytest_soft -s
$ ln tmp/test mytest_hard
$ ll -i
total 8
1055017 -rw-rw-r-- 2 yyx yyx 48 Apr 18 02:24 myfile
1055017 -rw-rw-r-- 2 yyx yyx 48 Apr 18 02:24 myfile_hard # 硬连接inode和源文件相同
1055027 lrwxrwxrwx 1 yyx yyx 10 Apr 18 02:24 myfile_soft -> myfile # 软连接inode和源文件不同


硬链接文件的 inode 和被链接文件的 inode 是一样的,但软链接文件有自己独立的 inode。


* **软连接是个独立文件,有自己的 inode 和 block**。block 中存储原文件的路径。
* 硬链接不是独立文件,硬链接的**本质是在指定目录下把原文件 inode 和新文件名的建立映射关系**。


##### 硬链接数



$ ll -ai
total 16
# 硬链接数
# ↓
1055009 drwxrwxr-x 2 yyx yyx 4096 Apr 18 02:29 .
1048191 drwxrwxr-x 6 yyx yyx 4096 Apr 18 02:23 …
1055017 -rw-rw-r-- 2 yyx yyx 48 Apr 18 02:24 myfile
1055017 -rw-rw-r-- 2 yyx yyx 48 Apr 18 02:24 myfile_hard
1055027 lrwxrwxrwx 1 yyx yyx 10 Apr 18 02:24 myfile_soft -> myfile


硬链接数是inode里的一个属性字段,本质是一种引用计数,表示分区内该 inode 存在多少对映射关系。等到硬链接数为0时,才会将文件从系统中删除。


##### 软硬链接的应用场景


###### 软链接


软链接一般用于将一个其他目录下的文件提到当前目录下,一般用来链接库文件。


###### 硬链接


每个目录下都有 . 和 … ,是当前目录和上级目录的硬链接,方便我们进行目录调整。


目录的硬链接数可以暗示其下有多少子目录。


系统不允许用户给目录的硬链接,容易造成路径环路问题。


#### 2.4 三个文件时间



$ stat test.c # 获取文件的状态信息
File: ‘test.c’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd01h/64769d Inode: 1320701 Links: 1
Access: (0664/-rw-rw-r–) Uid: ( 1003/ yyx) Gid: ( 1003/ yyx)
Access: 2022-05-24 02:38:07.988811151 +0800 # Access Time
Modify: 2022-05-24 02:38:07.988811151 +0800 # Modify Time
Change: 2022-05-24 02:38:07.988811151 +0800 # Change Time
Birth: -




| 时间 | 解释 |
| --- | --- |
| **Access Time** | 文件被**访问**的最近时间 |
| **Modify Time** | 文件**内容**被修改的最近时间 |
| **Change Time** | 文件**属性**被修改的最近时间 |


![在这里插入图片描述](https://img-blog.csdnimg.cn/ae5dfd8283784e8ea8b2408fbd305f8c.png#pic_center)


`Access Time`本应是最常改动的时间,所以系统为防止刷盘,该时间由系统定时刷新。


此外,Makefile 选择性编译源文件,就是根据源文件 Modify Time 是否新于可执行文件的 Modify Time。


 


### 3. 动静态库


#### 3.1 动静态库的定义


一般语言都会提供库,库可以看成一套头文件和一套库文件的集合。库用来给开发者提供一些基础的功能,可以提高开发效率。也可以保证代码安全。


一般库分两种:静态库和动态库。Linux下静态库文件的后缀为`.a`,动态库文件的后缀为`.so`。



$ ldd a.out # 查看可执行程序所依赖的动态库
linux-vdso.so.1 (0x00007ffeaadef000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa174091000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa174298000)
$ ll /usr/lib32/libc.so.6
lrwxrwxrwx 1 root root 12 Apr 7 2022 /usr/lib32/libc.so.6 -> libc-2.31.so
$ ll /usr/lib32/libc-2.31.so
-rwxr-xr-x 1 root root 2004160 Apr 7 2022 /usr/lib32/libc-2.31.so


* 库的文件命名:`libXXXX.so.xx`或`libXXXX.a.xx`。
* 库的真实命名:去掉前缀`lib`,去掉后缀和版本号`.so.xx`或`.a.xx`,剩下的就是真实命名。



> 
> 云服务器默认不安装c标准静态库。
> 
> 
> 
> ```
> $ sudo yum install -y glibc-static libstdc++-static
> 
> ```
> 
> 


#### 3.2 动静态库的生成


##### 静态库的生成


1. 先将所有`.c`源文件编译成`.o`目标文件,
2. 将所有的`.o`文件打包形成一个库文件。这就是静态库的本质。



$ ar -rc libXXX.a XXX1.o XXX2.o # ar 打包静态库命令 -rc replace & create



$ ar -tv libXXX.a # 查看静态库打包的.o目标文件
rw-rw-r-- 1003/1003 1240 May 24 18:02 2022 add.o
rw-rw-r-- 1003/1003 1240 May 24 18:02 2022 sub.o


##### 动态库的生成


1. `gcc -fPIC -c *.c`:首先形成与位置无关码
2. `gcc -shared -o libXX.so *.o`:将目标文件打包成动态库



libmath.so : add.o sub.o
gcc -shared -o $@ $^ # -shared 共享库也就是动态库
%.o : src/%.c
gcc -fPIC -c $< # position ignore code 与位置无关码


##### 库的使用


链接指定的库文件,需要指定头文件位置、库文件位置、库文件名称。



$ gcc test.c -Iinc -Llib -lmath [-static]


1. `-I`:指明头文件所在路径
2. `-L`:指明库文件所在路径
3. `-l`:指明库文件的真实名称,注意是去掉前后缀的真实名称
4. 如果库目录中动静态库都有,优先使用动态库,想使用静态库可以加选项`-static`。
	* 加上`-static`选项会生成纯静态链接程序。
	* 不加但路径下只有静态库,会生成半动半静链接程序。该库采用静态链接,但其他库默认动态链接。



> 
> 系统库文件在系统的默认路径下,头文件是在`usr/include`,库文件在`/lib64`中。编译器能够自动识别。
> 
> 
> 



mytest : mytest.c
gcc -o $@ $^ -Iinc -Llib -lmath


由于动态库是运行时链接,运行程序时,系统加载器默认只会加载系统默认库的路径。所以我们需要告诉加载器依赖库的路径,将库路径放入环境变量`LD_LIBRARY_PATH`。


![在这里插入图片描述](https://img-blog.csdnimg.cn/b8309f33000242dea79083967c655530.png#pic_center)


可以将该环境变量的导入放到`bashrc`中,或者放到系统级动态链接库地址配置目录`/etc/ld.so.conf.d`下并执行`ldconfig`。



bin=bin
src=src
libsrc=libsrc
lib=lib
obj=obj
sbin= ( b i n ) / s m a i n d b i n = (bin)/smain dbin= (bin)/smaindbin=(bin)/dmain
target_bin=$(sbin) ( d b i n ) t a r g e t l i b = (dbin) target_lib= (dbin)targetlib=(lib)/libmath.a
target_shared_lib= ( l i b ) / l i b m a t h . s o t a r g e t o b j = (lib)/libmath.so target_obj= (lib)/libmath.sotargetobj=(obj)/add.o ( o b j ) / s u b . o t a r g e t p i c o b j = (obj)/sub.o target_pic_obj= (obj)/sub.otargetpicobj=(obj)/pic_add.o $(obj)/pic_sub.o

all: $(target_obj) $(target_pic_obj) $(target_lib) $(target_shared_lib) $(target_bin)

( o b j ) / (obj)/%.o: (obj)/(libsrc)/%.c
gcc -o $@ -c $<
( t a r g e t l i b ) : (target_lib): (targetlib):(target_obj)
ar -o $@ $^ -rc
KaTeX parse error: Expected group after '_' at position 10: (obj)/pic_̲%.o:(libsrc)/%.c
gcc -o $@ -c $< -fPIC
( t a r g e t s h a r e d l i b ) : (target_shared_lib): (targetsharedlib):(target_pic_obj)
gcc -o $@ $^ -shared
( s b i n ) : (sbin): (sbin):(src)/main.c
gcc -o $(sbin) ( s r c ) / m a i n . c − l m a t h − I i n c − L (src)/main.c -lmath -Iinc -L (src)/main.clmathIincL(lib) -static
( d b i n ) : (dbin): (dbin):(src)/main.c
gcc -o $(dbin) ( s r c ) / m a i n . c − l m a t h − I i n c − L (src)/main.c -lmath -Iinc -L (src)/main.clmathIincL(lib)

.PHONY:clean
clean:
rm -rf obj/* lib/* bin/*


#### 3.3 静态链接和动态链接


静动态链接的区别在于链接的时机不一样:


* 静态链接是在链接时就将库文件和源文件链接,放到一块形成可执行程序。
* 采用动态链接的程序,链接时不链接库文件只链接源文件。在程序执行时,由加载器将库的代码和数据映射进进程的地址空间中,执行库代码的动作和本地代码的动作一致。


![在这里插入图片描述](https://img-blog.csdnimg.cn/8267a43a688d44dba331b8748964d79d.png#pic_center)




|  | 缺点 | 优点 |
| --- | --- | --- |
| **静态链接** | 空间浪费严重,更新较为麻烦 | 运行速度相对快一点 |
| **动态链接** | 运行速度相对慢一点 | 避免空间浪费,维护比较方便 |


* 静态链接将整个库文件拷贝至目标文件中,程序文件体积较大。但其具备执行所需的程序,不需要查找其他文件,所以运行速度相对快。
* 链接形成可执行程序之后,若库文件被修改,就需要重新链接。
* 由系统的装载程序加载库,库内容不会像静态链接那样存在多份,而是多个程序共享。更新库后新库会自动加载,库与可执行文件独立,提高了可维护性。
* 因为链接推迟到了程序运行时,所以每次执行程序都需要进行链接。



**先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前在阿里**

**深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/c1863dea8c735340620b5e3ddb3dd5ba.png)
![img](https://img-blog.csdnimg.cn/img_convert/dcc2fcb2da7aa758e783df08b9a08dfd.png)
![img](https://img-blog.csdnimg.cn/img_convert/4457fb5a08c9d2259cc9492a4f4abb42.png)
![img](https://img-blog.csdnimg.cn/img_convert/a324e7657d5a913bbe1ed009eba9a080.png)
![img](https://img-blog.csdnimg.cn/img_convert/3f3fcc1e0c37d7aa622e5d66181ec405.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**




**先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前在阿里**

**深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
[外链图片转存中...(img-Ms1grmT9-1715204005305)]
[外链图片转存中...(img-1yTbqTn4-1715204005305)]
[外链图片转存中...(img-K7c7SBB8-1715204005306)]
[外链图片转存中...(img-6U4irGSh-1715204005306)]
[外链图片转存中...(img-HqXlCk4J-1715204005306)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

  • 23
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值