Linux内核源码
文章平均质量分 88
落尘纷扰
服务于制造业的码农,没怎么写过代码
展开
-
Linux 虚拟文件系统(VFS)介绍
1. 通用文件模型Linux内核支持装载不同的文件系统类型,不同的文件系统有各自管理文件的方式。Linux中标准的文件系统为Ext文件系统族,当然,开发者不能为他们使用的每种文件系统采用不同的文件存取方式,这与操作系统作为一种抽象机制背道而驰。为支持各种文件系统,Linux内核在用户进程(或C标准库)和具体的文件系统之间引入了一个抽象层,该抽象层称之为“虚拟文件系统(VFS)”。VFS一方面提供一...原创 2016-05-27 21:40:20 · 17947 阅读 · 2 评论 -
Linux字符设备驱动
1. Linux设备类型Linux内核中的设备可分为三类:字符设备、块设备和网络设备。 字符设备(Character device):适合面向字符的数据交换,因其数据传输量较低。对这种设备的读写是按字符进行的,而且这些字符是连续地形成一个数据流。他不具备缓冲区,所以对这种设备的读写是实时的,如终端、磁带机、串口、键盘等。 块设备(Block device):是一种具有一定结构的随机存取设备,对这原创 2017-08-27 18:36:35 · 2513 阅读 · 0 评论 -
Linux内核中的kobject和kset介绍
本文会围绕kobject、ktype和kset三个概念进行介绍。kobject在内核中应用最多的就是设备驱动模型————总线、设备、驱动、类的管理都使用了kobject,但是kobject并不只为设备驱动模型服务,它是内核中的通用对象模型,用来为内核中各部分的对象管理提供统一视图,其实现在内核的lib/目录下。原创 2017-09-17 21:28:03 · 8057 阅读 · 1 评论 -
PPPoE收发包过程分析
路由器中的LAN/WAN口都是通过以太网(ether)设备来收发包的,而在WAN口进行了PPPoE拨号后,ifconfig会发现多出一个ppp0,这个设备是干什么用的呢? 实际上,这个设备是内核的ppp模块为方便pppoe等协议收发包用的,有了这个设备,你就可以将路由表改一改,将发往WAN口的数据包从ppp0(而不是eth1)发出去,内核协议栈会按照PPP协议相关的设置将这个包发原创 2017-12-29 23:26:39 · 3547 阅读 · 0 评论 -
Linux协议栈——compare_ether_addr_64bits函数分析
从陈老哥的博文中,获得一种新体验。在学习kernel代码的时候,不仅要注重其内在的流程和架构,也可以多多关注一下代码的实现细节,从小的地方去学习编程之道。今天以一个小函数compare_ether_addr_64bits,作为一个尝试。static inline unsigned compare_ether_addr_64bits(const u8 addr1[6+2],转载 2017-12-29 23:35:28 · 1239 阅读 · 0 评论 -
Linux内存管理 —— 文件系统缓存和匿名页的交换
1. swap的含义在Linux里swap有两个意思: 1. 动词:交换。内存和磁盘的颠簸行为。 2. 名词:硬盘的swap分区。没有文件背景的页面,即匿名页(anonymous page),如堆,栈,数据段等,不是以文件形式存在,因此无法和磁盘文件交换,但可以通过硬盘上划分额外的swap交换分区或使用交换文件进行交换。即上面wap作为名词的意思。Swap分区可以将不活跃的页交换到硬盘...原创 2018-03-06 18:27:22 · 17074 阅读 · 3 评论 -
Linux内存管理 —— DMA和一致性缓存
1. 出现内存不一致的原因CPU写内存的时候有两种方式: 1. write through: CPU直接写内存,不经过cache。 2. write back: CPU只写到cache中。cache的硬件使用LRU算法将cache里面的内容替换到内存。通常是这种方式。DMA可以完成从内存到外设直接进行数据搬移。但DMA不能访问CPU的cache,CPU在读内存的时候,如果cache命中...原创 2018-03-06 18:34:30 · 27723 阅读 · 6 评论 -
Linux内核中的锁
1. 为什么要保证原子性处理器分两种:cisc(复杂指令集,可以直接在内存上进行操作,如x86,一条汇编指令可以原子的完整读内存、计算、写内存)和rics(精简指令集,所有操作都必须是在CPU内部进行。所以你想给内存某个变量做加法,你要先用load指令把内存load到CPU的寄存器、再执行add,再执行store把结果放到内存中)。因此a++这句话在rics上并不是原子的,必须翻译成一个r...原创 2018-03-07 00:05:34 · 6583 阅读 · 0 评论 -
Linux内存管理 —— 为buddy做准备:MMU, TLB, ZONE
本文都是假设系统是32位,页大小为4KB,基于ARM架构(不过和体系结构相关的内容不多)。1. 了解MMU在启用MMU的Linux内核中,CPU是通过虚拟地址来访问物理内存的。MMU(Memory Management Unit),即内存管理单元,它集成在CPU中,负责虚拟地址到物理地址的映射,以及物理地址的访问,并提供内存访问权限检查机制,以达到内存保护的作用(ARM里面的MPU(M...原创 2018-03-06 17:12:32 · 2278 阅读 · 1 评论 -
Linux内存管理 —— 内核态和用户态的内存分配方式
1. 使用buddy系统管理ZONE我的这两篇文章buddy系统和slab分配器已经分析过buddy和slab的原理和源码,因此一些细节不再赘述。所有zone都是通过buddy系统管理的,buddy system由Harry Markowitz在1963年提出。buddy的工作方式我就不说了,简单来说buddy就是用来管理内存的使用情况:一个页被申请了,别人就不能申请了。通过/proc/b...原创 2018-03-06 17:36:04 · 14992 阅读 · 0 评论 -
Linux内存管理 —— 进程的虚拟地址空间和VSS
1. 进程虚拟地址空间进程的虚拟地址空间记录在其task_struct结构的指针成员mm中(struct mm_struct),这是用户态进程才有的,里面包含pgd、代码段、堆、栈地址等信息。(kernel不需要mm,因为kernel不需要引用动态库,内核线程有自己的栈空间,虚拟地址映射关系也是全局可见的,注意vmalloc和kmap产生的映射是由内核中的全局变量swapper_pg_dir和...原创 2018-03-06 17:47:07 · 1521 阅读 · 0 评论 -
Linux内核中的skb_queue_splice_tail_init函数
skb_queue_splice_tail_init()函数用于将链表a连接到链表b上,形成一个新的链表b,并将原来a的头变成空链表。其实现如下:/** * skb_queue_splice_tail - join two skb lists and reinitialise the emptied list * @list: the new list to add * @...原创 2018-04-06 13:26:00 · 1838 阅读 · 0 评论 -
Linux内核中的page migration和compaction机制简介
我们知道buddy容易产生内存碎片,内核中可以通过给页面设置迁移类型以及compaction机制来预防和处理内存碎片。内存页主要有下面三种类型: 1.可移动的(movable)。用户态申请。 2.可回收的(reclaimable)。文件系统的cache。 3.不可移动(unmovable)。内核申请用。可移动的页面,顾名思义就是在被分配之后,还可以改变在物理内存中的位置。只要更新一下...原创 2018-04-06 18:31:55 · 5019 阅读 · 0 评论 -
Linux内核中的内存屏障
编译器有时会对代码做一些优化,例如尝试在保证程序执行正确的前提下修改指令顺序或优化ldr/str指令,让程序执行地更快。但是编译器毕竟不能完全猜透人的心思,有时候它做的优化会导致程序运行不符我们的预期。因此,内核中提供了一些额外的函数,可以插在某段代码里,告诉编译器不要在这里做指令优化。这些函数分为两种:内存屏障:rmb(), wmb(), mb(),可以防止硬件上的指令重排。除了编译器,...原创 2018-04-30 19:07:16 · 4186 阅读 · 0 评论 -
中断下半部机制 - 软中断及tasklet
一个中断处理程序的一个或几个中断服务例程在执行结束之前,内核处于中断环境中,当前CPU不再响应同类型的中断,如果不允许中断嵌套,则CPU需要屏蔽掉所有中断。也就是说,一个CPU忙于服务于一个中断事件时,就不能处理其他中断,同时CPU不能执行其他进程,即不能被抢占,这种情况下,如果在中断服务例程中消耗的时间过多,就会对性能产生潜在的影响。一般情况下,一个中断事件所触发的动作可原创 2015-04-03 22:37:35 · 2760 阅读 · 1 评论 -
Linux协议栈-netfilter(4)-期望连接
传统的conntrack和NAT处理只对IP层和传输层头部进行转换处理,但是一些应用层协议,在协议数据报文中包含了地址信息。为了使得这些应用也能透明地完成NAT转换,NAT使用一种称作ALG的技术,它能对这些应用程序在通信时所包含的地址信息也进行相应的NAT转换。例如:对于FTP协议的PORT/PASV命令,在数据包载荷中需要包含地址信息,并且数据包如果需要做NAT,那应用层数据部分的地址也需原创 2015-04-04 22:18:18 · 5199 阅读 · 0 评论 -
谈谈NAPI机制
1. 引入问题内核收包主要有两种手段:轮询和中断。通过轮询,内核可以不断持续的检查设备时候有包收上来,例如设置一个定时器,定期检查设备上的某个定时器。这种方法会轻易浪费掉很多系统资源。如果采用中断收包,当设备收到包时,可以产生一个硬件中断通知内核,内核将中断其他活动,然后调用一个中断处理程序以满足设备的需求,内核只是将数据包放到某个队列中并通知内核中的收包模块。这种方式是非常常见的,在低流量负载下...原创 2015-03-04 22:11:27 · 4487 阅读 · 0 评论 -
Kernel编译和链接中的linker script语法详解
先要讲讲这个问题是怎么来的。(咱们在分析一个技术的时候,先要考虑它是想解决什么问题,或者学习新知识的时候,要清楚这个知识的目的是什么)。我在编译内核的时候,发现arch/arm/kernel目录下有一个这样的文件:vmlinux.lds.S。第一眼看上去,想想是不是汇编文件呢?打开一看,好像不是。那它是干嘛的?而且前面已经说过,make V=1的时候,发现这个文件的用处在ld命令中,即ld转载 2015-03-09 21:25:33 · 1880 阅读 · 0 评论 -
Linux内存管理(1) - bootmem分配器
内核中分配内存基本都基于伙伴系统,但是在内核启动之初,伙伴系统尚未建立,这时需要一个临时的内存分配器负责提供内核早期的内存需求,例如存放内核的代码段和数据段,以及将内存进行简单的管理供后续伙伴系统使用,这就是bootmem分配器。本文基于Linux 2.6.31的内核源码对bootmem分配器的工作过程进行分析。原创 2015-03-01 23:20:42 · 1999 阅读 · 0 评论 -
MIPS中的异常处理和系统调用
本文介绍mips体系结构中异常处理机制,并详细分析了系统调用异常的实现。原创 2015-03-03 21:40:29 · 9006 阅读 · 0 评论 -
Linux内存管理(4) - 不连续页的分配vmalloc
本文目的在于分析Linux内核中的vmalloc函数。内核版本为2.6.31。我们知道物理上连续的映射对内核是最好的,但不是总能成功。在分配一大块内存时,可能无法找到连续的内存块。在用户空间这不是问题,因为普通进程设计为使用处理器的分页机制,当然这会降低速度并占用TLB。在内核中也可以使用同样的技术,典型的例子为vmalloc()。vmalloc是一个接口函数,内核代码用它来分配在虚拟原创 2015-03-02 21:22:31 · 3021 阅读 · 2 评论 -
Linux内存管理(2) - buddy系统
本文目的在于分析Linux内存管理机制中的伙伴系统。内核版本为2.6.31。1. 伙伴系统的概念在系统运行过程中,经常需要分配一组连续的页,而频繁的申请和释放内存页会导致内存中散布着许多不连续的页,这样,当某一时刻要申请一块较大的连续内存时,虽然系统内存余量足够,即很多页是空闲的,但找不到一大块连续的内存供使用。Linux内核中使用伙伴系统(buddy system)算法来管理内存页。它把所有的空...原创 2015-03-02 20:54:17 · 6084 阅读 · 0 评论 -
Linux内存管理(3) - slab分配器和kmalloc
本文目的在于分析Linux内存管理机制的slab分配器。内核版本为2.6.31。1. SLAB分配器内核需要经常分配内存,我们在内核中最常用的分配内存的方式就是kmalloc了。前面讲过的伙伴系统只支持按页分配内存,但这个单位太大了,有时候我们并不需要这么大的内存,比如我想申请128字节的空间,如果直接使用伙伴系统则需分配4KB的一整页,这显然是浪费。slab分配器将页拆分为更小原创 2015-03-02 21:04:46 · 4985 阅读 · 0 评论 -
内核中dump_stack()的实现,并在用户态模拟dump_stack()
本文介绍linux内核中dump_stack()函数的工作原理,并据此实现了用户态的栈回溯的方法,实现的代码基于mips体系结构。原创 2015-03-04 21:50:51 · 6376 阅读 · 1 评论 -
Linux协议栈-netfilter(2)-conntrack
连接跟踪(conntrack)用来跟踪和记录一个连接的状态,它为经过协议栈的数据包记录状态,这为防火墙检测连接状态提供了参考,同时在数据包需要做NAT时也为转换工作提供便利。本文基于Linux内核2.6.31实现的conntrack进行源码分析。1. conntrack模块初始化1.1 conntrack模块入口conntrack模块的初始化主要就是为必要的全局数据结构进行初始化,代码流程如下:上...原创 2015-04-04 17:37:40 · 19558 阅读 · 2 评论 -
Linux协议栈-netfilter(3)-NAT
本文对netfilter中NAT部分的源码进行分析,读者需要先对NAT的基本概念有一个大致了解。1. NAT模块的初始化NAT模块的初始化过程主要是初始化一些全局变量以及注册NAT相关的hook函数。在下面nf_nat_init()函数和nf_nat_standalone_init()函数的流程图中用红色标记了要初始化的全局数据结构。nf_nat_init()函数:nf_nat_standalon...原创 2015-04-04 18:45:22 · 3558 阅读 · 2 评论 -
Linux协议栈-netfilter(1)-框架
1. netfilter框架Netfilter 是内核中进行数据包过滤,连接跟踪,地址转换等的主要实现框架。当我们希望过滤特定的数据包或者需要修改特定数据包的某些内容再发送出去,这些动作主要都在netfilter中完成。iptables工具就是用户空间和内核的Netfilter模块通信的手段,iptables命令提供很多选项来实现过滤数据包的各种操作,后面会讲到iptables命令如何原创 2015-04-04 14:52:30 · 16313 阅读 · 3 评论 -
Linux协议栈-netfilter(5)-iptables
iptables是用户态的配置工具,用于实现网络层的防火墙,用户可以通过iptables命令设置一系列的过滤规则,来截获特定的数据包并进行过滤或其他处理。iptables命令通过与内核中的netfilter交互来起作用。我们知道netfilter通过挂在每个hook点上的hook函数来过滤数据包,并且将过滤规则存放在几个表中供hook函数使用。相应的,iptables工具也定义了同样的几张规则原创 2015-04-04 22:36:15 · 5020 阅读 · 0 评论 -
Linux的中断处理分析
MIPS中,中断被当作一种异常(第0号异常)来处理。中断由外部设备产生,可能发生在任何时刻,每个中断都有一个编号分配给一个外部设备,这样来区分不同设备产生的中断,如果硬件和内核支持共享中断,则可以由多个设备共享一个中断编号。 在CPU得知中断发生后,它将进一步的处理委托给一个软件例程,这个软件例程是体系结构相关的,然后根据中断号来识别中断源,并进入特定的中断处理程序来处理该中断。原创 2015-04-02 23:00:39 · 2328 阅读 · 0 评论 -
linux内核中的likely()和unlikely()宏的作用
在看linux内核代码的时候,经常会看到likely(x)和unlikely(x)宏的使用。那这两个宏有什么作用呢?这两个宏在内核中的定义如下:# define likely(x) __builtin_expect(!!(x), 1)# define unlikely(x) __builtin_expect(!!(x), 0)可见这里使用了gcc的内建函数__builtin_exp原创 2015-04-10 00:16:17 · 19379 阅读 · 0 评论 -
linux内核中打印栈回溯信息 - dump_stack()函数分析
当内核出现比较严重的错误时,例如发生Oops错误或者内核认为系统运行状态异常,内核就会打印出当前进程的栈回溯信息,其中包含当前执行代码的位置以及相邻的指令、产生错误的原因、关键寄存器的值以及函数调用关系等信息,这些信息对于调试内核错误非常有用。原创 2015-05-08 21:19:32 · 28476 阅读 · 0 评论 -
内核符号表的生成和查找过程
Linux内核中的函数名、全局变量等,都保存在一个全局的符号表中,本文介绍内核符号表的生成及查找过程。原创 2015-03-02 22:40:55 · 8738 阅读 · 0 评论 -
Linux内核中负责回写脏页的线程
内核版本 3.0 和 3.4.35 (不同内核版本的回写机制不同哦~)Linux内核里负责回写脏页的线程称为flusher线程,它们以“flush-”+“设备名”来命名,例如”[flush-8:64]”(这里设备名是指用设备号拼接的字符串)。在BDI(即backing device info)模块初始化(default_bdi_init())时会创建”[sync_supers]”和”[bd...原创 2018-05-08 23:25:04 · 2281 阅读 · 0 评论