linux内核
文章平均质量分 89
庾志辉
这个作者很懒,什么都没留下…
展开
-
linux内核之哈希链表解析
本文只是对linux内核中的链表进行分析。内核版本是linux-2.6.32.63。文件在:linux内核/linux-2.6.32.63/include/linux/list.h。本文对list.h文件进行简要分析,有必要的地方还会以图进行说明。原创 2014-08-03 14:59:52 · 4594 阅读 · 0 评论 -
Linux内核源码分析--文件系统(二、高速缓存区)
从块设备中读取数据是很慢的(I/O操作相对于内存操作来说是比较慢的),所以为了不让CPU浪费宝贵的时间来等待读取块设备上的数据,就在内存中开辟了一段内存地址用来预获取最近使用过的多块设备块上的数据。当CPU需要访问块设备上的数据时,首先会在缓冲区中查找,如果有幸能找到,那么就直接拿过来使用;如果找不到就没办法,需要从块设备上把查找的数据块读取到高速缓存中(一般会多读取几个存放起来),然后CPU再从高速缓存区中读取需要的数据块;所以总结来说CPU只读内存上的数据,如果要读块设备上的数据,必须先放到高速缓存中,原创 2015-02-09 22:14:06 · 4601 阅读 · 0 评论 -
Linux内核源码分析--文件系统(四、Bitmap.c)
总结的来说其实Bitmap.c程序就是操作文件系统中的两个位图:i节点位图和逻辑块位图;拿逻辑块位图来说吧,申请一个新的逻辑块时,首先是在8块逻辑块位图中查找一个空闲的比特位,找到以后转换成逻辑块号,然后就通过逻辑块号找到真正的逻辑块,通过函数把该逻辑块映射到缓存区中,当然最后要对缓存区做些属性设置;释放一个逻辑块时也一样,首先做些检查,然后释放缓存块,最后也是设置下逻辑块位图(当然也是根据逻辑块号转换成8块逻辑块位图中的某个比特位)。原创 2015-02-21 16:17:41 · 3025 阅读 · 0 评论 -
Linux内核源码分析--文件系统(三、buffer.c)
前面已经大概的分析了下高速缓存区相关知识,这里再来分析下几个重要的函数;1、清缓存:把缓存区数据和设备进行同步; 2、缓存块插入到双链表/hash链表中,从双链表/hash链表中删除缓存块; 3、查找缓存块号; 4、从设备上读取数据到缓存中; 5、缓存区初始化函数;原创 2015-02-10 14:52:56 · 3672 阅读 · 0 评论 -
全面解析C语言中可变参数列表
全面解析c语言中可变参数列表问题:1、大众版:大家习惯的使用方式;2、真实版:真正的使用方式;3、实际原理:具体原理,本质;4、自己实现可变参数列表:理解本质后,自己用自己的方法来实现可变参数列表;5、可变参数列表缺陷:可变参数列表中存在的一些缺陷,以及提供的修改思路和方案。原创 2015-02-11 15:27:15 · 10350 阅读 · 2 评论 -
Linux内核源码分析--文件系统(八、Block_dev.c)
由于是块设备的读写操作,所以每一次都是以块为单位(1024)进行操作;pos是文件的位置光标,用pos可以得到文件现在所处在哪块逻辑块上,并且在该逻辑块上偏移了多少。再根据块的大小 可以得到该逻辑块还剩下多少空间。最后跟需要写入的字符数比较,如果该逻辑块剩下的空间足够存放需要写入的字符,则读取该逻辑块到缓存区,然后进行数据的写入;否则,先填满逻辑块剩下的空间,然后再读取下一个逻辑块;原创 2015-03-26 14:27:29 · 2421 阅读 · 0 评论 -
Linux内核源码分析--文件系统(九、File_dev.c)
file_dev.c程序是用于访问文件数据的读写程序;file_read() int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)函数,从i节点为inode的文件中 filp中pos位置处开始读取count个字节数据存放到用户空buf内 功能:从i节点为inode的文件中 filp中pos处开始读取count个字节数据存放到用户空间buf处 参数:in原创 2015-03-26 15:41:46 · 2088 阅读 · 0 评论 -
Linux内核源码分析--文件系统(七、Namei.c)
1、功能和stncmp()函数一样,都是对指定字符串进行比较。比较指定长度len的name和de结构体中的name进行比较,相等返回1,否则返回0; //字符串匹配,参数分别为:比较长度,文件名指针,目录项结构体static int match(int len,const char * name,struct dir_entry * de){ register int same __原创 2015-03-04 15:02:25 · 3729 阅读 · 0 评论 -
Linux内核源码分析--文件系统(六、Super.c)
1、释放指定设备的超级块:首先是对设备块号检查以及检查设备块号对应的超级块的合法性;然后释放8块i节点位图和逻辑块位图,最后释放掉超级块;//释放指定设备的超级块,//释放设备所使用的超级块数组项(s_dev=0),并释放该设备i节点位图和逻辑块所占用的高速缓存块//如果超级块对应的是文件系统根文件系统,或者其i节点上已经安装其他的文件系统,则不能释放该超级块void put_super原创 2015-02-26 17:07:06 · 4440 阅读 · 0 评论 -
Linux内核源码分析--文件系统(五、Inode.c)
//把文件上的数据存放在磁盘上,inode 文件i节点;block 文件中数据块号,create是否创建标志static int _bmap(struct m_inode * inode,int block,int create){ struct buffer_head * bh; int i;//判断文件数据块号block是否超出范围 if (block<0) panic("_原创 2015-02-26 10:54:41 · 5849 阅读 · 1 评论 -
linux内核驱动模块编程框架---(hello world模块)
linux内核驱动模块编程框架,模块Makefile文件,模块的常用操作命令(模块的加载卸载命令);重点来说下注册的回调函数,static int __init hello_init(void)和static void __exit hello_exit(void)函数; 一、模块初始化函数,这个函数是有返回值得,而模块卸载所触发的收尾处理函数是没有返回值得。 二、这两个函数和我们平时写得函数不一样,多了个__init和__exit(前面是两个_),这个可以加也可以不加。为什原创 2014-10-18 13:55:15 · 3785 阅读 · 0 评论 -
linux内核之链表操作解析
本文只是对linux内核中的链表进行分析。内核版本是linux-2.6.32.63。文件在:linux内核/linux-2.6.32.63/include/linux/list.h。本文对list.h文件进行简要分析,有必要的地方还会以图进行说明。代码分析:原创 2014-08-03 14:39:08 · 1946 阅读 · 0 评论 -
加载模块报错:version magic '2.6.32-504.el6.i686 SMP mod_unload 686 ' should
hello: module_layout: kernel tainted.Disabling lock debugging due to kernel tainthello: version magic '2.6.32-504.el6.i686 SMP mod_unload 686 ' should be '2.6.32-504.el6.i686 SMP mod_unload modversions 686 '第一步、看看你运行内核的版本:ls /usr/src/kernels/2.6.32-504.原创 2015-04-11 10:46:00 · 3821 阅读 · 0 评论 -
linux内核树的建立
交叉编译驱动环境搭建: 我的开发板是mini2440(s3c2440)内核版本是:2.6.32.2;用开发板自带的源码,利用samba服务器把源代码放到宿主机中,然后解压。(操作的都是在宿主机中)编译内核树的步骤和上面的一样,第二步稍微修改下,源码中一般有自带的.config文件,我的是config_mini2440_x35,把该文件拷贝一份为.config就可以了。其他的和上面一样。(其实不用那么完整的编译,只需要make zImage 下就可以的)原创 2014-10-17 14:10:27 · 5714 阅读 · 0 评论 -
linux内存管理之初始化zonelists
初始化后zonelists:m1 == node1 movable ; h1 == node1 highmen; n1 == node1 normal; d32.1 == node1 DMA32; d1 == node1 DMAm2 == node2 movable; .........ZONELIST_ORDER_NODE:pgdat->node_zonelists[0]->_zonerefs[0 ~ node * node->node_zones] = m1 h1 n1原创 2016-02-28 13:06:32 · 2123 阅读 · 0 评论 -
Linux内核源码分析--系统时间初始化(kernel_mktime()函数)
从boot文件中的几个汇编程序执行后跳转到init文件中的main.c程序开始继续执行,该main.c函数式为系统运行的环境进行初始化的。首先来看系统时间的初始化(因为系统时间的初始化开始程序就在init文件中),其中主要还是由kernel中的mktime.c程序中的kernel_mktime函数计算时间的。 先看下time_init(void)函数及相关结构是怎么实现的:原创 2015-01-19 23:14:24 · 3817 阅读 · 0 评论 -
Linux上电初始化--BOSI启动和boot环境设置
BIOS:上电启动时,最开始由硬件控制进入BIOS,BIOS代码一般存放在0xfe000~0xfffff最后几kb中; 启动中cs:eip == 0xffff:0x00000 === 0xffff0 这是最开始启动的(BIOS执行的第一条指令)下面是BIOS程序执行的内容:1、在0x00000处开始的1kb内存空间(0x00000~0x003fff)安装中断向量表(256个中断,c原创 2015-01-15 18:08:08 · 1952 阅读 · 0 评论 -
Linux内核源码分析--内存管理(一、分页机制)
最开始的地方是在head汇编中,如果看boot中那三个汇编的应该记得(那三个汇编还是比较重要的)。首先是分页机制,在CR0的第31位(PG位)置1表示开启分页机制,顺便也介绍下其他几个控制寄存器:CR1保留,没用;CR2 用来记录页面异常时线性地址(不懂没关系,后面会介绍);CR3 当前CPU使用的页目录表的地址(有此可见系统中不仅仅只有一个页目录表,但是在某一时刻有效的页目录表只有一个);当然有关页面操作的前提是CR0的第31位必须打开,也就是必须是在分页机制开启的时候那几个控制寄存器才有效。原创 2015-01-22 16:30:52 · 5567 阅读 · 4 评论 -
linux内核之链表结构分析
linux内核之链表结构分析,先来说下linux内核链表设计的第二个巧妙点:链表节点没有数据项。为什么这么设置呢,是因为设计者无法预计数据项是什么类型,总不能为每种数据类型都设计堆链表操作函数吧,所以干脆不设计数据项,这样设计出来的链表操作函数就既有了通用性。而至于数据项呢,使用者想怎么设计就怎么设计。关键点是数据项结构体中包含链表项,这与我们自己平常设计的的链表节点有点不一样。原创 2014-08-03 13:29:48 · 1206 阅读 · 0 评论 -
linux内核开发平台工具:VMware远程连接服务器
linux内核开发平台工具:VMware远程连接服务器;因为做内核开发的经常会遇到系统崩溃的现象,而我们开发的时候不可能直接在服务器上进行模块的加载和卸载。一般是在服务器上用VMware做个虚拟机开发,经过多次调试没问题时,才放到服务器上。我们一般是远程登录服务器上的虚拟机开发。当我们程序让虚拟系统崩溃时,要到服务器上重新开启虚拟机里面的系统。(还有做网络内核开发,一旦卸载了原来的模块,那就没有ip地址,也就不能远程登录控制了)如果服务器近的话还好,如果很远就比较麻烦了。现在这方法就是解决这个问题的。原创 2014-08-07 23:02:09 · 1795 阅读 · 0 评论 -
linux内核之container_of()应用
linux内核之container_of()应用,因为我觉得在 linux内核之container_of()详解 文章中已经讲的非常详细了,再写什么也觉得是狗尾续貂了,没必要。可是今天自己做openvswitch内核开发时,发现自己也用错几个地方。所以就写个简单的程序来说明下怎么使用container_of()这个宏吧;如果涉及到内核中 hlist_for_each_entry(),hlist_for_each_entry_continue(),hlist_for_each_entry_safe()等等,原创 2014-08-06 23:12:00 · 2065 阅读 · 2 评论 -
sk_buff整理笔记(三、内存申请和释放)
内核对于sk_buff结构的内存分配不是和一般的结构动态内存申请一样:只分配指定大小的内存空间。而是在开始的时候,在初始化函数skb_init()中就分配了两段内存(skbuff_head_cache和skbuff_fclone_cache )来供sk_buff后期申请时用,所以后期要为sk_buff结构动态申请内存时,都会从这两段内存中来申请(其实这不叫申请了,因为这两段内存开始就申请好了的,只是根据你要的内存大小从某个你选定的内存段中还回个指针给你罢了)。如果在这个内存段中申请失败,则再用内核中用最低层原创 2014-08-21 22:00:46 · 9557 阅读 · 2 评论 -
sk_buff整理笔记(四、克隆与复制)
上面的pskb_copy()函数和skb_clone()函数类似:skb_clone()函数克隆出来的skb结构不能修改其共享数据区的数据,而pskb_copy()函数也是一样的,克隆出来的skb及数据区不能修改共享的分片结构数据区内容。所以如果想要修改分片结构数据区的内容,则必须要用skb_copy()函数来克隆skb结构体。skb_copy()函数是对skb结构体真正的完全复制拷贝。不仅是sk_buff结构体还有data指针指向的数据区(包括分片结构)以及分片结构中指针指向的数据区,都各自复制拷贝一份。原创 2014-08-25 21:41:07 · 6985 阅读 · 1 评论 -
linux内核之hlist哈希链表的应用---C语言代码实现(内核态)
本文是继linux内核之链表操作解析 之后对linux内核中链表和哈希链表的操作宏以及操作函数的一个应用; 第一步:是定义数据类型,主要是哈希链表,因为用的是拉链法(也叫数组链表)处理碰撞,所以也可以当作是链表的一个应用。对哈希链表来说除了定义数据项节点外还要定义个哈希表。对数据项解释下,hNode是链表连接的,key是真正的数据。key是个比较复杂的结构体,姑且认为他里面有个整型成员,作为关键字,其他成员不管。注意点:数据项节点中的成员尽量都不要用指针(尤其时hNode成员一定不能用指针),因为:第一、在原创 2014-08-17 18:59:03 · 3218 阅读 · 0 评论 -
什么是可重入
问题就是:什么是可重入?如果执行结果和没有发生中断时顺序执行得到的结果一样就表明该函数是可重入的。(是每次不管有没有异步事件发生,该函数执行的结果都是一样的才算是可重入函数)。内核中断情况下:用可重入函数来分析下在内核发生中断时运行情况,当CPU执行到该函数内时,突然接到一个中断信号,CPU将对保存现场(把一些参数,返回地址,执行状态之类的保存到堆栈中去),然后去执行中断服务程序;当执行完中断服务程序后,CPU就会还原现场,把一些参数,返回地址,执行状态之类的进行出栈,然后CPU再次进入该函数,从上次执行的原创 2014-08-15 00:02:22 · 4833 阅读 · 7 评论 -
linux内核之container_of()详解(即:list_entry()的详解)
#define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) 减号右边分析:(unsigned long)(&((type*)0)->member) (type*)0: 把0地址强制转换成type结构体的地址,表示0地址处存放了type类型的结构体变量,为什么在0处强转为结构体地址,这也是个设计巧妙点;((type*)0)->member:这个表示指向结构体原创 2014-08-03 12:09:28 · 3032 阅读 · 1 评论 -
sk_buff整理笔记(五、队列管理函数)
分析sk_buff结构及相关结构的队列管理函数:初始化函数,skb_queue_head_init(struct sk_buff_head *list);插入函数,kb_queue_head(),skb_queue_tail();出队列函数,sk_buff *skb_dequeue(struct sk_buff_head *list),sk_buff *skb_dequeue_tail(struct sk_buff_head *list);清空队列函数,skb_queue_purge(struct sk_b原创 2014-08-31 22:37:54 · 7167 阅读 · 0 评论 -
openVswitch(OVS)源代码之linux RCU锁机制分析
RCU是read copy udate的缩写,按照单词意思就知道这是一种针对数据的读、复制、修改的保护锁机制。锁机制原理: 第一、写数据的时候,不需要像读写锁那样等待所有锁的释放。而是会拷贝一份数据区的副本,然后在副本中修改,等待修改完后。用这个副本替换原来的数据区,替换的时候就要像读写锁中上写锁那样,等到原数据区上所有访问者都退出后,才进行数据的替换;根据这种特性可以推断出,用RCU锁可以有多个写者,拷贝了多份数据区数据,修改后各个写着陆续的替换掉原数据区内容。 第二、读数原创 2014-10-15 19:07:11 · 4891 阅读 · 9 评论 -
Linux 新内核中主次设备号范围
作者:李强,华清远见嵌入式学院讲师。 设备驱动中,设备号设一个很重要的概念和变量。不论是主设备号,还是次设备号,在设备驱动中都占据了很重要的地位。那么他在Kernel中是如何操作的?这个数据结构都是通过那些函数可以很容易的在我们写Linux设备驱动模块时被我们所使用呢? 在include/linux/type.h文件中我们能看到一个关于dev_转载 2015-01-28 15:58:02 · 1980 阅读 · 0 评论 -
openVswitch(OVS)源代码分析 upcall调用(之linux中的NetLink通信机制)
如果看了前面的源码分析的就会知道,在什么情况下会调用upcall函数呢?就是在一个数据包查找不到相应的流表项时,才会调用upcall函数(比如一个数据包第一次进入这个内核,里面没有为这个数据包设定相应的流表规则)。upcall函数的调用其实就是把数据包的信息下发到用户 空间去,而由内核空间到用户空间的通信则要用到linux中的NetLink机制。所以熟悉下NetLink通信可以知道upcall函数调用需要什么样的参数以及整个函数的作用和功能。原创 2014-11-04 19:13:12 · 4677 阅读 · 0 评论 -
Linux内核源码分析--内存管理(二、函数实现技巧)
仔细的分析了一下各个内存管理函数的实现,发现里面涉及到了几个技巧,如果知道了这几个技巧,那么阅读内存管理源码将会事半功倍(主要是这几个技巧在几个函数中都出现过),当然也会选择性的分析几个比较重要的函数实现; 1、向上取整:以一个页面为了例,如果地址是1,那么向上取整就是4096;如果地址是 4095,向上取整就是4096;如果地址是4098,向上取整就是4096 x 2....... #define CODE_SPACE(addr) ((((addr)+4095)&~4095) <原创 2015-01-23 17:33:24 · 3370 阅读 · 3 评论 -
memcopy()函数c语言实现和汇编实现比较
首先来看汇编实现的memcpy函数,是利用宏函数来实现的,用汇编指令rep和movsb配合循环把数据以字节为单位从ds:esi传送到es:edi中,把循环次数放在ecx中。当然这样拷贝的才是真正的内存拷贝,其他的函数都稍微有点牵强;其实我感觉c语言来实现还是比较简单的,就是把输入的数据强制转换成字符来操作,因为在c语言中没有比字符更小的单位了。原创 2015-02-07 11:06:25 · 2544 阅读 · 0 评论 -
linux文件系统之读流程 SYSCALL_DEFINE3(read, xxx)
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count);fget_light();fcheck_files();ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos);1、struct iovec结构体 struct iovec { void __user *iov_base; /*原创 2016-05-05 00:50:55 · 3409 阅读 · 0 评论