HDU操作系统实验二:Linux 内核模块编程(网安,基于华为云arm架构)

实验介绍

本实验通过编写Linux内核模块,加载内核模块,并测试结果,了解Linux内核模块的概念、编译方法、安装和测试方法。

任务描述

  • Linux 内核模块的基本概念
  • Linux 内核模块的编写方法
  • Linux 内核模块的加载和移除
  • Linux内核模块的测试方法

实验目的

  • 学习掌握Linux 内核模块的编写
  • 学习掌握Linux 内核模块的加载和移除
  • 学习掌握测试Linux内核模块

实验内容

1. 掌握Linux 内核模块的基本概念

1.1 解Linux内核模块的基本概念。

1.2 网上查找资料(https://tldp.org/LDP/lkmpg/2.6/html/index.html),了解Linux内核模块的编写方法。

2. 设计和添加Linux 内核模块

2.1 打印“hello,world”

a.切换至home目录(该目录初始应该是空目录)下输入“mkdir hello”新建hello文件,“cd hello”进入hello文件。
b.输入"vim myhello.c",输入以下代码

#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>

static int  hello_init(void)
{
        printk(KERN_ALERT"hello,word\n");
        return 0;
}
static void  hello_exit(void)
{
        printk(KERN_ALERT"goodbye\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

保存并退出(“esc”退出编辑模式,“:wq”保存并退出)
c.输入"vim Makefile",输入以下代码

obj-m :=hello.o
hello-objs:=myhello.o
KDIR :=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default:
        make -C $(KDIR) M=$(PWD) modules//make前面为Tab,并不是空格,直接复制需要改下
clean:
        make -C $(KDIR) M=$(PWD) clean

保存并退出(“esc”退出编辑模式,“:wq”保存并退出)
d.输入“make”,进行模块编译,如果报错很可能是代码格式问题,请仔细检查,一段代码前不是空格(直接“CV大法”导致的后果)
e.输入“insmod hello.ko”,加载模块
f.输入"dmesg",查看

g.输入“rmmod hello”,卸载模块

2.2 设计一个带参数的模块,其参数为某个进程的PID号,模块的功能是列出该进程的家族信息,包括父进程、兄弟进程和子进程的程序名、PID号、进程状态。

a.切换至home目录下输入“mkdir test1”新建test1文件,“cd test1”进入test1文件。
b.输入"vim module1.c",输入以下代码

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
static pid_t pid=1;
module_param(pid, int, 0644);

static int module1_init(void)
{
    struct task_struct *p;
    struct list_head *pp;
    struct task_struct *psibling;
    //当前进程的PID
    p = pid_task(find_vpid(pid),PIDTYPE_PID);
    printk("me: %d %ld %s \n",p->pid,p->state,p->comm);

    //父进程
    if(p->parent == NULL){
            printk("No Parent\n");
    }
    else{
            printk("Parent:%d %ld %s \n",p->parent->pid,p->parent->state,p->parent->comm);
    }

    //兄弟进程
    list_for_each(pp,&p->parent->children)
    {
            psibling = list_entry(pp,struct task_struct,sibling);
            printk("Brother %d %ld %s \n",psibling->pid,psibling->state,psibling->comm);
    }

    //子进程
    list_for_each(pp,&p->children)
    {
            psibling = list_entry(pp,struct task_struct,sibling);
            printk("Children %d %ld %s \n",psibling->pid,psibling->state,psibling->comm);
    }
    return 0;
}

static void module1_exit(void)
{
    printk(KERN_ALERT"goodbye!\n");
}

module_init(module1_init);
module_exit(module1_exit);
MODULE_LICENSE("GPL");

保存并退出(“esc”退出编辑模式,“:wq”保存并退出)
c.输入"vim Makefile",输入以下代码

obj-m := module1.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
        make -C $(KDIR) M=$(PWD) modules
clean:
        make -C $(KDIR) M=$(PWD) clean

保存并退出(“esc”退出编辑模式,“:wq”保存并退出)
d.输入“make”,进行模块编译,如果报错很可能是代码格式问题,请仔细检查,一段代码前不是空格(直接CV导致的后果)
e.输入“insmod module1.ko pid=4”,加载模块
f.输入"dmesg",查看

g.输入“rmmod module1”,卸载模块

2.3 设计一个模块,显示当前系统的名称和版本

a.切换至home目录下输入“mkdir test2”新建test2文件,“cd test2”进入test2文件。
b.输入"vim module2.c",输入以下代码

#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/utsname.h>
#include<linux/module.h>
// 初始化函数
static int hello_init(void)
{
        printk("sysname:%s  \n  version:%s",utsname()->sysname,utsname()->version);
        return 0;
}
// 清理函数
static void hello_exit(void)
{
        printk("goodbye!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

保存并退出(“esc”退出编辑模式,“:wq”保存并退出)
c.输入"vim Makefile",输入以下代码

obj-m := module2.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
        make -C $(KDIR) M=$(PWD) modules
clean:
        make -C $(KDIR) M=$(PWD) clean

保存并退出(“esc”退出编辑模式,“:wq”保存并退出)
d.输入“make”,进行模块编译
e.输入“insmod module2.ko”,加载模块
f.输入"dmesg",查看

这个地方并没有出现我们想要的结果,先别急
g.输入“rmmod module2”,卸载模块,再次输入“dmesg”

卸载模块后结果就出来啦!!!

2.4 设计一个带参数的模块,其参数为指定进程标识符PID和新nice值(优先值),模块功能为修改指定进程的优先级(nice值和prio值)

a.切换至home目录下输入“mkdir test3”新建test3文件,“cd test3”进入test3文件。
b.输入"vim dmodule3.c",输入以下代码

#include<linux/kernel.h>
#include<linux/sched.h>
#include<linux/module.h>
#include<linux/init.h>
#include <linux/moduleparam.h>

MODULE_LICENSE("GPL");

static pid_t pid=1;
static int nice;
module_param(pid,int,0644);
module_param(nice,int,0644);
// 初始化函数
static int hello_init(void)
{
        struct task_struct *p;
        p = pid_task(find_vpid(pid),PIDTYPE_PID);
        printk("当前进程的pid:%d nice:%d ",p->pid,task_nice(p));
        if(nice!=0)
        {
                set_user_nice(p,nice);
                printk("当前进程修改后的pid:%d nice:%d ",p->pid,task_nice(p));
        }
        return 0;
}
// 清理函数
static void hello_exit(void)
{
        printk("goodbye!\n");
}
module_init(hello_init);
module_exit(hello_exit);

保存并退出(“esc”退出编辑模式,“:wq”保存并退出)
c.输入"vim Makefile",输入以下代码

obj-m := dmodule3.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
        make -C $(KDIR) M=$(PWD) modules
clean:
        make -C $(KDIR) M=$(PWD) clean

保存并退出(“esc”退出编辑模式,“:wq”保存并退出)
d.输入“make”,进行模块编译

e.输入“ps -l”,查看当前的进程

f.输入“insmod dmodule3.ko pid=2297 nice=5”(根据查看得到的pid值进行相应赋值),加载模块
g.输入"dmesg",查看

这个地方也没有出现我们想要的结果,先别急
h.输入“rmmod dmodule3”,卸载模块,再次输入“dmesg”

i.输入“ps -l”,再次查看,发现nice值已被修改

(PS:截止本篇完成时间为为止,博主还是有些问题没有解决,比如打印名称和版本这个实验,我们将打印放在初始函数中,但是加载模块后,日志中并没有出现信息,名称和版本的信息是在移除模块之后才在日志中出现,修改nice值实验也同样存在这个问题,希望有知道解决办法或其背后原因的小伙伴在评论区评论)

文章写作时间仓促,如有错误请指正,如有问题请在评论区中提问。

加油!

  • 24
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值