1.Linux内核源码解析---万字解析从设计模式推演per-cpu实现原理
2.详解Linux系统中inode索引节点已满问题的源引解决方法
3.如何克隆Linux内核git库到Win11电脑上(一)
4.apt-sortpkgs命令如何根据源索引字段排序软件包索引文件?
5.Linux虚拟文件系统中索引节点的结构及其作用是什么
6.解析LinuxSS源码探索一探究竟linuxss源码
Linux内核源码解析---万字解析从设计模式推演per-cpu实现原理
引子
在如今的大型服务器中,NUMA架构扮演着关键角色。码索它允许系统拥有多个物理CPU,源引不同NUMA节点之间通过QPI通信。码索虽然硬件连接细节在此不作深入讨论,源引但需明白每个CPU优先访问本节点内存,码索openform源码当本地内存不足时,源引可向其他节点申请。码索从传统的源引SMP架构转向NUMA架构,主要是码索为了解决随着CPU数量增多而带来的总线压力问题。
分配物理内存时,源引numa_node_id() 方法用于查询当前CPU所在的码索NUMA节点。频繁的源引内存申请操作促使Linux内核采用per-cpu实现,将CPU访问的码索变量复制到每个CPU中,以减少缓存行竞争和False Sharing,源引类似于Java中的Thread Local。
分配物理页
尽管我们不必关注底层实现,buddy system负责分配物理页,关键在于使用了numa_node_id方法。接下来,我们将深入探索整个Linux内核的per-cpu体系。
numa_node_id源码分析获取数据
在topology.h中,我们发现使用了raw_cpu_read函数,传入了numa_node参数。接下来,我们来了解numa_node的定义。
在topology.h中定义了numa_node。我们继续跟踪DECLARE_PER_CPU_SECTION的定义,最终揭示numa_node是一个共享全局变量,类型为int,存储在.data..percpu段中。
在percpu-defs.h中,numa_node被放置在ELF文件的.data..percpu段中,这些段在运行阶段即为段。接下来,我们返回raw_cpu_read方法。
在percpu-defs.h中,我们继续跟进__pcpu_size_call_return方法,此方法根据per-cpu变量的大小生成回调函数。对于numa_node的int类型,最终拼接得到的是raw_cpu_read_4方法。
在percpu.h中,调用了一般的read方法。在percpu.h中,获取numa_node的绝对地址,并通过raw_cpu_ptr方法。
在percpu-defs.h中,我们略过验证指针的怎么强制查看源码环节,追踪arch_raw_cpu_ptr方法。接下来,我们来看x架构的实现。
在percpu.h中,使用汇编获取this_cpu_off的地址,代表此CPU内存副本到".data..percpu"的偏移量。加上numa_node相对于原始内存副本的偏移量,最终通过解引用获得真正内存地址内的值。
对于其他架构,实现方式相似,通过获取自己CPU的偏移量,最终通过相对偏移得到pcp变量的地址。
放入数据
讨论Linux内核启动过程时,我们不得不关注per-cpu的值是如何被放入的。
在main.c中,我们以x实现为例进行分析。通过setup_percpu.c文件中的代码,我们将node值赋给每个CPU的numa_node地址处。具体计算方法通过early_cpu_to_node实现,此处不作展开。
在percpu-defs.h中,我们来看看如何获取每个CPU的numa_node地址,最终还是通过简单的偏移获取。需要注意如何获取每个CPU的副本偏移地址。
在percpu.h中,我们发现一个关键数组__per_cpu_offset,其中保存了每个CPU副本的偏移值,通过CPU的索引来查找。
接下来,我们来设计PER CPU模块。
设计一个全面的PER CPU架构,它支持UMA或NUMA架构。我们设计了一个包含NUMA节点的结构体,内部管理所有CPU。为每个CPU创建副本,其中存储所有per-cpu变量。静态数据在编译时放入原始数据段,动态数据在运行时生成。
最后,我们回到setup_per_cpu_areas方法的分析。在setup_percpu.c中,我们详细探讨了关键方法pcpu_embed_first_chunk。此方法管理group、unit、静态、保留、动态区域。精品源码分享网站
通过percpu.c中的关键变量__per_cpu_load和vmlinux.lds.S的链接脚本,我们了解了per-cpu加载时的地址符号。PERCPU_INPUT宏定义了静态原始数据的起始和结束符号。
接下来,我们关注如何分配per-cpu元数据信息pcpu_alloc_info。percpu.c中的方法执行后,元数据分配如下图所示。
接着,我们分析pcpu_alloc_alloc_info的方法,完成元数据分配。
在pcpu_setup_first_chunk方法中,我们看到分配的smap和dmap在后期将通过slab再次分配。
在main.c的mm_init中,我们关注重点区域,完成map数组的slab分配。
至此,我们探讨了Linux内核中per-cpu实现的原理,从设计到源码分析,全面展现了这一关键机制在现代服务器架构中的作用。
详解Linux系统中inode索引节点已满问题的解决方法
今天login server的一个网站,发现login后没有生成session。根据以往经验,一般是空间已满导致session文件生成失败。
代码如下:
df -h
代码如下:
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/dev-root G G G % /
udev 2.0G 4.0K 2.0G 1% /dev
tmpfs M K M 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 2.0G 4.0K 2.0G 1% /run/shm
/dev/sda1 M M M % /boot
空间剩余G,可以排除空间已满的情况。导致文件生成失败还有另一个原因,就是文件索引节点inode已满。
代码如下:
df -i
代码如下:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/dev-root 0 % /
udev 1% /dev
tmpfs 1% /run
none 5 1% /run/lock
none 2 1% /run/shm
/dev/sda1 1% /boot
inodes 占用%,果然是这个问题。
解决方法:删除无用的临时文件,释放inode。
查找发现 /tmp 目录下有很多sess_xxxxx的 session临时文件。
代码如下:
ls -lt /tmp | wc -l
进入/tmp目录,执行find -exec命令
代码如下:
sudo find /tmp -type f -exec rm { } ;
如果使用rm *,有可能因为文件数量太多而出现Argument list too long错误。除了/tmp的临时文件外,0字节的文件也会占用inode,应该也释放。
遍历寻找0字节的文件,并删除。
代码如下:
sudo find /home -type f -size 0 -exec rm { } ;
删除后,inode 的使用量减少为%,可以正常使用了。
代码如下:
df -i
代码如下:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/dev-root % /
udev 1% /dev
tmpfs 1% /run
none 5 1% /run/lock
none 2 1% /run/shm
/dev/sda1 1% /boot
PS:什么是inode
linux中,文件查找不是通过文件名称来查找的。实际上是通过inode来实现文件的查找定位的。我们可以形象的乐娱系统源码将inode看做是一个指针fip。当文件存储到磁盘上去的时候,文件肯定会存放到一个磁盘位置上,可以这样想象,既然文件数据是存放在磁盘上的,如果我们知道这个文件数据的地址,当我们想要读写文件的时候,我们是不是直接使用这个地址去找到文件就可以了呢?
是的,linux下,inode其实就是可以这么认为,把inode看作是一个指向磁盘上该文件存储区的地址。只不过这个地址我们一般是没办法直接使用的,而是通过文件名来间接使用的。事实上,inode不仅包含了文件数据存储区的地址,还包含了很多信息,比如数据大小,等等文件信息。但是inode是不保存文件名的。文件名是保存在一个目录项中。每一个目录项中都包含了文件名和inode。
我们可以通过一个图来看看目录项,inode,文件数据四者之间的关系。
从上图可以看到,目录项中包含了文件名和inode。
如何克隆Linux内核git库到Win电脑上(一)
假设我们没有使用虚拟机,不开启WSL,没有安装ext4驱动和ext4文件系统,仅仅有一个单纯的NTFS分区,只想将Linux内核源码代码下载到本地进行学习。在进行这一操作前,我们需要找到Linux内核源码的git库。Linux内核官方网站是 kernel.org。在这个网站上,Linus Torvalds维护的内核库是主要的资源。不过,由于git服务器位于国外,如新加坡,国内发起的下载网速可能非常慢。为了解决这一问题,我们可以选择使用国内类似github的网站gitee。gitee提供了Linux内核代码的镜像下载,其git库地址为 /mirrors/linux_old1.git。这个镜像库的名字是 /mirrors/linux_old1.git,其与Linus Torvalds在github上托管的库 /torvalds/linux 相关联。gitee每天会自动从github上同步一次,这个频率对于大多数用户已经足够。修改labelme源码套索
下一步是安装git工具,以及下载git库。有许多支持git的工具,比如从 pc.qq.com 下载的Git(带图形界面,也支持命令行),或者TortoiseGit(一系列软件版本管理工具之一),都是不错的选择。通过gitee下载Linux kernel库的命令如下:
在gitee上下载速度快到令人发指,很快就能看到结算界面。然而,下载完成后,我们可能无法进行checkout操作,导致在 /mirrors/linux_old1/ 目录下看不到任何文件。
为了解决checkout问题,我们需要调整Windows系统默认不允许使用诸如 "aux" 这样的设备名字作为普通文件名的规则。调整方法如下:
在完成这一系列操作后,git开始进行checkout文件的输出,尽管有一些警告信息,但最终出现%和Done,表示checkout操作完成。在 /mirrors/linux_old1/ 目录下,我们可以看到完整的Linux内核代码的目录结构,非常完美。
然而,在实际操作中,我们可能会遇到一个图像表示的问题,其中猩红的字体提示checkout过程中闪过的警告信息。使用git diff查看后,我们发现文件存在差异。接下来,我们需要解决这个问题。
首先,我们怀疑git软件可能存在bug,但考虑到git是Linus Torvalds亲自编写,且全球用户都在使用,这个问题不太可能出现在git本身。因此,我们尝试检查自己是否在命令中输入了错误。实际上,问题出在Windows系统上。由于Windows系统不区分文件名的大小写,当创建文件时,即使使用大写字母,文件系统也会将它们转换为小写。因此,即使我们在NTFS文件系统上创建的文件名使用了大写,文件系统在进行文件名比较时也会转换为小写。
在gitee.com/mirrors/linux_old1/.../查看原始目录结构时,我们发现目录下存在名为"xt_CONNMARK.h"和"xt_connmark.h"的两个文件,而我们的硬盘上只有一个名为"xt_CONNMARK.h"的文件。因此,git在尝试checkout文件时,发现文件名不匹配。
解决这个问题的方法是使用自带的fsutil工具,将指定目录的属性设置为区分大小写。这样做后,我们可以在同一目录下同时存在大写和小写的文件名。使用标准命令进行操作后,git开始checkout文件,但NTFS系统再次阻止我们更改目录属性。网络上关于fsutil工具的文章中,很少有人提到这个问题,也没有人提供解决方案。
解决这个问题的方法是先创建一个空目录,然后再尝试更改其属性。当目录为空时,fsutil工具可以更改目录的属性,之后我们可以让git还原目录下的所有文件。通过使用此命令,我们成功解决了问题。
接下来,我们解决的是git在NTFS文件系统上创建git库时将参数core.ignoreCase设置为true的问题。由于Linux kernel的netfilter子系统在处理文件时引入了一些错误,因此即使底层NTFS系统已经设置为区分大小写,我们还需要在上层的git软件配置中相应地进行更改。
在解决了一系列问题后,我们最终可以顺利将Linux内核代码从gitee下载到本地。接下来,我们将继续讨论如何在Linux下生成交叉索引,以解决后续可能遇到的问题。
apt-sortpkgs命令如何根据源索引字段排序软件包索引文件?
在Debian Linux环境中,apt-sortpkgs命令是一种实用的工具,专门用于整理和排序软件包索引文件。这个命令的核心功能是接收索引文件(如源索引或包索引),然后根据内置的排序规则对文件中的记录进行有序排列。它的使用方法相对直观,主要包括几个参数选项:使用 -c 参数指定要使用的配置文件,以便定制排序行为。
通过 -s 参数,可以直接根据源索引字段进行排序,这对于快速定位特定软件包非常有用。
另外,-o 参数允许你设置配置选项,以满足个性化的排序需求。
如果需要获取帮助信息,只需输入 -h,命令便会提供详细的使用指导。
以下是几个具体的使用实例:要对Packages文件进行普通排序,可以在终端输入 [root@linuxcool ~]# apt-sortpkgs Packages。
如果想依据配置文件进行操作,可以使用 [root@linuxcool ~]# apt-sortpkgs -c Packages。
要按照源索引字段排序,输入 [root@linuxcool ~]# apt-sortpkgs -s Packages,即可看到文件按指定字段排列的结果。
总的来说,apt-sortpkgs命令为管理和优化Debian Linux系统的软件包索引提供了一种方便快捷的方式,使得管理变得更为有序和高效。Linux虚拟文件系统中索引节点的结构及其作用是什么
索引节点是UNIX文件系统的一个重要部分. 通常用户不用考虑它们,但知道它们是什么确实很有必要.
索引节点是磁盘上用于描述文件的一种数据结构. 它保存了文件的大部分重要信息,包括文件数据块(用户关心的文件部分)在磁盘上的地址. 每个索引节点都有自己的标识号, 称为索引号(i-number). 实际上用户根本不需要关心文件在磁盘上的物理地址, 也不用关心索引号----除非是要找出对文件的链接. 但用户关心下列信息, 而它们都被保存在文件的索引节点中:
文件所有权: 拥有文件的用户和组
文件访问模式: 不同的用户和组是否可以读, 写或执行文件.
文件时间标记: 文件最后一次被修改的时间, 最后被访问的时间和索引节点最后被修改的时间.
文件类型: 是否为常规文件, 特殊文件或者其他类型的抽象伪装文件.
文件系统第一次被创建时(通常是磁盘第一次初始化时), 会为每一个文件系统创建若干数量的索引节点. 该数目是文件系统所能容纳的最大文件数. 只要不重新初始化文件系统, 就不能改变这个数目, 否则会损坏该文件系统上所有的数据. 很有可能(虽然很少见)文件系统会将索引节点全部用光,就像有可能用完存储空间一样----当文件系统中有很多很多小文件时,这种情况就可能发生.
使用ls –l命令会显示出在大部分信息. ls –i option显示文件的索引号. 而stat命令则可以列出索引节点中的几乎所有信息.
解析LinuxSS源码探索一探究竟linuxss源码
被誉为“全球最复杂开源项目”的Linux SS(Secure Socket)是一款轻量级的网络代理工具,它在Linux系统上非常受欢迎,也成为了大多数网络应用的首选。Linux SS的源码的代码量相当庞大,也备受广大开发者的关注,潜心钻研Linux SS源码对于网络研究者和黑客们来说是非常有必要的。
我们以Linux 3. 内核的SS源码为例来分析,Linux SS的源码目录位于linux/net/ipv4/netfilter/目录下,在该目录下包含了Linux SS的主要代码,我们可以先查看其中的主要头文件,比如说:
include/linux/netfilter/ipset/ip_set.h
include/linux/netfilter_ipv4/ip_tables.h
include/linux/netfilter/x_tables.h
这三个头文件是Linux SS系统的核心结构之一。
接下来,我们还要解析两个核心函数:iptables_init函数和iptables_register_table函数,这两个函数的主要作用是初始化网络过滤框架和注册网络过滤表。iptables_init函数主要用于初始化网络过滤框架,主要完成如下功能:
1. 调用xtables_init函数,初始化Xtables模型;
2. 调用ip_tables_init函数,初始化IPTables模型;
3. 调用nftables_init函数,初始化Nftables模型;
4. 调用ipset_init函数,初始化IPset模型。
而iptables_register_table函数主要用于注册网络过滤表,主要完成如下功能:
1. 根据提供的参数检查表的有效性;
2. 创建一个新的数据结构xt_table;
3. 将该表注册到ipt_tables数据结构中;
4. 将表名及对应的表结构存放到xt_tableshash数据结构中;
5. 更新表的索引号。
到这里,我们就大致可以了解Linux SS的源码,但Learning Linux SS源码只是静态分析,细节的分析还需要真正的运行环境,观察每个函数的实际执行,而真正运行起来的Linux SS,是与系统内核非常紧密结合的,比如:
1. 调用内核函数IPv6_build_route_tables_sockopt,构建SS的路由表;
2. 调用内核内存管理系统,比如kmalloc、vmalloc等,分配SS所需的内存;
3. 初始化Linux SS的配置参数;
4. 调用内核模块管理机制,加载Linux SS相关的内核模块;
5. 调用内核功能接口,比如netfilter, nf_conntrack, nf_hook等,通过它们来执行对应的网络功能。
通过上述深入了解Linux SS源码,我们可以迅速把握Linux SS的构架和实现,也能熟悉Linux SS的具体运行流程。Linux SS的深层原理揭示出它未来的发展趋势,我们也可以根据Linux SS的现有架构改善Linux的网络安全机制,进一步开发出与Linux SS和系统内核更加融合的高级网络功能。
实例讲解Linux系统中硬链接与软链接的创建
首先要弄清楚,在Linux系统中,内核为每一个新创建的文件分配一个Inode(索引结点),每个文件都有一个惟一的inode号。文件属性保存在索引结点里,在访问文件时,索引结点被复制到内存在,从而实现文件的快速访问。链接是一种在共享文件和访问它的用户的若干目录项之间建立联系的一种方法。Linux中包括两种链接:硬链接(Hard Link)和软链接(Soft Link),软链接又称为符号链接(Symbolic link)。
一、硬链接
硬链接说白了是一个指针,指向文件索引节点,系统并不为它重新分配inode。可以用:ln命令来建立硬链接。语法:
复制代码
代码如下:
ln [options] existingfile newfileln[options] existingfile-list directory
用法: 第一种:为existingfile创建硬链接,文件名为newfile。第二种:在directory目录中,为 existingfile-list中包含的所有文件创建一个同名的硬链接。常用可选[options] f 无论newfile存在与否,都创建链接。-n 如果newfile已存在,就不创建链接。
下面举一些例子:
复制代码
代码如下:
$ ls il-rwx - - - - - - 1 longcheng longcheng 8月 5 : file1
-rwx - - - - - - 1 longcheng longcheng 8月 5 : file2
复制代码
代码如下:
$ ln file2 file2hard$ ls il
-rwx - - - - - - 1 longcheng longcheng 8月 5 : file1
-rwx - - - - - - 2 longcheng longcheng 8月 5 : file2
-rwx - - - - - - 2 longcheng longcheng 8月 5 : file2hard
注意在创建链接前,file1 显示的链接数目为1,创建链接后(1)file1和file1hard的链接数目都变为2;(2) file1和file1hard在inode号是一样的(3) file1和file1hard显示的文件大小也是一样。可见进行了ln命令的操作结果:file1和file1hard是同一个文件的两个名字,它们具 有同样的索引节点号和文件属性,建立文件file1的硬链接,就是为file1的文件索引节点在当前目录上建立一个新指针。
链接数同时减一,只有将所有指向文件内容的指针,也即链接数减为0时,内核才会把文件内容从磁盘上删除。当前目录逻辑结构:(不好意思图没有显示出来)。
还可以在不同目录,但同一文件系统中建立文件的硬链接。设file1、file2在目录/home/longcheng/dir1中,下面的命令,在/home/longcheng中建立file2的硬链接。
复制代码
代码如下:
ln file2 /home/longcheng/file2hard下面的程序,是将dir1目录中所有文件,在目录dir2中建立硬链接
复制代码
代码如下:
$mkdir dir2$ln /home/longcheng/dir1/* /home/longcheng/dir2
如果使用了 ln f existingfile newfile,如果newfile已经存在,则无论原来newfile是什么文件,只用当前用户对它有写权限,newfile就成为exisitngfile的硬链接文件。
尽管硬链接节省空间,也是Linux系统整合文件系统的传统方式,但是存在一下不足之处:
(1)不可以在不同文件系统的文件间建立链接
(2)只有超级用户才可以为目录创建硬链接。虽然很多树上说root用户可以创建,但是笔者在学习过程中发现即使是root用户也不能创建,我的系统是Redhat,内核2.4、2.6都试过,在其他系统中不知道是不是可以。
二、软链接(符号链接)
软链接克服了硬链接的不足,没有任何文件系统的限制,任何用户可以创建指向目录的符号链接。因而现在更为广泛使用,它具有更大的灵活性,甚至可以跨越不同机器、不同网络对文件进行链接。
建立软链接,只要在ln后面加上选项 s,下面举个例子
复制代码
代码如下:
$ ls -il-rwx - - - - - - 1 longcheng longcheng 8月 5 : file1
-rwx - - - - - - 2 longcheng longcheng 8月 5 : file2
-rwx - - - - - - 2 longcheng longcheng 8月 5 : file2hard
复制代码
代码如下:
$ln s file1 file1soft$ls -il
-rwx - - - - - - 1 longcheng longcheng 8月 5 : file1
-rwx - - - - - - 2 longcheng longcheng 8月 5 : file2
-rwx - - - - - - 2 longcheng longcheng 8月 5 : file2hard
lrwxrwxrwx 1 longcheng longcheng 5 8月 5 : file1soft-file1
从上面链接后的结果可以看出来软链接与硬链接,区别不仅仅是在概念上,在实现上也是不同的。区别:硬链接原文件在文件属性上软链接明确写出了是链接文件,而硬链接没有写 出来,因为在本质上硬链接文件和原文件是完全平等关系;链接数目是不一样的,软链接的链接数目不会增加;文件大小是不一样的,硬链接文件显示的大小是跟原 文件是一样的,这用强调,因为是等同的嘛,而这里软链接显示的大小与原文件就不同了,file1大小是B,而file1soft是5B,这里面的5实 际上就是file1的大小。
总之,建立软链接就是建立了一个新文件。当访问链接文件时,系统就会发现他是个链接文件,它读取链接文件找到真正要访问的文件。
在不同系统之间建立软链接、对目录建立链接,这里就不举例了,读者可以自己去尝试,我也是在不断实践中学习的。
当然软链接也有硬链接没有的缺点,因为链接文件包含有原文件的路径信息,所以当原文件从一个目录下移到其他目录中,再访问链接文件,系统就找不到 了~~,而硬链接就没有这个缺陷,你想怎么移就怎么移(呵呵);还有它要系统分配额外的空间用于建立新的索引节点和保存原文件的路径。
补充一下:可以通过symlink来查看链接文件,可以用 man symlink来学习。
开启Linux之旅使用国内源加速体验linux国内源
开启Linux之旅:使用国内源加速体验
拥有Linux系统的计算机,不管是个人电脑,还是网络服务器,它们都与其他的系统有着根本的不同,它们可以安全地运行各种应用程序,提供可靠性和性能,并对现有网络架构提供非常有用的增强功能。 Linux也是一个可定制且开放源代码的操作系统,这使得Linux开发者有机会在系统中使用世界上最新的技术。
使用Linux系统时,最重要的事情之一是配置Linux源,因此我们可以从此源下载并安装应用程序和系统补丁。 用户可以从官方源中使用新组件,也可以安装任何第三方软件,以增强他们的Linux体验。 如果用户的Linux系统位于中国,那么下载过程就可能很缓慢,因为有时这些源位于海外服务器。
这时,我们可以使用国内源来加速Linux下载,使我们可以更快更安全地安装并使用新的应用程序和组件。 国内源也非常有用,因为它们减少了网络上的流量和延迟,从而提高了使用体验。
配置国内源的方法非常简单。 对于Ubuntu和Debian,可以使用下面的命令打开源配置文件:
sudo vim /etc/apt/sources.list
接下来,将以下内容添加到文件的末尾:
deb [由于某些原因,这里省略源内容]
完成后更新本地包索引:
sudo apt update
完成这些步骤后,我们就可以使用国内源下载最新的软件包和补丁,以便我们可以更快地更新我们的Linux系统。
以上就是在Linux上使用国内源来加速Linux体验的简要说明。 它有助于缓解网络联接延迟和提高带宽,从而使我们的Linux体验变得更好。