kernel

Linux页高速缓存和页回写

  页高速缓存(cache)是Linux内核实现磁盘缓存的机制。磁盘高速缓存之所以重要的原因有二:1.访问磁盘的速度要远远低于访问内存的速度;2.数据一旦被访问,根据临时局部原理,它将很有可能在短时间内再次被访问到。 1.缓存手段   页高速缓存是由内存中的物理页面组成的,其内容对应磁盘上的物理块。页高速缓存大小能动态调整--它可以通过占用空闲内存以扩张大小,也可以自我收缩以缓解内存压力。注意,系统不一定要将整个文件都缓存,而只是缓存部分。 1.1写缓存   包括以下三种: 不缓存。直接写磁盘。 写透缓存。写操作自动更新内存缓存,同时也更新磁盘文件。 回写。程序执行写操作直接写到缓存中,后端存储不会立刻更新,而是将页高速缓存中被写入的页面标记为『脏』页,并被加入到脏页链表。然后由一个进程周期性将脏页链表中的页写回到磁盘。…

Read more

Linux进程地址空间

  对一个进程而言,它好像都可以访问整个系统的所有物理内存。即使单独一个进程,它拥有的地址空间也远远大于系统物理内存。 1.地址空间   每个进程都有一个32位或者64位的平坦(flat)地址空间,空间具体大小取决于体系结构,平坦指的是地址空间范围是一个独立的连续区间。一些操作系统提供了段地址空间,这种空间并非是一个独立的线性区域,而是被分段的,但现代采用虚拟内存的操作系统通常都是使用平坦地址空间而不是分段式的内存模式。通常情况下,每个进程都有唯一的这种平坦地址空间。一个进程的地址空间与另一个进程的地址空间即使有相同的内存地址,实际上彼此不相干。我们称这样的进程为线程。   尽管一个进程可以寻址4GB的虚拟内存,但这并不代表它就有权访问所有的虚拟地址。我们把可被访问的合法地址空间称为内存区域。通过内核,进程可以给自己的地址空间动态…

Read more

Linux块I/O

  Linux下有两种基本的设备类型,一种是字符设备,另外一种是块设备。如果一个硬件设备是以字符流的方式被访问的话,则属于字符设备;反之,如果一个设备是随机(无序)访问的话,则属于块设备。比如键盘属于字符设备,硬盘属于块设备。字符设备仅仅需要控制一个位置--当前位置,而块设备访问的位置必须能够在截至的不同区间前后移动。   扇区是块设备最小寻址单元,一般为512字节。块是文件系统的一种抽象--只能基于块来访问文件系统。虽然物理磁盘寻址是按照扇区级进行的,但是内核执行的所有磁盘操作都是按块进行的。内核还要求块大小是2的整数倍,而且不能超过一个页的长度。总结来说,扇区是设备的最小寻址单元,而块是文件系统的最小寻址单元。 1.缓冲区和缓冲区头   当一个块被调入内存时,它要存储在一个缓冲区中,每一个缓冲区与一个块对于,它相当于是磁盘块在…

Read more

Linux虚拟文件系统

  通过虚拟文件系统(VFS),程序可以利用标准的Unix系统调用对不同的文件系统,甚至不同介质上的文件系统进行读写操作,如下图所示:使用cp(1)命令从ext3文件系统格式的硬盘拷贝数据到ext2文件系统格式的可移动磁盘上。两种不同的文件系统,两种不同的介质,连接到同一个VFS上。 1.文件系统抽象层   vfs可以使得用户可以直接使用open(),read(),write()这样的系统调用而无须考虑具体文件系统和实际物理介质。vfs把各种不同的文件系统抽象后采用统一的方式进行操作。而之所以可以使用这种通用接口对所有类型的文件系统进行操作,是因为内核在它的底层文件系统接口上建立了一个抽象层。该抽象层使Linux能够支持各种文件系统,即便是它们在功能和行为上存在很大差异。下图展示了一次用户控件的write()调用具体触发的流程。 2.Unix文件系统…

Read more

