操作系统课程设计:新增Linux驱动程序(重制版)(三)

简介: 操作系统课程设计:新增Linux驱动程序(重制版)

7.2小组整合思路

题目1与题目4存在的共同点是:在进行内核的编译之前需要修改内核中的文件。题目2与题目3存在的共同点是:需要编译内核,在编译完成的新内核进行模块的编译。而题目5完全不涉及内核。

因此,整合的总体流程如下:首先修改内核源码文件中涉及到题目1与题目4的部分。接下来,进行长达1~2小时的编译内核、编译模块与安装新内核。然后,进入新的内核,传入题目2与题目3涉及到的源代码文件,安装并卸载相应的模块进行测试。最后,编译并测试题目5涉及到的源代码。

在本文的章节四中,本小组已经事先统一了用同一个版本的Linux发行版与同一个版本的Linux内核源码。因此,整合的过程得到了一定的简化。

题目1涉及到的内核源码的文件包括:

arch/x86/entry/syscalls/syscall_64.tbl

kernel/sys.c

include/linux/syscalls.h

题目4涉及到的内核源码的文件包括:

arch/x86/mm/fault.c

include/linux/mm.h

kernel/kallsyms.c

在替换了这6个文件后,按第四章节的流程操作,对内核进行重新编译。

进入新的内核。

在新的内核中,题目1需要使用程序对内核进行测试。

题目2涉及到的文件包括:super.c、sysfs.c、file.c、Makefile。将这4个文件放在同一个目录下,进行模块编译。

题目3涉及到的文件包括:zombotany_blkdev.c、Makefile。将这2个文件放在同一个目录下,进行模块编译。

题目4涉及到的文件包括:readpfcount.c、Makefile。将这2个文件放在同一个目录下,进行模块编译。利用模块的形式,对缺页中断次数进行了测试。

题目5涉及到的文件包括:share.c、read.c。这2个文件不涉及也不调用内核。在这2个文件中,就可以加入题目1设计到的系统调用。例如,可以系统调用,计算当前图书馆内已有人数的三次方。如图29所示。可以用gcc -c share.c -o share.out 和gcc -c read.c -o read.out直接编译运行。

其余运行结果不再贴图赘述。

7.3编译新内核时遇到的问题与解决思路

因为在完成个人的题目时,反复编译了内核,所以在整合小组工作并重新编译时出现了boot分区不够的情况,不能在boot分区安装新内核,如图30所示。运行df -hl,发现boot分区只开了300M,且空间即将耗尽。所以,在安装新内核之前需要先对boot分区进行扩容。

首先关机,创建新的磁盘,重新开机后将/boot分区取消挂载。对新的磁盘(nvme0n2)分区,执行命令fdist /dev/nvme0n2,创建一个新分区,全部采取默认选项。

运行lsblk命令,查看新磁盘的新分区。对新分区进行格式化 mkfs.ext4 /dev/nvme0n2p1

将旧内核复制到boot_old文件夹(cp -r /boot/ /boot_old),备份旧内核中的文件。之后,把boot分区挂载回来,挂载到新分区。mount /dev/nvme-n2p1 /boot。在挂载完成后,再把boot_old的备份文件复制回来。cp -r /boot_old/. /boot

将永久挂载写入到/etc/fstab里。先执行blkid查看所有分区的uuid。如图33。

打开/etc/fstab,找到nvme0n2p1的分区填入。加入记录:

UUID=5b624350-9fce-495d-934e-650f62cfe189 ext4 /boot defaults 0 1

保存并退出后更新挂载信息。mount -alsblk。可以看到,/boot分区被挂载到了有20GB的新磁盘上。

重新挂载/boot分区后,重新make install安装内核模块。但是,还需要运行grub2-mkconfig -o /boot/grub2/grub.cfg更新引导文件。否则,会出现如下情况:在旧内核中,/boot分区被正确地识别到并挂载到nvme0n2p1分区,但在新内核找不到/boot。更新引导文件后,新内核也能找到/boot分区。再次重启虚拟机,终于可以成功进入新内核。编译新内核时可能遇到的/boot分区不足的情况被通过这种办法成功得以解决。

编译安装新内核过程中还可能遇到的情况如图35:客户机操作系统已禁用CPU。此问题解决办法较为简单:在物理机开机时按f12进入bios,在bios中设置允许虚拟机。若已经设置允许虚拟机,则需要关掉windows defender或腾讯电脑管家或360。当虚拟机占用主机过多资源时就有可能也会出现该情况。

