看内核需要的一些语法知识点以及碎片

来源:互联网 发布:比较两组数据的相关性 编辑:程序博客网 时间:2024/06/07 18:49
1.预处理运算符##为宏扩展提供了一种连接实际变元的手段。如果替换文本中的参数用 ##相连,那么参数就被实际变元替换, ##与前后的空白符被删除,如:
#define  paste( front, back )  front ## back从而宏调用paste(name, 1)的结果是建立单词name1。

2.用_init以及 _initdata修饰的数据或者函数在编译阶段会放入特定的段。
_init 修饰的数据放入.init.text 段
_initdata 修饰的数据放入 .initdata 段
这些数据在内核初始化结束之后就会被释放。
#define __init __attribute__ ((__section__ (".init.text")))#define __initdata __attribute__ ((__section__ (".init.data")))

3.__attribute__
__attribute__ ((attribute-list))可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。如对齐方式

struct S {

short b[3];

} __attribute__ ((aligned (8)));

typedef int int32_t __attribute__ ((aligned (8)));


4  do_initcalls()函数

do_initcall函数通过for循环,由__initcall_start开始,直到__initcall_end结束,依次调用识别到的初始化函数。而位于__initcall_start和__initcall_end

之间的区域组成了.initcall.init节,其中保存了由xxx_initcall形式的宏标记的函数地址,如arch_initcall宏,do_initcall函数可以很轻松地取得函数地址并执行其指向的函数。


5.统一编址,ARM使用的是统一编址

外设接口中的IO寄存器(即IO端口)与主存单元一样看待,每个端口占用一个存储单元的地址,将主存的一部分划出来用作IO地址空间,如,在PDP-11中,把最高的4K主存作

为IO设备寄存器地址。端口占用了存储器的地址空间,使存储量容量减小

/* ioremap用于将I/O内存区映射到虚拟地址。参数phys_addr为要映射的I/O内存起始地址,参数size为要映射的I/O内存的大小,返回值为被映射到的虚拟地址 */void *ioremap(unsigned long phys_addr, unsigned long size);

6.register_chrdev(MEM_MAJOR,"mem",&memory_fops)

首先我们在注册函数里面调用了register_chrdev(MEM_MAJOR,"mem",&memory_fops),向内核注册了一个字符设备

第一个参数是主设备号,0代表动态分配,这里的MEM_MAJOR是1。第二个参数是设备的名字,第三个参数是文件操作指针。

完成注册后,在/proc/devices中的第一个字符设备我们就看到了:1 mem。


7.kobject 参考 http://blog.csdn.net/liuhaoyutz/article/details/7480657
kobject是Linux设备模型中最基本的数据结构,代表设备模式的一个基本对象。
kobj_type是kobject的类型,包含了kobject的属性以及对属性的操作接口,不同的kobject可以具有相同的kobj_type。
Kset是一个特殊的Kobject(因此它也会在"/sys/“文件系统中以目录的形式出现),是几个kobject的集合。
kobject的注册是通过调用kobject_init_and_add函数platform_driver_register-->{  drv->driver.bus =&platform_bus_type  driver_register } -->bus_add_driver -->kobject_init_and_add
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,                          struct kobject *parent, const char *fmt, ...)  {          va_list args;          int retval;             kobject_init(kobj, ktype);  //初始化kobject           va_start(args, fmt);          retval = kobject_add_varg(kobj, parent, fmt, args);  //将其注册进sys文件系统,生成相应的目录        va_end(args);             return retval;  }  
fmt这个是将要生成的文件夹的名字,会显示在/sys路径下。此函数执行过程中会调用sysfs_create_dir 在/sys目录下建立kobject相关目录结构以及populate_dir(kobj)->sysfs_create_file(kobj, attr) 建立默认的kobj_type里定义的属性文件其实这个函数的功能和kobject_create_and_add(const char *name, struct kobject *parent) 是一样的。

8.Kset 参考: http://blog.chinaunix.net/uid-20672257-id-3147037.html

kset的主要功能是包容;我们可以认为他是kobject的顶层容器。实际上,在每个kset对象的内部包含了自己的kobject,并且可以用多种处理kobject的方法处理kset。

kobject通过kset组织成层次化的结构,kset是相同类型的kobject的组合。通俗的讲,kobject建立一级的子目录,kset可以为kobject建立多级的层次性的父目录。

struct kset {struct subsystem * subsys; 所在的subsystem的指针struct kobjtype * ktype; 指向该kset对象类型描述符的指针struct listhead list; 用于连接该kset中所有kobject的链表头struct kobject kobj; 嵌入的kobjectstruct  kset_uevent_ops * uevent_ops; 指向热插拔操作表的指针};
包含在kset中的所有kobject被组织成一个双向循环链表,list域正是该链表的头。Ktype域指向一个kobjtype结构,被该kset中的所有kobject共享,
表示这些对象的类型。Kset数据结构还内嵌了一个kobject对象(由kobj域表示),所有属于这个kset 的kobject对象的parent域均指向这个内嵌的对象。
此外,kset还依赖于kobj维护引用计数:kset的引用计数实际上就是内嵌的kobject对象的引用计数。
热插拔事件:在linux系统中,当系统配置发生变化时,如添加kset到系统或移动kobject,一个通知会从内核空间发送到用户空间,这就是热插拔事件。
热插拔事件会导致用户空间中的处理程序(如udev,mdev)被调用,这些处理程序会通过加载驱动程序,创建设备节点等来响应热插拔事件。

对热插拔事件的实际控制是由struct kset_uevent_ops结构中的函数完成的。

       struct kset_uevnt_ops{       int (*filter)(struct kset *kset,struct  kobject *kobj);       const char *(*name)(struct kset *kset, struct kobject *kobj );       int (*uevent)(struct kset *kset,struct  kobject *kobj,struct kobj_uevent *env);}

filter决定是否产生事件,如果返回0,将不产生事件。

name向用户空间传递一个合适的字符串

uevent通过环境变量传递任何热插拔脚本需要的信息,他会在(udev或mdev)调用之前,提供添加环境变量的机会。


device_register和driver_register是通过bus模块的bus_add_device和bus_add_driver实现的。
bus_add_device创建的属性文件放在
/sys/devices/xxx/xxx_device/目录中,然后调用 sysfs_create_link接口,将该device在sysfs中的目录,链接到该bus的devices目录下,例如:
xxx# ls /sys/bus/spi/devices/spi1.0 -l                                                        
lrwxrwxrwx root   root   2014-04-11 10:46 spi1.0 -> ../../../devices/platform/s3c64xx-spi.1/spi_master/spi1/spi1.0

bus_add_driver 创建的目录体现在/sys/bus/xxx/drivers/下,如/sys/bus/spi/drivers/spidev。

9.设备树中断
设备节点利用interrupt-parent 和interrupts 属性描述到中断控制器的中断连接。其中interrupt-parent 属性值为中断控制器节点的指针,#interrupts 属
性值描述可触发的中断信号,其值格式与中断控制器的interrupt-cells 属性值有关。一般#interrupt-cells 属性值为2,interrupts 属性就对应为一对描述硬件中断号和中断触发方式的十六进制值。

0 0
原创粉丝点击