操作系统实验一

操作系统第一次实验

Topic: 操作系统概念验项目1:Linux内核模块
Requirements:

  1. 掌握Linux内核模块的加载和卸载方法
  2. 了解内核数据结构的概念和使用方法。
  3. 学习如何使用内核链接列表数据结构。

Procedure
实验环境
为了确保完成本次实验,首先需要准备实验环境,本实验使用Ubuntu系列的Linux虚拟机进行操作。
在这里插入图片描述

实验内容

第一部分 - 创建内核模块

  1. 打开终端应用程序,进入Linux虚拟机的命令行界面。
    在这里插入图片描述

  2. 使用编辑器创建一个新的C源文件,命名为simple.c,并将以下代码复制到文件中:

// 包含必要的内核头文件
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

// 模块初始化函数
int simple_init(void) {
    // 向内核日志输出加载模块信息
    printk(KERN_INFO "Loading Module\n");
    return 0;
}

// 模块清理函数
void simple_exit(void) {
    // 向内核日志输出移除模块信息
    printk(KERN_INFO "Removing Module\n");
}

// 定义模块的初始化和清理函数,在加载和卸载模块时会调用这些函数
module_init(simple_init);
module_exit(simple_exit);

// 模块许可证类型声明为GPL
MODULE_LICENSE("GPL");
// 模块描述信息
MODULE_DESCRIPTION("Simple Module");
// 模块作者姓名
MODULE_AUTHOR("ALI");

在这里插入图片描述

Makefile文件内容如下:

在这里插入图片描述

  1. 保存并退出编辑器。

  2. 使用命令make命令编译源代码,生成内核模块文件simple.ko。在这里插入图片描述
    编译完后ls命令查看生成的文件
    在这里插入图片描述

  3. 使用命令lsmod查看当前加载的内核模块,确认simple模块未加载。在这里插入图片描述

  4. 使用命令sudo insmod simple.ko将simple模块加载到内核中。在这里插入图片描述

  5. 使用命令lsmod再次查看已加载的内核模块,确认simple模块已加载。在这里插入图片描述

  6. 使用命令dmesg查看内核日志缓冲区中的信息,确认模块已加载。在这里插入图片描述

  7. 使用命令sudo rmmod simple将simple模块从内核中卸载。在这里插入图片描述

  8. 使用命令dmesg -c清空内核日志缓冲区。在这里插入图片描述

第二部分:使用内核数据结构

  1. 定义结构体:首先,我们需要定义一个结构体,其中包含要插入到链表中的元素。在这个实验中,我们定义了一个名为"birthday"的结构体,包含了day、month、year和list_head类型的成员变量。

  2. 创建链表头:使用LIST_HEAD()宏来创建一个链表头对象,作为链表的引用。

  3. 创建并初始化结构体实例:使用kmalloc()函数分配内核内存,并创建并初始化一个birthday结构体实例。然后,使用INIT_LIST_HEAD()宏来初始化结构体中的list成员。

  4. 将元素插入链表:使用list_add_tail()宏将该实例添加到链表的末尾。

  5. 遍历链表:使用list_for_each_entry()宏来遍历链表,并在每次迭代中对每个元素进行操作。

  6. 从链表中删除元素:使用list_del()宏从链表中删除元素,并使用kfree()函数释放之前使用kmalloc()分配的内存。

代码如下:

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/slab.h>

struct birthday {
    int day;
    int month;
    int year;
    struct list_head list; // 链表节点,在每个结构体实例中都包含一个list_head类型的成员
};

static LIST_HEAD(birthday_list); // 定义一个链表头,作为链表的入口

int simple_init(void) {
    struct birthday *person; // 创建一个birthday结构体指针,用于存储要插入链表的数据
    struct birthday *ptr; // 创建一个birthday结构体指针,用于遍历链表

    printk(KERN_INFO "Loading Module\n");

    // 创建并初始化结构体实例
    person = kmalloc(sizeof(*person), GFP_KERNEL); // 分配内存空间来存储结构体实例
    person->day = 11; // 设置结构体实例的成员变量值
    person->month = 4;
    person->year = 2001;
    INIT_LIST_HEAD(&person->list); // 初始化结构体实例的list成员,将其设置为空链表
    list_add_tail(&person->list, &birthday_list); // 将结构体实例添加到链表的尾部

    // 遍历链表并输出到内核日志缓冲区
    list_for_each_entry(ptr, &birthday_list, list) { // 遍历整个链表
        printk(KERN_INFO "Birthday: %d/%d/%d\n", ptr->day, ptr->month, ptr->year); // 输出每个节点的生日信息到内核日志缓冲区
    }
    return 0;
}

void simple_exit(void) {
    struct birthday *ptr, *next; // 创建两个birthday结构体指针,用于遍历链表和释放内存
    printk(KERN_INFO "Removing Module\n");

    // 从链表中删除元素并释放内存
    list_for_each_entry_safe(ptr, next, &birthday_list, list) { // 安全地遍历整个链表(删除节点时也能正常进行)
        list_del(&ptr->list); // 将当前节点从链表中删除
        kfree(ptr); // 释放当前节点占用的内存空间
    }
}
module_init(simple_init); // 模块加载时调用simple_init函数进行初始化
module_exit(simple_exit); // 模块卸载时调用simple_exit函数进行清理

MODULE_LICENSE("GPL"); // 模块的许可证
MODULE_DESCRIPTION("Simple Module"); // 模块的描述信息
MODULE_AUTHOR("ALI"); // 模块的作者信息

用vim命令上面代码写入到simple.c中,内容如下:
在这里插入图片描述

Makefile内容如下:在这里插入图片描述

  1. 编译和加载模块:使用提供的Makefile编译模块,并使用insmod命令加载模块。
    在这里插入图片描述
    在这里插入图片描述
    使用insmod加载模块
    在这里插入图片描述

  2. 检查内核日志缓冲区:使用dmesg命令查看内核日志缓冲区中的输出,确保链表的构建和操作正确执行。
    在这里插入图片描述

  3. 卸载模块:使用rmmod命令卸载模块。

在这里插入图片描述

  1. 检查链表是否被删除:使用dmesg命令检查内核模块卸载后是否已删除链表。

在这里插入图片描述


Results:

  1. 在第一部分的实验中,成功创建了一个简单的内核模块,并通过命令加载和卸载模块。在内核日志缓冲区中可以看到相应的加载和卸载信息。
  2. 在第二部分的实验中,成功创建了一个包含五个struct birthday元素的链表,并通过遍历链表将内容输出到内核日志缓冲区。在模块退出后,链表中的元素被成功删除,并将内存返回给内核。

实验总结:

  1. 通过本实验,我了解了操作系统的基本概念和组织结构,以及Linux操作系统的特点、用户界面和常用的shell命令。我还学会了如何创建和加载内核模块,并使用内核数据结构进行操作。
  2. 通过这个实验,我对操作系统的开发过程有了更深入的了解,也提高了对Linux内核模块的理解和应用能力。这对我今后的学都具有重要意义。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值