调试手段、内存分配、字符设备的创建

写点复习笔记,为面试找工作准备。加油!!!

内核调试手段

1.printk()

2.在头文件上定义#define DEBUG打开内核的调试信息(本质上还是printk)

3.产生oops的时候根据oops输出信息分析。可根据calltrace信息判断具体调用函数导致oops

4.可以通过文件系统中的相关文件夹来查看设备运行信息

内存分配

尽管内存的最小可寻址单位为字节,但是内核还是把物理页作为内存管理的基本单位,应为mmu通常以

页为单位进行处理。内存分配中的page和具体的物理页相关,和虚拟页无关。内核仅仅用这个数据结构

来描述物理内存本身,而不是描述包含在其中的数据。

内存分配的三个接口函数

1.以页为单位分配

a.struct page *alloc_page(gfp_t gfp_mask, unsigned int order)

分配2order次幂的连续物理页,返回指向第一个页的page指针

b.unsigned long _get_free_pages(gfp_t gfp_mask, unsigned int order)

和a类似,只不过返回的是第一个也的逻辑地址

把pages改成page就变为分配单独一页。

2.以字节为单位获取内存

a.void *kmalloc(size_t size, gfp_t flags)

分配size大小的内存块,并且所分内存区域在物理上是连续的。(和用户空间的malloc用法类似)

但是kmalloc有个上限,最大只能分配128Kb的内存。

b.void *vmalloc(unsigned long size)

工作方式类似kmalloc,只不过分配的内存虚拟地址是连续的。通过分配非连续的物理内存块,再

修正页表,把内存映射到 逻辑地址控件的连续区域中。不得已时才使用。

3.slab

内核需要频繁的分配和回收数据结构,这通过slab来实现。内存的分配也是通过slab来实现的,建

立在slab层之上。

slab把不同的对象以组划分,例如进程描述符放在同一个slab组中,索引节点(struct inod)放在同一

个slab组中。这个太复杂以后在研究了。

热插拔udev(mdev)

mdev是udev的简化版本,busybox支持的是mdev。通过mdev和内核的class结合可以自动在/dev下

创建设备文件节点。现在先解释mdev的工作原理。

mdev创建设备节点文件的两种方式

a.mdev -s(在启动脚本rcS中)

通过执行mdev -s指令后,mdev会遍历/sys/block和/sys/class目录下的文件夹,并且会搜索子文件夹中

的dev文件。如果找到dev文件,则通过dev文件中的主设备号:从设备号,并以包含dev文件的文件夹名

作为设备名称在/dev目录下创建设备节点。例如/sys/class/i2c-dev/i2c-0/dev,并且dev内容为89:0,则

mdev搜索后会自动在/dev目录下创建一个主设备号为89,从设备号为0,设备名称为i2c-0的设备节点。

2.uevent

uevent会导致mdev的执行。在想系统调用device_create()函数的时候是产生uevent,会导致mdev的执行。

mdev会根据device_path路径下的dev文件中的信息创建设备节点,并且设备名称以device_path中最后包

含dev文件的文件夹名命名。

具体mdev内容可以参考这篇博文

http://blog.chinaunix.net/space.php?uid=23089249&do=blog&id=34495

字符驱动注册过程

1.分配设备号

a.int register_chrdev_region(dev_t first, unsigned int count, char*name)

用于静态分配设备号,first是主设备号(实现定义好),count是设备数目(决定次设备号,从0开始),name

会出现子啊/proc/devices中的设备名称。

b.int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name)

用于动态分配设备号,dev和firstminor用于存放返回值。dev表示申请到的主设备号,firstminor为次设备号

通常从0开始。

2.注册字符设备

a. int register_chardev(unsigned int major, const char *name, struct file_operation *fops)

这个是注册字符驱动的老接口,major是主设备号,name是会在/proc/device中出现的驱动名称。

fops是这类设备默认的操作方法集。

b.cdev_init()和cdev_add()函数相结合

通过cdev_init()来初始化一个cdev结构体,通过cdev_add函数添加到内核。

a和b方法的区别:老方法在调用字符驱动注册函数后,会自动给指定的主设备注册256个次设备,次设备号为0~255,

即使系统没有这么多的此设备,所以比较浪费。而b方法会按照参数中给定的此设备数生成次设备。

3.设备文件节点

a.通过mknod创建

直接在/dev目录下,根据设备号创建设备文件节点

b.通过udev(mdev)和class动态创建

busybox中的udev就是mdev,mdev可自动创建设备文件节点。这里介绍class的具体用法。

class需要使用到两个函数:

1.class_create

2.device_create

通过class_create创建class结构体

然后通过函数device_create在/sys/class目录下生成相关目录和dev文件,并且触发uevent导

致mdev执行,然后mdev根据相关信息在/dev下创建设备节点文件。

mdev的原理可以在这里找到:
http://www.cnblogs.com/hnrainll/archive/2011/06/10/2077435.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值