Linux操作系统分析实验-文件操作,实验三

一、实验目的

1、 理解Linux中虚拟文件系统的内容

2、 学习编写内核模块的方法

3、 在虚拟文件系统/proc中实现文件操作算法

二、实验内容

编写一个内核模块,在/proc文件系统中增加一个目录hello,并在这个目录中增加一个文件world,文件的内容为hello world。

实验涉及的内核函数

1、在proc中创建目录函数 proc_mkdir

该函数原型为:

struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent);

name:要创建的目录的名称

parent:指向该目录的父目录的指针

返回指向当前目录的指针结构体。

2、创建version文件的函数为proc_create

该函数原型为:

static inline struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops);

第一个参数name为文件名,

第二个参数mode为文件的读写权限,

第三个参数parent为其父目录的结构体指针,第四个参数proc_fops为文件的读写操作结构体。

3、实现内核空间与用户空间的数据传递函数:

copy_to_user()和copy_from_user()这两个函数。

(旧内核是raw_copy_to_user() 和 raw_copy_from_user()这两个函数)

 copy_to_user() 函数的完整形态为

unsigned long copy_to_user(void *to, const void *from, unsigned long count);

函数的作用是将内核空间的数据复制到用户空间。其中

to:目标地址(用户空间)

from:源地址(内核空间)

count:将要拷贝数据的字节数

返回:成功返回0,失败返回没有拷贝成功的数据字节数

4、从 /proc 中删除一个文件函数 remove_proc_entry() 

函数的原型是:

remove_proc_entry(const char *name, struct proc_dir_entry *parent)

name:要删除的文件名

parent :文件在 /proc 文件系统中的位置

三、实验原理

1、/proc 文件系统是Linux上的一种虚拟文件系统,存储的是当前内核运行状态的一系列特殊文件,用户可以通过这些文件查看有关系统硬件及当前正在运行进程的信息。

2、最初开发 /proc 文件系统是为了提供有关系统中进程的信息。但是由于这个文件系统非常有用,因此内核中的很多元素也开始使用它来报告信息或启用动态运行时配置。

用户一般不可以随便在/proc 文件系统中添加信息

3、   /proc 目录下文件详解

(1)内存

/proc/buddyinfo

伙伴系统的信息

/proc/pagetypeinfo

伙伴系统进一步细分信息

/proc/zoneinfo

内存区域使用情况

/proc/slabinfo

内核对象缓存(slab caches)的统计信息

/proc/meminfo

当前内存信息

/proc/vmstat

虚拟内存统计信息

/proc/vmallocinfo

虚拟内存分配信息

/proc/swaps

swap分区使用情况

/proc/mtd

内存设备分区表信息

/proc/dma

DMA(直接内存访问)通道的列表

/proc/mtrr

系统使用的Memory Type Range Registers (MTRRs)

/proc/kpagecount

系统中物理页的引用计数
/proc/kpageflags系统中物理页的标志

(2)I/O

/proc/filesystems

目前系统支持的文件系统

/proc/diskstats

磁盘设备的统计信息

/proc/ioports

当前系统硬件设备使用的IO端口列表

/proc/iomem

I/O 内存映射

/proc/locks

当前被内核锁定的文件

/proc/mounts

当前挂载信息

(3)CPU

/proc/cpuinfocpu相关信息
/proc/loadavg  当前系统负载
/proc/softirqs系统软中断信息
/proc/schedstat调度器信息
/proc/sched_debug调度器debug信息

            

(4)kernel

/proc/cmdline  在引导启动时传递给Linux内核的参数
/proc/crypto内核支持的加密方式
/proc/modules当前系统已经加载的模块(lsmod)
/proc/version内核版本信息
/proc/stat系统和内核的统计信息
/proc/fb内核编译期间帧缓冲信息
/proc/kmsg内核日志信息
/proc/kcore表示系统物理内存,可以用gdb检查内核数据结构的当前状态
/proc/kallsyms内核符号信息,主要用于调试
/proc/timer_list内核各种计时器信息
/proc/timer_stats系统中定时器的使用情况
/proc/sysrq-trigger内核触发器(危险!)
/proc/execdomainsLinux内核当前支持的execution domains

          

