广州站在哪里,定制开发教程,建设人行官方网站下载,公司网站建设杭州图1 Linux系统整体结构 图2 Linux的源代码结构
下面显示一段内核模块代码案例#xff1a;
#include linux/moduLe.h
#include linux/kernel.h
#include linux/intt.h
/*模块的初始化函数lkp_ init()_init是用于初始化的修饰符
*/
static int __init lk…
图1 Linux系统整体结构 图2 Linux的源代码结构
下面显示一段内核模块代码案例
#include linux/moduLe.h
#include linux/kernel.h
#include linux/intt.h
/*模块的初始化函数lkp_ init()_init是用于初始化的修饰符
*/
static int __init lkp_init(void)
{printk( 1Hello ,world!from the kernel space...\n );return 0;
}
/*模块的退出和清理函数1kp_ exit()
*/
static void __exit lkp_exit(void)
{printk( 1Goodbye ,world!leaving kernel space...\n );
}
module_init(lkp_init);
module_exit(lkp_exit);
/*模块的许可证声明GPL
*/
MODULE_ LICENSE(GPL);在此使用了printk0函数该函数是由内核定义的功能和C库中的printf()类似它 把要打印的日志输出到终端或系统日志。字符串中的1是输出的级别表示立即在终端输出。
任何模块都要包含的三个头文件: #include linux/module.h #include linux/kernel.h #incldue linux/init.h 说明: module.h头文件包含了对模块的版本控制; kernel.h包含 了常用的内核函数; init.h包含 了宏__init和__exit宏__init告诉编译程序相关的函数和变量仅用于初始化编译程序将标有__init的所有代码存储到特殊的内存段中初始化结束就释放这段内存。
内核模块的Makefile文件
obj-m:module_example.o #产生module_example模块的目标文件
CURRENT_PATH :$(shell pwd) #模块所在的当前路径
LINUX_KERNEL :$(shell uname -r) #linux内核源代码的当前版本
LINUX_KERNEL_PATH : /usr/src/linux-headers-S(LINUX_KERNEL) #linux内核源代码的绝对路径all:make -C $(LINUX_KERNEL_PATH) M$(CURRENT_PATH) modules #编译模快
clean:make -C $(LINUX_KERNEL_PATH) M$(CURRENT_PATH) clean #清理模块第一行中的obj-m :这个赋值语句的含义是说明要使用目标文件module_example.o建立一个模块最后生成的模块名为module_ example.ko。.0文件是经过编译和汇编而没有经过链接的中间文件。 注: makefile文件中 若某一 行是命令则它必须以一个Tab键开头。
模块插入命令:
$insmod module_ example.ko
模块删除命令:
$rmmod module_ example
查看模块信息的命令:
$dmesg
Linux内核模块与C应用的对比 操作系统接口 OS是如何对系统调用进行处理的? 系统调用发生在用户态当调用了系统调用后就陷入到内核态。如何陷入比如在比如DOS的软中断int 21HLinux下的int 0x80处理器不同指令不同我们统一把他叫做陷入指令。OS比较理智它会在陷入之前先把自己当时执行的CPU现场保存起来然后进行压栈给自己留下退路接下来就是让内核执行一段程序这段程序叫系统调用服务例程比如执行sub1在显示器上输出内核把这种脏活累活于完以后它会理智的撤出就是把堆栈中东西弹出来就行)。 系统调用与一般过程调用有何不同? 系统调用要涉及到CPU状态的转换首先从用户态陷入到内核态在内核执行系统调用服务例程处理结束后返回用户态一般的程序它调用的时候在用户态也可能在内核态只是一个函数调用另外一个函数而已不存在CPU状态的转换 。
Linux各种接口 不管是图形接口还是命令行接口都统称为用户接回因为图形界面只是一种与用户更方便打交道的方式其本质还是一堆实用程序的集合。而库函数如printfopenread等等这些库函数实际上很多也只是穿了件衣服尤其是与硬件或者系统打交道的话并不是库函数干的实际上是操作系统干的这就是系统调用接口。 系统调用与API 系统调用是与具体操作系统相关的而AP1是遵循POSIX标准的Linux的ibc库的函数malloc和free都叫做API其实现都调用了brk系统调用另一方面一个API实现可能会调用好几个系统调用而有些AP甚至不需要任何系统调用比如说strepy函数因为它们不需要内核提供的服务 系统调用-内核的出口 系统调用顾名思义说的是操作系统提供给用户程序调用的一组特殊接口从逻辑上来说系统调用可被看成是一个内核与用户空间进行交互的接口它好比一个中间人把 用户进程请求传达给内核待内核把请求处理完毕后再将处理结果送回给用户空间。 如图为Linux系统中各个子系统相关的工具集在这里可以通过strace命令查看个应用程序所调用的系统调用strace被称为神器它是Linux环境下的一款程序调试工具它可以统计每一个系统调用所执行的时间、被调用的次数和出错的次数例如“strace -c 可执行文件名”它把执行的时间以微妙为单位的每个系统调用平均耗时、调用次数、错误次数以及系统调用名称显示在表格中。 从用户态函数到系统调用 比如在程序中调用fwrite函数,图中①,而fwrite函数在glibc库中调用系统调用write()(图中②)然后从用户态陷入内核态(图中③)查找系统调用表syscall table ( 图中④)在内中中对应的系统调用服务例程为sys_write,然后在内核执行该例程.