参考文献

[1] https://blog.csdn.net/cxy_chen/article/details/80998510

[2] https://blog.csdn.net/wys7250578/article/details/9045237

[3] https://blog.csdn.net/skywalker_123/article/details/102587813

[4]https://blog.csdn.net/m0_46362426/article/details/118879627

[5]https://forums.pvpgn.pro/viewtopic.php?id=2226

[6]https://stackoverflow.com/questions/61590926/how-to-install-gcc-g-9-on-centos-8-docker-centoslatest

[7]https://communities.vmware.com/t5/VMware-Workstation-Pro/Update-to-Workstation-14-1-2-fails-and-destroys-existing/td-p/2735925

源程序清单

Makefile

ifeq ($(KERNELRELEASE),)
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
  $(MAKE) -C $(KDIR) M=$(PWD) modules
modules_install:
  $(MAKE) -C $(KDIR) M=$(PWD) modules_install
clean:
  rm -rf *.o *.ko .depend *.mod.o *.mod.c Module.* modules.*
.PHONY:modules modules_install clean
else
  obj-m := zombotany_blkdev.o
endif

zombotany_blkdev.c

#include <linux/module.h>
#include <linux/blkdev.h>
#define SIMP_BLKDEV_DISKNAME "zombotany_blkdev"//设备名称
#define SIMP_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR //主设备号
#define SIMP_BLKDEV_BYTES (256*1024*1024)            // 块设备大小为256MB
#define SECTOR_SIZE_SHIFT 9//9个扇区
static struct gendisk * zombotany_blkdev_disk;// gendisk结构表示一个简单的磁盘设备
static struct block_device_operations  zombotany_blkdev_fops = { 
    .owner = THIS_MODULE,//设备主体
};
static struct request_queue * zombotany_blkdev_queue;//指向块设备请求队列的指针
unsigned char  zombotany_blkdev_data[SIMP_BLKDEV_BYTES];// 虚拟磁盘块设备的存储空间
//请求处理函数
static void  zombotany_blkdev_do_request(struct request_queue *q){
    struct request *req;// 正在处理的请求队列中的请求
    struct bio *req_bio;// 当前请求的bio
    struct bio_vec *bvec;// 当前请求的bio的段(segment)链表
    char *disk_mem;      // 需要读/写的磁盘区域
    char *buffer;        // 磁盘块设备的请求在内存中的缓冲区
    while((req = blk_fetch_request(q)) != NULL){//得到请求
        // 判断当前请求是否合法
        if((blk_rq_pos(req)<<SECTOR_SIZE_SHIFT) + blk_rq_bytes(req) > SIMP_BLKDEV_BYTES){//判断地址是否越界访问
            printk(KERN_ERR SIMP_BLKDEV_DISKNAME":bad request:block=%llu, count=%u\n",(unsigned long long)blk_rq_pos(req),blk_rq_sectors(req));//越界访问了,则输出
            blk_end_request_all(req, -EIO);
            continue;//获取下一请求
        }
        //获取需要操作的内存位置
        disk_mem =  zombotany_blkdev_data + (blk_rq_pos(req) << SECTOR_SIZE_SHIFT);
        req_bio = req->bio;// 获取当前请求的bio
        switch (rq_data_dir(req)) {  //判断请求的类型
        case READ:
            // 遍历req请求的bio链表
            while(req_bio != NULL){
                // for循环处理bio结构中的bio_vec结构体数组(bio_vec结构体数组代表一个完整的缓冲区)
                for(int i=0; i<req_bio->bi_vcnt; i++){
                    bvec = &(req_bio->bi_io_vec[i]);
                    buffer = kmap(bvec->bv_page) + bvec->bv_offset;
                    memcpy(buffer, disk_mem, bvec->bv_len);//把内存中数据复制到缓冲区
                    kunmap(bvec->bv_page);
                    disk_mem += bvec->bv_len;
                }
                req_bio = req_bio->bi_next;//请求链表下一个项目
            }
            __blk_end_request_all(req, 0);//被遍历完了
            break;
        case WRITE:
            while(req_bio != NULL){
                for(int i=0; i<req_bio->bi_vcnt; i++){
                    bvec = &(req_bio->bi_io_vec[i]);
                    buffer = kmap(bvec->bv_page) + bvec->bv_offset;
                    memcpy(disk_mem, buffer, bvec->bv_len);//把缓冲区中数据复制到内存
                    kunmap(bvec->bv_page);
                    disk_mem += bvec->bv_len;
                }
                req_bio = req_bio->bi_next;//请求链表下一个项目
            }
            __blk_end_request_all(req, 0);//请求链表遍历结束
            break;
        default:
            /* No default because rq_data_dir(req) is 1 bit */
            break;
        }
    }
}
//模块入口函数
static int __init  zombotany_blkdev_init(void){
    int ret;
    //添加设备之前,先申请设备的资源
     zombotany_blkdev_disk = alloc_disk(1);
    if(! zombotany_blkdev_disk){
        ret = -ENOMEM;
        goto err_alloc_disk;
    }
    //设置设备的有关属性(设备名,设备号,fops指针
    strcpy( zombotany_blkdev_disk->disk_name,SIMP_BLKDEV_DISKNAME);
     zombotany_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
     zombotany_blkdev_disk->first_minor = 0;
     zombotany_blkdev_disk->fops = & zombotany_blkdev_fops;
    //将块设备请求处理函数的地址传入blk_init_queue函数,初始化一个请求队列
     zombotany_blkdev_queue = blk_init_queue( zombotany_blkdev_do_request, NULL);
    if(! zombotany_blkdev_queue){
        ret = -ENOMEM;
        goto err_init_queue;
    }
     zombotany_blkdev_disk->queue =  zombotany_blkdev_queue;
  //初始化扇区数
    set_capacity( zombotany_blkdev_disk, SIMP_BLKDEV_BYTES>>9);
    //入口处添加磁盘块设备
    add_disk( zombotany_blkdev_disk);
    return 0;
    err_alloc_disk:
        return ret;
    err_init_queue:
        return ret;
}
//模块的出口函数
static void __exit  zombotany_blkdev_exit(void){
// 释放磁盘块设备
    del_gendisk( zombotany_blkdev_disk);
// 释放申请的设备资源
    put_disk( zombotany_blkdev_disk);   
// 清除请求队列
    blk_cleanup_queue( zombotany_blkdev_queue);
}
module_init( zombotany_blkdev_init);// 声明模块的入口
module_exit( zombotany_blkdev_exit);// 声明模块的出口
相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
目录
相关文章
|
5天前
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
26 9
|
5天前
|
缓存 运维 网络协议
深入Linux内核架构:操作系统的核心奥秘
深入Linux内核架构:操作系统的核心奥秘
22 2
|
9天前
|
缓存 网络协议 Linux
Linux操作系统内核
Linux操作系统内核 1、进程管理: 进程调度 进程创建与销毁 进程间通信 2、内存管理: 内存分配与回收 虚拟内存管理 缓存管理 3、驱动管理: 设备驱动程序接口 硬件抽象层 中断处理 4、文件和网络管理: 文件系统管理 网络协议栈 网络安全及防火墙管理
31 4
|
8天前
|
安全 网络协议 Linux
Linux操作系统的内核升级与优化策略####
【10月更文挑战第29天】 本文深入探讨了Linux操作系统内核升级的重要性,并详细阐述了一系列优化策略,旨在帮助系统管理员和高级用户提升系统的稳定性、安全性和性能。通过实际案例分析,我们展示了如何安全有效地进行内核升级,以及如何利用调优技术充分发挥Linux系统的潜力。 ####
27 1
|
11天前
|
物联网 Linux 云计算
Linux操作系统的演变与未来趋势####
【10月更文挑战第29天】 本文深入探讨了Linux操作系统从诞生至今的发展历程,分析了其在服务器、桌面及嵌入式系统领域的应用现状,并展望了云计算、物联网时代下Linux的未来趋势。通过回顾历史、剖析现状、预测未来,本文旨在为读者提供一个全面而深入的视角,以理解Linux在当今技术生态中的重要地位及其发展潜力。 ####
|
12天前
|
安全 Linux 数据安全/隐私保护
Vanilla OS:下一代安全 Linux 发行版
【10月更文挑战第30天】
32 0
Vanilla OS:下一代安全 Linux 发行版
|
15天前
|
人工智能 安全 Linux
|
4月前
|
安全 Linux 网络安全
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
|
1月前
|
Unix 物联网 大数据
操作系统的演化与比较:从Unix到Linux
本文将探讨操作系统的历史发展,重点关注Unix和Linux两个主要的操作系统分支。通过分析它们的起源、设计哲学、技术特点以及在现代计算中的影响,我们可以更好地理解操作系统在计算机科学中的核心地位及其未来发展趋势。
|
3月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
109 3