完成功能相似2,打印proc下的相关信息。可是不用从新编译内核,节省时间,更为灵活linux
模块是在内核空间运行的程序,其实是一种目标文件,不能单独运行但其代码可在运行时连接到系统中做为内核的一部分运行或卸载。Linux内核模块是一个编译好的、具备特定格式的独立目标文件,用户可经过系统提供的一组与模块相关的命令将模块加载进内核,当内核模块被加载后,它有以下特色:
1) 与内核一块儿运行在相同的内核态和内核地址空间;
2) 运行时与内核具备一样的特权级;
3) 可方便地访问内核中的各类数据结构。
此外,内核模块还能够很容易地被移出内核,当用户再也不须要某模块功能时,能够将它从内核卸载以节省系统主存开销。shell
一个典型的内核模块应包含以下几个部分:
1)头文件声明。其中module.h和init.h是必不可少的。module.h包含加载模块时须要的函数和符号定义;init.h中包含模块初始化和清理函数的定义。若是在加载时容许用户传递参数,模块中还应包含moduleparam.h头文件。
2)模块许可声明。从内核2.4.10版本开始,模块必须经过MODULE_LICENSE宏声明此模块的许可证,不然在加载此模块时会显示“kernel tainted”(内核被污染)的警告信息。从linux/module.h文件中可看到,被内核接受的许可证有GPL、GPL v二、GPL and additionalrights、Dual BSD/GPL、Dual MPL/GPL、Dual MIT/GPL和Proprietary。
3)初始化和清理函数声明。内核模块必须调用宏module_init和module_exit去注册初始化和清理函数。初始化和清理函数必须在宏module_init和module_exit使用前定义,不然会出现编译错误。这两个函数配对使用,例如当初始化函数申请了一个资源,那么清理函数就应释放这个资源,使得模块不留下任何反作用。除了模块初始化函数和清理函数,还能够根据须要设计编写其它函数。数据结构
注意增长了模块相关的库函数和函数声明,命名为 mymodules.c(与下面的Makefile对应)函数
#include<linux/module.h> #include<linux/init.h> #include <linux/fs.h> #include <asm/uaccess.h> #include<linux/sched.h> static int mymodule_init(void)//模块初始化 { struct file *fp; mm_segment_t fs; loff_t pos; int i,j,k,temp,flag; char cpuinfo[600],cpuinfo_end[]={'f','l','a','g','s'}; char meminfo[200],meminfo_end[]={'B','u','f','f','e','r','s'}; char uptime[20];int runtime; char version[150]; printk("system info print.(by system_call)\n"); /*cpuinfo*/ fp=filp_open("/proc/cpuinfo",O_RDONLY,0); fs=get_fs(); set_fs(KERNEL_DS); pos=0; vfs_read(fp,cpuinfo,sizeof(cpuinfo),&pos); for(i=0;i<5000;i++) { flag=1; for(j=0;j<5;j++) if(cpuinfo[i+j]!=cpuinfo_end[j]) { flag=0; break; } if(flag) break; } cpuinfo[i]='\0'; printk("cpuinfo:\n%s\n\n",cpuinfo); filp_close(fp,NULL); set_fs(fs); /*meminfo*/ fp=filp_open("/proc/meminfo",O_RDONLY,0); fs=get_fs(); set_fs(KERNEL_DS); pos=0; vfs_read(fp,meminfo,sizeof(meminfo),&pos); for(i=0;i<1500;i++) { flag=1; for(j=0;j<7;j++) if(meminfo[i+j]!=meminfo_end[j]) { flag=0; break; } if(flag) break; } meminfo[i]='\0'; printk("meminfo:\n%s\n\n",meminfo); filp_close(fp,NULL); set_fs(fs); /*uptime*/ fp=filp_open("/proc/uptime",O_RDONLY,0); fs=get_fs(); set_fs(KERNEL_DS); pos=0; vfs_read(fp,uptime,sizeof(uptime),&pos); for(i=0;i<20;i++) { if(uptime[i]=='.') break; } uptime[i]='\0'; runtime=0; for(j=0;j<i;j++) { temp=uptime[j]-'0'; for(k=0;k<i-j-1;k++) temp*=10; runtime+=temp; } printk("uptime:\nsystem has already started for %d minutes.\n\n",runtime/60); filp_close(fp,NULL); set_fs(fs); /*version*/ fp=filp_open("/proc/version",O_RDONLY,0); fs=get_fs(); set_fs(KERNEL_DS); pos=0; vfs_read(fp,version,sizeof(version),&pos); version[132]='\0'; printk("version:\n%s\n",version); filp_close(fp,NULL); set_fs(fs); printk("info printed over.\n"); return 0; } static void mymodule_exit(void)//模块清理函数 { printk("module unloading.\n"); } module_init(mymodule_init); //注册初始化函数 module_exit(mymodule_exit); //注册清理函数 MODULE_LICENSE("GPL"); //模块许可声明
注意modules下以tab开头ui
ifneq ($(KERNELRELEASE),) obj-m := mymodules.o#obj-m 指编译成外部模块 else KERNELDIR := /lib/modules/$(shell uname -r)/build #定义一个变量,指向内核目录 PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif
切换root用户,执行如下
make
insmod ./mymodules.ko
lsmod
能够看到模块已安装
设计
dmesg –c
完成后可删除模块
rmmod mymodules3d