Linux内存管理

  在内核中分配内存空间不像在其他地方分配内存这么容易,主要原因是空间受限。内核与用户空间不同,不支持这种简单便捷的内存分配方式。 1.页   内核把物理页作为内存管理的基本单位。尽管处理器的最小可寻址单位是字,但内存管理单元(MMU)通常以页为单位进行处理,大多数32位体系结构支持4KB的页,64位为8KB。内核用struct page结构体表示系统中的每个物理页。 struct page { unsigned long flags; //页状态,标识是否为脏页,是否锁定在内存等等。一共有32位标识 atomic_t _count; //该物理页的引用次数 atomic_t _mapcount; unsigned long private; struct address_space *mapping;…

Read more

Linux bridge学习

  Linux bridge是Linux内核中虚拟网桥的一个实现,它与OpenvSwitch都实现交换机功能,但比后者简单一些,只实现了最简单的二层功能,而没有ovs下诸如QoS,OpenFlow,netconf等等复杂的功能。本文主要参考《深入理解Linux网络技术内幕》,更像一个读书笔记性质的小结。   虚拟网桥是定义在真实设备之上的一个抽象设备,当该真实设备发生状态变化,则Linux bridge会受到影响。netdevice通知链向内核注册br_device_event回调函数,任何真实设备的变动会触发该回调函数。   下图是在有无网桥情况下收发包的示意图。在设备上传输数据是通过dev_queue_xmit执行的,它会调用设备驱动函数hard_start_xmit进行发包,中间有一些查找发包的过程。dev_queue_xm…

Read more

mininet与namespace

  前一阵发现一个问题,就是用mininet起的主机的namespace用ip netns查看不到,一直感觉很奇怪,因为根据mininet官网给出的描述,起创建的switch,host还有自带的controller都是位于namespace下的,其中switch和自带controller都是位于root namespace下,不同host是位于不同的host下面,但是为啥子用ip netns就看不到,明明ip netns就是查看namespace的。今天有时间,上网查了一下,终于知道以前了解的namespace只是冰山一角。本文只给出概括说明,具体不同namespace的详细用法查看文章底部的链接。   总得概括来说其实就是一句话:ip netns add创建的namespace是带name的,而mininet创建的namespace是nameles…

Read more

ovs中流表在内核空间与用户空间的匹配过程

  一直对ovs中facet和subfacet概念搞不清楚,今天仔细查了网上,关于这个的解释信息好少,以下这个是mail list里面的回答,感觉挺正确了: As I understand, there are two kinds of flow in OVS. One is in the user space, e.g. vswitchd, where flow key can include some wildcards to match, while the other lies in kernel space, e.g. openvswitch.ko, where the flow key can never have wildcard. If no wildcard in user space flow (a.k.a facet), the flow from…

Read more

ovs datapath笔记

  这几天在学习ovs的源码,现在来做个datapath的笔记。事先声明,本文的内容摘自博客,源码,视频以及自己的总结等,具体参考文献已经在文章末尾给出,主要参考为Baohua Yang的OpenvSwitch 代码分析。 0.模块介绍   datapath为ovs内核模块,负责执行数据交换,也就是把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。   一个datapath可以对应多个vport,一个vport类似物理交换机的端口概念。一个datapth关联一个flow table,一个flow table包含多个条目,每个条目包括两个内容:一个match/key和一个action,一个match/key可以从包中获取,对应一个action处理行为,最常见的action是在不同flow中进行转发。下图所示的是1…

Read more

Linux网络内核数据结构之sk_buff

  sk_buff是Linux网络内核中最重要的数据结构之一。所有网络分层(MAC或L2分层上的另一种链路层协议,L3的IP,L4的TCP或UDP)都会使用这个结构来存储其报头,有关用户数据的信息,以及用来协调其工作的其他内部信息。当该结构从一个分层传到另一个分层时,其不同的字段会随之发生改变。在不同层数据传递时,通过附加报头的形式,减少了拷贝带来的开销。   内核把所有sk_buff结构链成一个双向链表,并添加了一个头元素,该头元素的结构是sk_buff_head: struct sk_buff_head {   struct sk_buff *next; 指向后继结点   struct sk_buff *prev; 指向前驱结点   __u32 qlen; 表中元素的数…

Read more

Linux内核同步方法

1. 原子操作   内核提供了两组原子操作接口--一组针对整数进行操作,另一组针对单独的位进行操作。 1.1 原子整数操作   针对整数的原子操作智能对atomic_t类型的数据进行处理。在这里之所以引入了一个特殊数据类型,而没有直接用C语言的int,主要处于以下原因: 让原子函数只接收atomic_t类型的操作数,可以确保原子操作只与这种特殊类型数据一起使用。同时,也保证了该类型的数据不会被传递给任何非原子函数。 使用atomic_t类型确保编译器不对相应的值进行访问优化--这点使得原子操作最终接收到正确的内存地址,而不是别名。 在不同体系结构上实现原子操作的时候,使用atomic_t可以屏蔽其间的差异。   atomic_t是32位数,后来引入了64位的atomic64_t。下图是原子整数操作函数表: 1.2…

Read more

中断之后下半部和推后执行的工作

  在前面所说的中断处理程序,由于本身存在一些局限,所以它智能完成整个中断处理流程的上半部。这些局限包括: 中断处理程序以异步方式执行,并且它有可能会打断其他重要代码(甚至包括其他中断处理程序)的执行。因此,为了避免被打断的代码停止时间过长,中断处理程序应该执行得越快越好。 如果当前有一个中断处理程序正在执行,在最好的情况下,与该中断同级的其他中断会被屏蔽,在最坏的情况下,当前处理器上所有其他中断都会被屏蔽。因为禁止中断后硬件与OS无法通信,因此,中断处理程序执行得越快越好。 由于中断处理程序往往需要对硬件进行操作,所以它们通常有很高的时限要求。 中断处理程序不在进程上下文中运行,所以它们不能阻塞。 1.下半部   下半部的任务就是执行与中断处理密切相关但中断处理程序本身不执行的工作。在理想的情况下,最好是中断处理程序将所有工作都交给下半…

Read more

中断与中断处理

1.中断   中断本质上是一种特殊的电信号,由硬件设备发向处理器。处理器接收到中断后,会马上向OS反映此信号的到来,然后就由OS负责处理这些新到来的数据。硬件设备生成中断的时候并不考虑与处理器的时钟同步--换句话说就是中断随时可以产生。因此,内核随时可能因为新到来的中断而被打断。   不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标志。这些中断值通常被称为中断请求(IRQ)线。每个IRQ线都会被关联一个数值量。 2.中断处理程序   在响应一个特定中断的时候,内核会执行一个函数,该函数叫做中断处理程序或中断服务例程。产生中断的每个设备都有一个相应的中断处理程序。一个设备的中断处理程序是它设备驱动程序的一部分--设备驱动程序是用于对设备进行管理的内核代码。   中断处理程序需要负责通知硬件设备中断已经被…

Read more

linux内核中的数据结构

  linux建议开发者使用其内建的数据结构,而不要自作主张搞一套山寨的。本文讲解内核中常用的4种数据结构:链表,队列,映射,二叉树。 1.链表   链表包括单向链表(有一个后向指针),双向链表(有一个后向指针和一个前向指针),环形链表(首尾相连)。linux内核的标准链表采用环形双向链表形式实现。 1.1 链表数据结构   linux内核方式与众不同,它不是将数据结构塞入链表,而是将链表节点塞入数据结构。比如,一个普通的链表节点: struct Node {   int data;   struct Node *pre;;   struct Node *next; };   linux下的实现是把前后指针抽出来,形成单独数据结构…

Read more

系统调用

1.与内核通信   系统调用在用户空间进程和硬件设备之间添加了一个中间层。该层主要作用有三个: 它为用户空间提供了一种硬件的抽象接口。 系统调用保证了系统的稳定和安全。 如果应用程序可以随意访问硬件而内核又对此一无所知的话,几乎没办法实现多任务和虚拟内存。 举例:应用程序调用printf(),调用C库中的printf(),又调用C库中的write(),又调用内核中的write()系统调用。 2.系统调用   在linux中,每个系统调用都被赋予一个系统调用号。   linux系统调用比其他许多OS执行得要快。linux很短的上下文切换时间是一个重要的原因,进出内核都被优化得简洁高效。另外一个原因是系统调用处理程序和每个系统调用本身也都非常简洁。 3.系统调用处理程序   系统调用通知内核的机制是靠软…

Read more

linux下进程调度

  linux 2.6之后内核的进程调度算法是CFS:完全公平调度算法。 1.策略 1.1 I/O消耗性和处理器消耗型的进程   调度策略通常要在两个矛盾的目标中间寻找平衡:进程响应迅速和最大系统利用率了。 1.2 进程优先级   linux采用了两种不同的优先级范围。第一种是用nice值,范围从-20到+19,默认值为0;越大的nice值意味着更低的优先级。相比高nice值的进程,低nice值的进程可以获得更多的处理器时间。nice值也代表时间片的比例。可以通过ps -ef查看系统中的进程列表,结果中标记NI的一列就是进程对应的nice值。   第二种是实时优先级,其值是可配置的,默认情况下它的变化范围从0到99。与nice相反,越高的实时优先级数值意味着进程优先级越高。对应的Linux下是PTPRIO。 1…

Read more

linux下进程管理

1.进程   进程提供两种虚拟机制:虚拟处理器和虚拟内存。   fork()系统调用从内核返回两次:一次回到父进程,另一次回到新产生的子进程。通常,创建新的进程都是为了立即执行新的,不同的程序,而接着调用exec()这组函数就可以创建新的地址空间,并把新的程序载入其中。在现代linux内核中,fork()实际上由clone()系统调用实现。   最终,程序通过exit()系统调用退出执行。这个函数会终结进程并将其占用的资源释放掉。父进程可以通过wait4()系统调用查询子进程是否终结。 2.进程描述符及任务结构   内核把进程的列表存放在叫做任务队列(task list)的双向循环链表中。链表中每一项都是类型为task_struct,称为进程描述符的结构。 2.1分配进程描述符   linu…

Read more