(5)other

/proc/interrupts中断表
/proc/uptime系统运行时间
/proc/devices设备信息(主设备号等)
/proc/mdstat 虚拟设备信息(软raid等)
/proc/misc其他的主要设备(设备号为10)上注册的驱动
/proc/cgroupcgroup相关信息
/proc/consoles系统中所有控制台的信息
/proc/keys证书相关
/proc/key-users关于密钥用户的信息,包括密钥使用情况的统计数据

         

4、/proc 目录下的目录

acpi包含高级配置和电源接口(ACPI)相关的信息
bus提供了系统中所有总线和连接到这些总线上的设备的信息
driver包含内核识别的驱动程序的信息。这个目录通常用于内核开发和调试
fs文件系统相关的信息
ipmi包含通过 Intelligent Platform Management Interface (IPMI) 接口收集的硬件监控和管理信息
irq包含中断请求(IRQ)的信息
scsi提供 SCSI 设备的信息
sys是一个非常重要的目录,包含了系统级别的参数和设置
sysvipc包含系统虚拟进程通信(SysV IPC)的相关信息
tty包含了与终端(TTY)设备相关的信息

四、实验步骤

   要求写出实验过程和思路(用文字表述,或画流程图,或写出伪代码 都可以)。

本实验是编写一个内核模块,在/proc文件系统中增加一个目录hello,并在这个目录中增加一个文件world,文件的内容为hello world。实验步骤如下:

(1)利用proc_mkdir()函数创建目录:

          proc_parent = proc_mkdir("hello",NULL);

(2)在/proc目录下有version和softirqs等文件,本实验利用proc_create函数创建一个version文件world :

显然,创建version文件的函数为proc_create,查阅文档可知,该函数原型为:

static inline struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops);

该函数接收4个参数,第一个参数为文件名,第二个参数为文件的读写权限,第三个参数为其父目录的结构体指针,第四个参数为文件的读写操作结构体。

参照/proc/version文件的实现代码和本实验要求,可写出创建world文件的主要代码:

其中,world文件的父目录指针即为先前创建hello目录所返回的指针,proc_fops定义了该文件所能执行的操作,由于本实验只要求读取文件内容,因此只实现了read属性:

其中,read_proc为实现读取文件内容的函数指针,其实现如下:

(4)定义模块的初始化和清理函数

其实现如下:

(5)编写Makefile

为编译该模块,还需编写Makefile文件

五、实验数据及源代码

Proc_hello.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <asm/uaccess.h>static struct proc_dir_entry* proc_parent;
int len, temp;
char* msg; //字符数组static ssize_t read_proc(struct file* filp, char __user* buf, size_t count, loff_t* offp) {//该函数将文件内容通过msg复制给buf,以此实现文件内容的读取。//read_proc为实现读取文件内容的函数指针if (count > temp)count = temp;temp = temp - count;raw_copy_to_user(buf, msg, count);if (count == 0)temp = len;return count;
}static const struct file_operations proc_fops = {//赋予文件world只读的属性.read = read_proc
};void create_new_proc_entry(void) {//create a new directory named hello, and return a pointer point to this dir//创建一个名为hello的新目录,并返回指向该目录的指针proc_parent = proc_mkdir("hello", NULL); //创建一个目录helloif (!proc_parent) //创建目录失败printk(KERN_INFO "Error creating proc entry");//create a file named world, add read attribute to this file using proc_fops//创建一个名为world的文件,使用proc_fops将read属性添加到此文件//world文件的父目录指针即为先前创建hello目录所返回的指针proc_create("world", 0, proc_parent,&proc_fops); //第一个参数为文件名,第二个参数为文件的读写权限,第三个参数为其父目录的结构体指针,第四个参数为文件的读写操作结构体。msg = "hello world\n"; //文件内容len = strlen(msg); //获得字符串msg的长度temp = len;printk(KERN_INFO "1.len = %d", len);printk(KERN_INFO "proc initialized");
}int proc_init(void) { //模块的初始化函数create_new_proc_entry();return 0;
}void proc_cleanup(void) { //模块的退出和清理函数printk(KERN_INFO " Inside cleanup_module\n");remove_proc_entry("hello", proc_parent); //移除目录helloremove_proc_entry("world", NULL); //移除文件world
}module_init(proc_init); //向内核注册模块提供新功能
module_exit(proc_cleanup); //注销由模块提供所有的功能
MODULE_LICENSE("GPL"); //模块具有GUN公共许可证

