本文共 2877 字,大约阅读时间需要 9 分钟。
Linux内核模块与_proc文件系统
2007年第1期福建电脑
163
Linux内核模块与/proc文件系统
文运平,韩秀娟
(河南理工大学河南焦作454000)
【摘要】:/proc文件系统是一个伪的文件系统,就是说它是一个实际上不存在的目录,它并不存在于某个磁盘上,而是由核心在内存中产生。本文就是利用Linux模块机制允许用户动态的修改内核、加载自己编写的程序,获取进程状态。
:Linux文件系统内核模块【关键字】
1.引言
加载自己编写的Linux模块机制允许用户动态的修改内核、
程序,而不用每次都编译内核。这种机制极大的改善了Linux的灵活性。/proc文件系统是一个伪的文件系统,就是说它是一个
它并不存实际上不存在的目录,因而这是一个非常特殊的目录。
这个目录用于提供在于某个磁盘上,而是由核心在内存中产生。
关于系统的信息。通过/proc,可以用标准Unix系统调用(比如open()、read()、write()、ioctl()等等)访问进程地址空间。事实上,So-larisps(1)命令正是利用/proc获取进程状态2.Linux内核模块
加载自己编写的Linux模块机制允许用户动态的修改内核、
程序,而不用每次都编译内核。这种机制极大的改善了Linux的灵活性。Linux模块可分为静态可加载模块和动态可加载模块,一旦加载入内核,模块就和内核具有相同的权利。
模块可以单独编译成目标代码,这样模块就是一个目标文件。它可以根据用户的实际需要,在系统启动后由用户自己动态的加载到内核中。当不在需要模块时,用户也可以动态的将其卸载处内核。
加载和卸载模块由两种方式:
1.根用户(root)可以通过insmod和rmmod命令显示的将模块载入或从内核中将它卸载。
2.内核也可载需要时,请求守护进程(kerneld)加载和卸载模块。
内核中有一个变量叫module_list,定义载/linux/include/lin-ux/module.h中,其定义的原型为:externstructmodule*mod-ule_list;它是一个全局变量,每当用户将一个模块加载到内核中
每当内时,这个模块就会被添加到由module_list形成的链表中。
核要使用到这个用户加载的模块所提供的函数时,内核就会去检索这个链表,找到这个模块,然后再使用到其提供的函数或变量。
每个模块都可以输出(export)一些变量和函数,供其他模块或核心代码调用。当然这些模块也可以使用已经加载到内核中的模块提供的函数和变量。模块可通过符号表(symboltable)使用核心资源,内核将资源登记再符号表中。当模块加载时,内核利用符号表来解决模块的资源引用问题。Linux允许模块堆栈
当模块(modulestacking),即一个模块可请求其他模块为之服务。
加载入内核时,系统将新加载模块提供的资源和符号加到内核符号表中。通过这种通信机制,新载入的模块可以访问已加载的模块提供的资源。3.相应的数据结构
与模块有关的重要数据结构主要有下面几个:structmod-ule,structmodule_symbol,structmodule_info,structmodule_ref。
从模块功能上来看,structmodule这个结构体用来完成记录模块的信息,及模块间的相互关系,而其他几个结构体用来完成将模块动态的连接入核心。
structmodule有一个指针指向它对应的structmodule_symbol和structmod-ule_ref.
structmodule{
unsignedlongsize_of_struct;
structmodule*next;/*由于模块在系统中是以单向链表的形式存储的,该指针指向链表中当前模块的下一个模块。变量module_list的指针始终指向链表头,通过next指针*/
/*可以遍历所有加载到系统中的模块*/constchar*name;/*指向模块的名字*/
unsignedlongsize;/*模块的大小,以页为单位*/
union{
atomic_tusecount;longpad;}uc;
unsignedlongflags;unsignednsyms;unsignedndeps;
structmodule_symbol*syms;/*指向该模块对应的符号表*/
structmodule_ref*deps;/*它和refs用来记录模块之间的引用关系,引用该模块的所有模块形成一个链表*/
structmodule_ref*refs;
int(*init)(void);/*模块的初始化函数*/void(*cleanup)(void);/*模块的卸载函数*/
conststructexception_table_entry*ex_table_start;conststructexception_table_entry*ex_table_end;#ifdef__alpha__;unsignedlonggp;#endif
conststructmodule_persist*persist_start;conststructmodule_persist*persist_end;int(*can__unload)(void);intrunsize;
constchar*kallsyms_start;constchar*kallsyms_end;constchar*archdata_start;constchar*archdata_end;ocnstchar*kernel_data;}
结构体module_symbol,结构体module_ref和结构体mod-ule_info是三个非常重要的数据结构,他们分别包含两方面的信息:符号信息和引用信息
用户输入命令lsmod,insmod,rmmod,ksyms等,这些命令行实际上是系统提供给用户以操作和查询模块的应用程序名,在运行过程中将涉及到相关的与模块有关的系统调用。这些系统调用又集中体现在五个相关函数中,这五个函数如下:
Sys_creat_module为模块分配空间,将模块链入系统的模块链中
Sys_init_module初始化模块,修正指针使模块正常工作Sys_delete_module从系统模块链中删除模块,释放内存空间
Sys_query_module在模块链表中查询模块
Sys_get_kernel_syms将系统的所有符号表全部取出到用户空间
这几个函数都位于/linux/kernel/module.c源文件中,在这个源文件的开始就定义了模块的核心数据结构。接着又定义了模块的头指针structmodule*modlue_list=&kernel_module;通过这个头指针系统,可以遍历所有加载内核的模块。如果模块加载失败,整数型staticintkmalloc_failed将为真。
转载地址:http://kejdv.baihongyu.com/