zoukankan      html  css  js  c++  java
  • 《Linux及安全》课程实践二

    编译生成新内核

    一、实践原理

    Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合。之所以提供模块机制,是因为Linux本身是一个单内核。单内核由于所有内容都集成在一起,效率很高,但可扩展性和可维护性相对较差,模块机制可弥补这一缺陷。

    Linux模块可以通过静态或动态的方法加载到内核空间,静态加载是指在内核启动过程中加载;动态加载是指在内核运行的过程中随时加载。

    一个模块被加载到内核中时,就成为内核代码的一部分。模块加载入系统时,系统修改内核中的符号表,将新加载的模块提供的资源和符号添加到内核符号表中,以便模块间的通信。

    二、实践过程

    (一)简单模块——姓名

    1.编写模块代码

    #include<linux/init.h> 
    #include<linux/module.h>
     
    MODULE_LICENSE("Dual BSD/GPL");      //声明许可
    
    static char *name="ZhangXin"; 
    static int num=20135301; 
    
    static int __init name_init(void) 
    { 
        printk(KERN_ALERT "name :%s
    ",name);    //输出姓名
        printk(KERN_ALERT "num :%d
    ",num);     //输出学号
        return 0; 
    } 
    
    static void __exit name_exit(void) 
    { 
        printk(KERN_INFO"Name module exit
    ");
    } 
    
    module_init(name_init); 
    module_exit(name_exit); 
    
    module_param(num,int,S_IRUGO);     //可传入参数给num
    module_param(name,charp,S_IRUGO);     //可传入参数给name
    
    //作者等信息声明
    MODULE_AUTHOR("ZhangXin"); 
    MODULE_VERSION("v1.0"); 
    MODULE_DESCRIPTION("A simple module for testing printk and module params");

    2.编译模块

    接下来写Makefile。

    obj-m:=myname.o
    CURRENT_PATH:=$(shell pwd)
    LINUX_KERNEL_PATH:= /usr/src/linux-headers-3.13.0-32-generic
    all:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
    clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

    3、加载测试卸载模块

    (二)进程

    1.编写模块代码

    模块构造函数:执行insmod或modprobe指令加载内核模块时会调用的初始化函数。函数原型必须是module_init(),括号内是函数指针

    模块析构函数:执行rmmod指令卸载模块时调用的函数。函数原型是module_exit()

    模块许可声明:函数原型是MODULE_LICENSE(),告诉内核该程序使用的许可证,不然在加载时它会提示该模块污染内核。一般会写GPL。

    头文件module.h,必须包含此文件;

    头文件kernel.h,包含常用的内核函数;

    头文件init.h包含宏_init和_exit,允许释放内核占用的内存。

    写一个简单的代码,用来向内核输出进程信息。

    #include<linux/kernel.h>
    #include<linux/module.h>
    #include<linux/init.h>
    #include<linux/sched.h>
    
    static struct task_struct *pcurrent;
    
    static int __init print_init(void)
    {
        printk(KERN_INFO "print current task info
    ");
        printk("pid	tgid	prio	state
    ");
        for_each_process(pcurrent){
            printk("%d	",pcurrent->pid);
            printk("%d	",pcurrent->tgid);
            printk("%d	",pcurrent->prio);
            printk("%ld
    ",pcurrent->state);
        }
        return 0;
    }
    static void __exit print_exit(void)
    {
        printk(KERN_INFO "Finished
    ");
    }
    
    module_init(print_init);
    module_exit(print_exit);

    2.编译模块

    接下来写Makefile。

    (其中,all到make的过程中要使用“回车+Tab”键)

    obj-m:=proclist.o
    CURRENT_PATH:=$(shell pwd)
    LINUX_KERNEL_PATH:= /usr/src/linux-headers-3.13.0-32-generic
    all:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
    clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

    第一行:自己写的.c的文件名+”.o”。

    第三行的LINUX_KERNEL_PATH后面要写你自己的内核版本对应的内核源码包地址.

    解释一下make命令:

    make -C $(LINUX_KERNEL_PATH) 指明跳转到内核源码目录下读取那里的Makefile

    M=$(CURRENT_PATH) 表明返回到当前目录继续执行当前的Makefile。

    make之后的执行时这样的:

    生成了好多文件:

    3、加载模块

    sudo insmod proclist.ko

    输入密码后即可。此时已经加载了模块。

    4、测试模块

    Dmesg:看内核信息

     

    三、遇到的问题

    1. linux的内核版本

    uname –r

    位数

    2.内核位置

     

  • 相关阅读:
    HDU1720 A+B Coming
    HDU1390 ZOJ1383 Binary Numbers
    HDU1390 ZOJ1383 Binary Numbers
    HDU2504 又见GCD
    HDU2504 又见GCD
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1020 ZOJ2478 Encoding
    HDU1020 ZOJ2478 Encoding
    HDU2097 Sky数
  • 原文地址:https://www.cnblogs.com/lalacindy/p/5482448.html
Copyright © 2011-2022 走看看