Makefile文件

ifneq ($(KERNELRELEASE),) obj-m := proc_hello.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build 
PWD := $(shell pwd)
default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif 
clean:$(MAKE) -C $(KERNELDIR) M=$(PWD) clean

六、实验结果分析(截屏的实验结果,与实验结果对应的实验分析)

1、实验结果与实验程序、实验步骤、实验原理的对应分析;

2、实验过程中的问题及原因和解决办法。

首先下载Linux内核版本并解压,然后将proc_hello.c文件拷贝至Linux/fs/proc目录下,由于该目录下原本就有Makefile文件,因此要对原Makefile文件备份后再拷贝本实验中的Makefile:

mv Makefile Makefile.bak

mv my_makefile Makefile

然后,再使用make命令编译模块:

编译成功后,再使用insmod命令安装模块,可以看到该目录下多了一个ko文件,该文件即为编译成功的模块文件。

最后切换至/proc目录,即可看到结果。

出现的问题以及可能出现的问题:

权限问题:

原因:编写和加载内核模块通常需要特权,而非特权用户可能会遇到权限问题。

解决办法:使用 sudo 或在超级用户权限下执行相关操作。

模块加载失败:

原因:可能是由于编译错误、符号冲突等原因引起的。

解决办法:检查模块加载时的日志输出(使用 dmesg 命令),查找错误消息以便识别和解决问题。

七、实验思考题

1、编写一个有两个进程并发运行的程序,并在结尾设定一个死循环,编译完成后让其在后台运行,然后在前台用cat 命令查看/proc目录下的文件/proc/meminfo (当前内存信息)、/proc/vmstat (虚拟内存统计信息)、/proc/vmallocinfo(虚拟内存分配息)、/proc/filesystems(目前系统支持的文件系统)、/proc/locks(当前被内核锁定的文件)、/proc/cpuinfo ( cpu相关信息)和/proc/modules(当前系统已经加载的模块(lsmod))中信息,分析其含义。

创建一个简单的C程序,该程序创建两个并发运行的进程,然后进入死循环。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void processFunction(int processNumber) {for (int i = 0; i < 5; i++) {printf("Process %d: Iteration %d\n", processNumber, i);sleep(1);}
}int main() {pid_t childPid;// 创建第一个子进程if ((childPid = fork()) == 0) {// 子进程1执行的代码processFunction(1);exit(0);}// 创建第二个子进程if ((childPid = fork()) == 0) {// 子进程2执行的代码processFunction(2);exit(0);}// 父进程执行的代码printf("Parent process: Waiting for child processes to finish...\n");// 进入死循环while (1) {// 保持程序运行sleep(1);}return 0;
}

编译这个程序

使用cat命令查看/proc目录下的信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/882004.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐给前端同学的自动化测试库

对于前端开发而言&#xff0c;自动化测试不仅能够提高开发效率&#xff0c;还能确保应用的稳定性和可靠性。而Python提供了多种适用于前端自动化测试的库。这些库能够帮助前端开发者轻松实现UI测试、API测试和性能测试等多种需求。本文将介绍几个Python中常用的前端自动化测试库…

