Linux内核设计基础(十)之内核开发与总结

(1)Linux层次结构:



(2)Linux内核组成:

主要由进程调度(SCHED)、内存管理(MM)、虚拟文件系统(VFS)、网络接口(NET)和进程间通信(IPC)等5个子系统组成。


(3)与Unix的差异:

  • Linux支持动态加载内核模块
  • 支持对称多处理(SMP)机制
  • Linux内核可以抢占
  • Linux内核并不区分线程和其他的一般进程
  • Linux提供具有设备类的面向对象的设备模型、热插拔事件,以及用户空间的设备文件系统(sysfs)

(4)内核开发的特点:

  • 内核编程时既不能访问C库也不能访问标准的C头文件
  • 内核编程时必须使用GNU C
  • 内核编程时缺乏像用户空间那样的内存保护机制
  • 内核编程时难以执行浮点运算
  • 内核给每个进程只有一个很小的定长堆栈
  • 由于内核支持异步中断、抢占和SMP,因此必须时刻注意同步和并发
  • 要考虑可移植性的重要性

(5)模块的编写及运行:

来个Hello World,程序员的老朋友了。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

/*
 * hello_init 初始化函数,当模块装载时被调用,如果装载成功返回0,
 * 否则返回非零值
 */
static int hello_init(void)
{
	printk(KERN_ALERT "I bear a charmed life.\n");
	return 0;
}

/*
 * hello_exit 退出函数,当模块卸载时被调用
 */
static void hello_exit(void)
{
	printk(KERN_ALERT "Out, out, brief candle!\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Qiushan");
MODULE_DESCRIPTION("A Hello, World Module");

这是最简单的内核模块,hello_init()是模块的入口点,通过module_init()注册到系统,在被装载时被调用。另外所有模块初始化函数必须符合下面的形式:

int my_init(void);

下面是Makefile的示例:

obj-m := hello.o

make -C /kernel/source/location SUBDIRS=$PWD modules

然后执行

sudo make modules_install

sudo insmod hello.ko //装载

sudo rmmod hello //卸载



(6)移植要注意对齐:

如果一个变量的内存地址正好是它长度的整数倍,那它就自然对齐。如,对于一个32位类型的数据,如果它在内存中的地址刚好可以被4整除(也就是最低两位为0),那它就自然对齐。对于RISC,载入未对齐的数据会导致处理器陷入

对齐原则:
  • 对于标准数据类型,地址只要是其长度的整数倍就对齐了。
  • 对于数组,只要按照基本数据类型进行对齐就可以了,随后的所有元素自然能够对齐。
  • 对于联合体,只要它包含的长度最大的数据类型能够对齐就可以了。
  • 对于结构体,只要结构体中每个元素能够正确对齐就可以了。
对于结构体,这里介绍一个例子:

struct animal_struct {
	char dog;                   /* 1 byte */
	unsigned long cat;    /* 4 bytes */
	unsigned short pig;  /* 2 bytes */
	char fox;                  /* 1 byte */
};



这可不是每个元素正确对齐。实际上编译器会作如下变动:

struct animal_struct {
	char dog;                   /* 1 byte */
	u8 __pad0[3];            /* 3 bytes */
	unsigned long cat;     /* 4 bytes */
	unsigned short pig;   /* 2 bytes */
	char fox;                    /* 1 byte */
	u8 __pad1;               /* 1 byte */
};

第一个填充__pad0是为了保证cat可以按照4字节对齐,这样自动使其它小对象都对齐了,最后一个填充__pad1是为了填补struct本身的大小,是这个结构体长度能被4整除,这样,由该结构体组成的数组中,每个数组项也就会自然对齐了。

struct animal_struct {
	unsigned long cat;     /* 4 bytes */
	unsigned short pig;   /* 2 bytes */
	char dog;                    /* 1 byte */
	char fox;                     /* 1 byte */
};








Linux内核设计基础(十)之内核开发与总结,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。