发布时间:2015-01-15 15:47:33
kernel 3.10内核源码分析--中断--中断和异常返回流程
一、问题
1、内核调度与中断/异常/系统调用的关系如何?
2、信号处理与中断/异常/系统调用的关系如何?
3、内核抢占与中断/异常/系统调用的关系如何?
这些问题都需要分析清楚中断/异常的返回流程,才能解答。......【阅读全文】
发布时间:2015-06-04 17:16:24
1、基本原理 本文主要涉及ip_append_data中的UFO(UDP Fragment Offload)相关流程,主要由ip_ufo_append_data函数完成相关功能。比较简单。 UFO(UDP Fragment Offload)是硬件网卡提供的一种特性,由内核和驱动配合完成相关功能。其目的是由网卡硬件来完成本来需要软件进行的分段(分片)操作用于提升效率和性能。如大家所知.........【阅读全文】
发布时间:2015-03-30 07:24:04
kernel 3.10内核源码分析--IO--SCSI错误处理机制
基本原理
SCSI层提供的错误处理机制,主要针对两种IO错误类型(其实也就只有这两种类型):
1、IO错误(IO Error)。IO错误是底层固件(比如SAS控制器固件或光纤卡固件)主动上报的事件(中断),表示下发的IO请求(SCSI命令)执行完成,但是出错了。出现的情况较少,典型情况如:磁盘损坏导致IO执行错误。
2、IO超时(IO Timeout)。IO超时是IO请求下发后,在指定时间内(在IO请求下发时会启动相应的定时器,默认为30s,有些特殊的指令设置为60s或10s)没有执行完成(执行完成的标志是有相应的中断事件上报)。那可能的原因就多了,在IO链路上的每个环节出现问题(而又没有相应的事件主动上报时),都可能出现超时,这种情况相对比较复杂。典型的案例为:光纤卡链路问题(虚断)。
SCSI层提供的错误处理机制基本原理为:
1、在host初始化时启动相应的错误处理内核线程(scsi_eh_x)
2、当出现IO超时(由定时器触发后检测)或IO错误(由软中断触发后检......【阅读全文】
发布时间:2015-03-19 07:21:33
kernel 3.10内核源码分析--BUG_ON流程
一、问题
在dmesg或messages中常见BUG_ON的相关打印,如:
------------[ cut here ]------------
kernel BUG at ...
也常见其它的异常打印,比如page_fault相关的,softlockup相关的,有时候不太好区分它们之间的差别,但区分它们却是否重要,直接关系着对问题本质的判断。
这里简单分析了一下BUG_ON在3.10 kernel代码中的实现。
二、基本原理
BUG_ON通过BUG宏实现。BUG最终是通过执行ud2汇编指令实现。ud2指令看起来有点陌生,大概就是undefine的意思,是一种让CPU产生invalid opcode异常的软件指令,此时会有相应的异常事件上报,内核捕获相应的异常,由预先注册的异常处理接口进行处理:打印相关错误信息,最终根据配置进行kdump或panic或停止当前进程。......【阅读全文】
发布时间:2015-03-11 07:21:35
kernel 3.10内核源码分析--hung task机制
一、相关知识
长期以来,处于D状态(TASK_UNINTERRUPTIBLE状态)的进程都是让人比较烦恼的问题,处于D状态的进程不能接收信号,kill不掉。在一些场景下,常见到进程长期处于D状态,用户对此无能为力,也不知道原因,只能重启恢复。
其实进程长期处于D状态肯定是不正常的,内核中设计D状态的目的是为了让进程等待IO完成,正常情况下IO应该会顺利完成,然后唤醒相应的D状态进程,即使在异常情况下(比如磁盘离或损坏、磁阵链路断开等),IO处理也是有超时机制的,原理上不会存在永久处于D状态的进程。但是就是因为内核代码流程中可能存在一些bug,或者用户内核模块中的相关机制不合理,可能导致进程长期处于D状态,无法唤醒,类似于死锁状态。
针对这种情况,内核中提供了hung task机制用于检测系统中是否存在处于D状态超过120s(时长可以设置)的进程,如果存在,则打印相关警告和进程堆栈。如果配置了hung_task_panic(proc或内核启动参数),则直接发起panic,结合kdump可以搜集到vmco......【阅读全文】
发布时间:2015-01-23 17:14:02
kernel 3.10内核源码分析--块设备层request plug/unplug机制
一、基本原理
Linux块设备层使用了plug/unplug(蓄流/泄流)的机制来提升IO吞吐量。基本原理为:当IO请求提交时,不知直接提交给底层驱动,而是先将其放入一个队列中(相当于水池),待一定时机或周期后再将该队列中的请求统一下发。将请求放入队列的过程即plug(蓄流)过程,统一下发请求的过程即为unplug(泄流)过程。每个请求在队列中等待的时间不会太长,通常在ms级别。
如此设计,可以增加IO合并和排序的机会,便于提升磁盘访问效率。......【阅读全文】
发布时间:2015-01-06 13:00:03
一、概念
Linux系统中,应用程序以进程的方式存在,调度也以进程为单位,有关进程的概念就不多说了,参考教科书。
本文主要关注进程状态、偶然会见到的僵尸进程(Z状态)、以及很少见过的X状态进程。
每个进程都有相应的状态,如平常常见的R、S和D状态,也有在出现问题时见到的Z状态,即僵尸状态,还有极少见到的X状态,这也是本文重点分析和关注的。......【阅读全文】
发布时间:2015-01-05 16:50:08
进程调度时,当被选中的next进程不是current进程时,需要进行上下文切换。
进行上下文切换时,有一些问题不太容易理解,比如:
1、进程上下文切换必然发生在内核态吗?
2、上下文切换后原来的进程(prev)如果恢复执行,从什么地方开始执行?
3、上下文切换后,如何切换到新进程执行?新进程从什么地方开始执行?
5、上下文切换时,堆栈如何切换,如果保证不混乱?
6、A进程执行时被打断调度B进程运行,B进程正常执行过程中被打断调度C进程运行,C运行被打断中调度D运行,以此类推,看似一个无限嵌套,如何恢复到A进程运行,不会一层层返回吧?会不会有问题?
7、上下文切换后,如何恢复到新进程的用户态程序继续执行?
上述问题(可能还有其它疑问~)在理解了进程上下文切换的细节后,就都能回答了。......【阅读全文】
发布时间:2015-01-05 13:57:45
Linux中有3种栈:
1)用户栈。当进程处于用户态时使用,位于进程地址空间(用户态部分(如:0-0xc0000000))底部,用户态分配局部变量和函数调用时时,使用该栈,跟平时我们见到和理解的一样,就是虚拟地址空间中的一段。
2)内核栈。跟用户栈独立,属于进程,即每个进程都有自己的内核栈,单独分配,大小为8k,跟thread_info结构放在一起,在用户态和内核态切换时,需要进行切换。
3)中断栈。老版本内核中默认认跟内核栈共享,新版本内核中与内核栈独立,且软中断和硬中断单独使用自己的中断栈。中断、异常、软中断使用此栈。
本文主要讲解内核栈、用户栈和内核栈切换的相关实现。......【阅读全文】
发布时间:2014-12-30 16:51:55
kernel 3.10内核源码分析--进程退出exit_code
进程退出时,有相应的exit_code,可用于判断进程退出的原因。......【阅读全文】
发布时间:2014-11-19 16:06:19
kernel 3.10内核源码分析--slab原理及相关代码
1、基本原理
我们知道,Linux保护模式下,采用分页机制,内核中物理内存使用buddy system(伙伴系统)进行管理,管理的内存单元大小为一页,也就是说使用buddy system分配内存最少需要分配一页大小。那如果需要分配小于一页的内存该怎么办呢?
另一方面,内核中经常需要大量的数据结构(比如struct task_strcut),这些数据结构的频繁分配和释放对性能影响较大。
Slab正是用于解决上述的两个问题, Slab 分配器源于 Solaris 2.4 的分配算法,工作于buddy system之上,用于管理特定大小对象的缓存,提高小块内存或特定对象内存分配效率。
Slab的两个用途如前面所述:1、缓存和管理内核中经常使用的数据结构对象,内核中使用slab提供的专用的接口,可以实现数据结构对象的快速分配,大大减少相关开销,提升效率。2、缓存和管理小块内存,也称通用缓存,用于kmalloc的底层实现和支撑。......【阅读全文】
发布时间:2014-09-12 17:02:34
kernel 3.10内核源码分析--udp_sendmsg()--UDP发包流程
udp_sendmsg()主要流程如下:
1)前期处理。包括,对数据长度合法性判断、pending数据的判断、目的地址的处理和获取、控制信息的处理、组播处理、connected信息处理、MSG_CONFIRM标志的处理等。
2)调用ip_append_data()接口将其添加到传输控制块(sock)的发送队列中(利用发送队列中的现有skb,或者新创建skb,详细原理和流程请参见ip_append_data()接口的分析)。
3)判断是否有cork标记(MSG_MORE),如果没有,则说明需要立即发送,则调用udp_push_pending_frames()接口发送报文,实际是将包提交至IP层;如果设置了cork,则说明需要阻塞等待直到数据达到MTU大小,则完成本次的udp_sendmsg()处理。......【阅读全文】
发布时间:2014-09-09 19:53:39
kernel 3.10内核源码分析--ip_append_data--IP层提供的UDP和RAW socket的发包接口
基本原理
UDP发包流程中,当没有cork的情况下,会走过udp_sendmsg到达ip_append_data,该接口是IP层提供的UDP和RAW Socket的发包接口,同时,TCP中用于发送ACK和RST报文的接口ip_send_reply最终也会调用此接口
该接口的主要作用是:将数据拷贝到适合的skb(利用发送队列中现有的或新创建)中,可能有两种情况:
1)放入skb的线性区(skb->data)中;
2)或者放入skb_shared_info的分片(frag)中
另外,还需要考虑MTU对skb数据进行分割,为IP层的分片做准备。......【阅读全文】
发布时间:2014-09-05 15:00:23
kernel 3.10内核源码分析--Sysrq处理流程、键盘驱动、input子系统相关
1、基本介绍
Sysrq魔术键提供了大量的实用功能,可用户快速获取系统运行状态信息,尤其是在系统出现异常时,收集有用信息,对于疑难问题的分析有极大的帮助。
典型应用场景如:
1)系统进入了挂死状态(如调度出现异常、或系统负荷过重),但仍能响应中断,此时可以通过Sysrq魔术键(c)手工触发panic,结合kdump,就能收集到vmcore信息,用于问题的后续分析定位,非常有用。
2)当系统中某进程出现挂死(可能是D状态,或是死锁),此时需要确认该进程具体挂在什么地方,可以使用Sysrq魔术键(t)打印出系统中所有进程的堆栈信息。
3)当系统出现反应迟钝、交互困难时,难以通过shell或终端交互获取到有用信息,此时可以使用Sysrq魔术键(m,p)打印出系统中内存使用的详细信息和CPU运行上下文信息等。......【阅读全文】
发布时间:2014-08-13 18:58:47
kernel 3.10代码分析--KVM相关--KVM_SET_USER_MEMORY_REGION流程
1、基本原理
如之前分析,kvm虚拟机实际运行于qemu-kvm的进程上下文中,因此,需要建立虚拟机的物理内存空间(GPA)与qemu-kvm进程的虚拟地址空间(HVA)的映射关系。
虚拟机的物理地址空间实际也是不连续的,分成不同的内存区域(slot),因为物理地址空间中通常还包括BIOS、MMIO、显存、ISA保留等部分。
qemu-kvm通过ioctl vm指令KVM_SET_USER_MEMORY_REGION来为虚拟机设置内存。主要建立guest物理地址空间中的内存区域与qemu-kvm虚拟地址空间中的内存区域的映射,从而建立其从GVA到HVA的对应关系,该对应关系主要通过kvm_mem_slot结构体保存,所以实质为设置kvm_mem_slot结构体。......【阅读全文】
发布时间:2014-08-12 19:44:18
kernel 3.10代码分析--KVM相关--虚拟机创建
1、基本原理
如之前分析,kvm虚拟机通过对/dev/kvm字符设备的ioctl的System指令KVM_CREATE_VM进行创建,本文简单解释及分析在3.10版本内核代码中的相关流程,用户态qemu-kvm部分暂不包括。......【阅读全文】
发布时间:2014-08-06 09:42:39
kernel 3.10内核源码分析--vmalloc(非连续内存页分配)
在分配内存时,总是希望能分配到连续的物理内存页,愿望是美好的,但系统中可能没有太多的连续内存可用(比如内存碎片严重时),此时就需要一种非连续内存的分配方式。于是乎,就产生了vmalloc,vmalloc用于分配不连续的物理内存页,但将其映射到内核虚拟地址空间中后,其虚拟地址是连续的
内核虚拟地址空间中,有一段专门的区间用于vmalloc,称之vmalloc区,位于线性映射区之后,准确的说是从892M+8M(VMALLOC_START)到VMALLOC_END之间,其中892M是线性映射区,用于线性映射低端内存,之后的8M是安全间隙,用于区间隔离,防止越界。
vmalloc区中包含一个个独立的子区域,每个子区域用于一次独立映射,各个子区域间通过一个内存页进行隔离,防止不正确的内存访问操作。......【阅读全文】
发布时间:2014-08-06 09:09:10
3.10 kernel内核源码分析--ioremap
1、为什么需要ioremap
问题:分配mmio(request_mem_region)后,得到的是物理地址,按理只需要将其转换为虚拟地址后(内核中,低端内存只是一个偏移而已),
应该就可以直接访问了吧?但是为什么还需要使用ioremap将其转换为线性地址后才能访问呢?
解答:分配的mmio的物理地址在内核中不一定能直接访问,比如:
1)x86 32位环境中,mmio的地址范围就在3G-4G之间,位于高端内存,内核中不能直接访问,需要进行映射。
2)一些体系架构中,IO内存根本就不能直接访问,必须建立相应的映射后才行,相应的映射工作由架构相关的ioremap完成......【阅读全文】
发布时间:2014-07-17 19:23:47
Out Of Memory(OOM),即内存耗尽,当系统中内存耗尽时,如果不做处理,将处于崩溃的边缘,因为无内核资源可用,而系统运行时刻都可能需要申请内存。这时,内核需要采取一定的措施来防止系统崩溃,这就是我们熟知的OOM流程,其实就是要回收一些内存,而走到OOM流程,已经基本说明其它的回收内存的手段都已经尝试过了(比如回收cache),这里通常只能通过kill进程来回收内存了,而选择被kill进程的标准就比较简单直接了,总体就是:谁用的多,就kill谁。......【阅读全文】
发布时间:2014-07-02 17:15:46
kernel 3.10内核源码分析--缺页异常(page fault)处理流程......【阅读全文】