YOLO11改进-模块-引入Histogram Transformer Block(HTB)解决恶劣天气(雨雾雪)

本篇文章将介绍一个新的改进机制——HTB&#xff0c;并阐述如何将其应用于YOLOv11中&#xff0c;显著提升模型性能。在现代计算机视觉任务中&#xff0c;尤其是在目标检测领域&#xff0c;YOLO系列模型因其快速和准确的检测性能而备受关注。随着YOLOv11的提出&#xff0c;我们迎…

CTF(二)

导言&#xff1a; 本文主要讲述在CTF竞赛中&#xff0c;web类反序列化题目unseping。。 靶场链接&#xff1a;攻防世界 (xctf.org.cn) 反序列化漏洞&#xff1a;反序列化漏洞&#xff08;二&#xff09;_fst反序列化 rocksdb 字段值错误-CSDN博客 打开后可以看到&#xff1…

涂鸦智能落地 Koupleless 合并部署,实现云服务降本增效

文&#xff5c;八幡、朵拉 杭州涂鸦智能技术专家 主要研究微服务与可观测、消息引擎、任务调度、数据层中间件等领域。 本文 5389 字 阅读 15 分钟 当前涂鸦通过 Koupleless 的静态合并部署能力&#xff0c;很好地解决了资源浪费问题。 为了进一步提升研发效率&#xff0c;涂鸦…

MYSQL 拼接函数

目录 1、CONCAT 2、CONCAT_WS 1、CONCAT 解释&#xff1a;用于拼接两个或多个字符串成一个字符串。如果任何一个参数为 NULL&#xff0c;则 CONCAT 函数的结果也会是 NULL。 语法格式&#xff1a;SELECT concat(column_name1,column_name2,...) FROM table_name 中文注释&…

关于Docker

文章目录 DockerWSLWMWare虚拟机CentOS7安装dockerdocker基础命令docker数据卷挂载本地目录或文件 Docker Docker是一个快速构建、运行、管理应用的工具。 能够快速部署项目、项目依赖的组件、项目运行的环境。 项目传统的部署方式缺点&#xff1a; 各类环境、组件命令太多&…

具体应用案例:树莓集团助力传统制造业数字化转型

以一家传统制造业企业为例&#xff0c;在树莓集团的支持下&#xff0c;该企业逐步完成了数字化转型&#xff1a; 1. 生产智能化&#xff1a; 通过树莓集团提供的物联网和智能制造解决方案&#xff0c;企业的生产线实现了全面数字化&#xff0c;实时监控设备状态&#xff0c;进行…

CasADi库C++用法整理学习---以NMPC代码为例

参考几个使用方法博客 1 官方文档写的很清楚 对SM&#xff0c;DM&#xff0c;XM数据类型疑惑。什么时候使用什么样的类型&#xff0c;还是都可以&#xff1f; x MX.sym(“x”) 这将创建一个 11 矩阵&#xff0c;即一个包含名为 x 的符号基元的标量。这只是显示名称&#xff…

关键词提取技术:TF-IDF 详解

1. 什么是TF-IDF&#xff1f; TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09; 是一种统计方法&#xff0c;用于评估单词在文档集或语料库中的重要性。它是自然语言处理和信息检索中的核心技术之一。 TF-IDF主要基于以下两个概念&#xff1a; TF&a…

书籍推荐:《从零构建大型语言模型》附免费PDF下载

通过从头开始构建一个大型语言模型&#xff0c;了解如何创建、训练和调整大型语言模型 &#xff08;LLMs&#xff09;&#xff01; 一、构建大型语言模型&#xff08;从头开始&#xff09; 在《构建大型语言模型&#xff08;从头开始&#xff09;》中&#xff0c;你将了解如何…

C++ —— 关于继承(inheritance)

目录 1. 继承的概念及定义 1.1 继承的概念 1.2 继承的定义格式 1.3 继承基类成员访问方式的变化 1.4 类模板的继承 2.基类与派生类的转换 3. 继承中的作用域 3.1 隐藏规则 4. 派⽣类的默认成员函数 4.1 4个常见默认成员函数 4.2 实现⼀个不能被继承的类 5. 继承与友元…

