将一组与模块相关的命令加载进内核

完成功能类似2,打印proc下的相关信息。但是不用重新编译内核,节省时间,更为灵活

内核模块介绍

模块是在内核空间运行的程序,实际上是一种目标文件,不能单独运行但其代码可在运行时链接到系统中作为内核的一部分运行或卸载。Linux内核模块是一个编译好的、具有特定格式的独立目标文件,用户可通过系统提供的一组与模块相关的命令将模块加载进内核,当内核模块被加载后,它有如下特点:

  1. 与内核一起运行在相同的内核态和内核地址空间;
  2. 运行时与内核具有同样的特权级;
  3. 可方便地访问内核中的各种数据结构。

    此外,内核模块还可以很容易地被移出内核,当用户不再需要某模块功能时,可以将它从内核卸载以节省系统主存开销。

一个典型的内核模块应包含如下几个部分:

1)头文件声明。其中module.h和init.h是必不可少的。module.h包含加载模块时需要的函数和符号定义;init.h中包含模块初始化和清理函数的定义。如果在加载时允许用户传递参数,模块中还应包含moduleparam.h头文件。

2)模块许可声明。从内核2.4.10版本开始,模块必须通过MODULE_LICENSE宏声明此模块的许可证,否则在加载此模块时会显示“kernel tainted”(内核被污染)的警告信息。从linux/module.h文件中可看到,被内核接受的许可证有GPL、GPL v2、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"); //模块许可声明

Makefile

注意modules下以tab开头

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 mymodules

linux动态内核模块编程-3的更多相关文章

  1. Linux内核模块编程——Hello World模块

    Linux内核模块编程 编程环境 Ubuntu 16.04 LTS 什么是模块 内核模块的全称是动态可加载内核模块(Loadable Kernel Modul,KLM),可以动态载入内核,让它成为内核 ...

  2. linux内核模块编程实例

    linux内核模块编程实例 学号:201400814125 班级:计科141 姓名:刘建伟 1.确定本机虚拟机中的Ubuntu下Linux的版本 通过使用命令uname -a/uname -r/una ...

  3. 《linux内核设计与分析》内核模块编程

    内核模块编程 一.准备工作 虚拟机:VMware Workstation 12操作系统:ubuntu当前内核版本:linux-headers-4.4.0-22-generic 二.有关于内核模块的知识 ...

  4. linux实践——内核编程 基础模块

    一.内核模块的概念 Linux模块(module)是一些可以作为独立程序来编译的函数和数据类型的集合.内核模块给我们带来的便利是模块本身并不被编译进内核文件,可在内核运行期间动态的安装或卸载.因为如果 ...

  5. Linux 动态库剖析

    进程与 API 动态链接的共享库是 GNU/Linux® 的一个重要方面.该种库允许可执行文件在运行时动态访问外部函数,从而(通过在需要时才会引入函数的方式)减少它们对内存的总体占用.本文研究了创建和 ...

  6. 【linux草鞋应用编程系列】_4_ 应用程序多线程

    一.应用程序多线程     当一个计算机上具有多个CPU核心的时候,每个CPU核心都可以执行代码,此时如果使用单线程,那么这个线程只能在一个 CPU上运行,那么其他的CPU核心就处于空闲状态,浪费了系 ...

  7. 《Linux/Unix系统编程手册》读书笔记3

    <Linux/Unix系统编程手册>读书笔记 目录 第6章 这章讲进程.虚拟内存和环境变量等. 进程是一个可执行程序的实例.一个程序可以创建很多进程. 进程是由内核定义的抽象实体,内核为此 ...

  8. linux动态库编译和使用

    linux动态库编译和使用详细剖析 引言 重点讲述linux上使用gcc编译动态库的一些操作.并且对其深入的案例分析.最后介绍一下动态库插件技术, 让代码向后兼容.关于linux上使用gcc基础编译, ...

  9. Linux下的编程实战【转】

    一篇比较不错的文章, 降到了 makefile make , gcc编译器,GDB调试器, Linux文件系统,Linux文件API,.C语言库函数(C库函数的文件操作实际上是独立于具体的操作系统平台 ...

随机推荐

  1. demo(幸福大转盘)总结

    百度推广首页demo 在<head>与</head>之间加入代码 <link rel="shortcut icon" href="favic ...

  2. html5学习笔记(audio)

    来源于<HTML5高级程序设计> audio api <audio controls> controls告诉浏览器显示播放控件 不指定 type 浏览器自解 oggMP3 ty ...

  3. Secret Code

    Secret Code 一.题目 [NOIP模拟赛A10]Secret Code 时间限制: 1 Sec  内存限制: 128 MB 提交: 10  解决: 6 [提交][状态][讨论版] 题目描述 ...

  4. hdu 5243 Homework

    Homework Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  5. 插入排序—希尔排序(Shell`s Sort)原理以及Java实现

    希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进.希尔排序又叫缩小增量排序 基本思想: 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录 ...

  6. C# var声明变量解析

    C# var声明变量解析: 在C#3.0中提供了一种新的声明变量的方式,这就是var. 通过这个关键字,在声明变量时就无需指定类型了,变量类型是在初始化时由编译器确定的.代码如下: var ss = ...

  7. js字符串和数组操作,容易混淆的方法总结(slice、substring、substr、splice)

    平时工作中,很少静下心来总结基础知识,总觉得自己会用了,有点飘了,直到碰壁之后才懂得基础知识的重要性.大牛告诉我,一次写对,是不是可以不用F12去调试了?是不是省了时间?简直是面红耳赤,无地自容.在这 ...

  8. python2和python3 print输出不换行

    python2 print不换行 在print最后加上一个逗号,会把两个输出打印在同一行,不过两个输出之间有一个空格的间隔,例如:print '{0}'.format(123),print '{0}' ...

  9. ecshop彻底去版权把信息修改成自己的全教程

    前台部分: 一.去掉头部title部分的ECSHOP演示站-Powered by ecshop 1.问题:“ECSHOP演示站”方法:在后台商店设置 – 商店标题修改2.问题:“ Powered by ...

  10. Unity 5 官方打包管理工具 Asset Bundle Manager

    http://blog.csdn.net/suifcd/article/details/51570003 Unity5在Asset bundle 打包管理上采用了全新的方式,不需要再对每个文件进行MD ...