webpack 学习入门

webpack 1. 简介1.1 webpack 是什么1.2 webpack 五个核心概念1.2.1 入口 - Entry1.2.2 出口 - Output1.2.3 Loader1.2.4 插件 - Plugins1.2.6 模式 - Mode 2. webpack 初体验2.1 初始化配置2.1.1. 准备2.1.2. 写代码2.1.3 编译打包应用 3. webpack 开发环境的基本配置3.1 打包样…

HTML(七)表格

https://chatgai.lovepor.cn/ 在HTML中&#xff0c;表格的标准形式如下&#xff1a; <table></table> 使用上面的语言&#xff0c;就已经生成了一个表格&#xff0c;只不过这个表格什么都没有 那么&#xff0c;该如何让表格存在东西呢&#xff1f; 首先&#xf…

springboot 整合spring ai实现 基于知识库的客服问答

rag 需求产生的背景介绍&#xff1a; 在使用大模型时&#xff0c;常遇到的问题之一是模型可能产生幻觉&#xff0c;即生成的内容缺乏准确性。此外&#xff0c;由于大模型不直接访问企业的专有数据&#xff0c;其响应可能会显得泛泛而谈&#xff0c;不够精准或具体&#xff0c;…

基于YOLOv10的农场实时目标检测系统(python+pyside6界面+系统源码+可训练的数据集+也完成的训练模型)

摘要&#xff1a; 基于YOLOv10的农场实时目标检测系统&#xff0c;利用4393张图片&#xff08;3905张训练集&#xff0c;488张验证集&#xff09;进行模型训练&#xff0c;最终开发出一个高效的农场目标检测模型。为了方便用户操作和实时检测&#xff0c;本系统还开发了基于Pyt…

VSCode运行QT界面

VSCode用久了,感觉Qt Creator的写起代码来还是不如VSCode得心应手,虽然目前还是存在一些问题,先把目前实现的状况做个记录,后续有机会再进一步优化。 当前方式 通过QtCreator创建一个CMake项目,然后使用CMake的方式在VSCode中进行编译。 claude给出的建议 左上角的名字会…

SiLM27212 270V 4A/4A 支持高频信号输入 集成自举二极管的高低边门极驱动器

SiLM27212系列选型&#xff1a; SiLM27212LEK-DG SiLM27212EK-DG SiLM27212LCA-DG SiLM27212CA-DG SiLM27212LCB-DG SiLM27212CB-DG SiLM27212系列是一款支持高频信号输入的高低边N沟道MOSFET驱动器&#xff0c;有着优异的性能&#xff0c;广泛应用于各类模…

Linux查看下nginx及使用的配置文件

1、查到nginx进程 ps -aef | grep nginx2、通过进行pid查到nginx路径 pwdx <pid>3、根据路径得到配置文件 path***/nginx -t如下&#xff1a;

MacOS虚拟机安装Windows停滞在“让我们为你连接到网络”,如何解决?

1. 问题描述 MacOS在虚拟机安装win11过程中&#xff0c;停止在“让我们为你连接到网络”步骤&#xff0c;页面没有任何可以点击的按钮&#xff0c;进行下一步操作。 2. 解决方案&#xff08;亲测有效&#xff09; 到达该界面&#xff0c;按下ShiftF10&#xff08;Windows&…

【机器学习】深入浅出讲解贝叶斯分类算法

0. 前言 1.贝叶斯分类器介绍 贝叶斯分类是一类分类算法的总称&#xff0c;这类算法均以贝叶斯定理为基础&#xff0c;故统称为贝叶斯分类。而朴素贝叶斯&#xff08;Naive Bayes&#xff09;分类是贝叶斯分类中最简单&#xff0c;也是常见的一种分类方法。 一些很常见的分类…