当前位置: 首页 > news >正文

【操作系统】实验八 proc文件系统

🕺作者: 主页

我的专栏
C语言从0到1
探秘C++
数据结构从0到1
探秘Linux

😘欢迎关注:👍点赞🙌收藏✍️留言

🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有问题可在评论区提出,感谢支持!!!

文章目录

  • 实验八
      • 实验目的
      • 实验准备
      • 编译内核模块
      • 加载内核模块
      • 查看和操作文件内容
      • 卸载内核模块

实验八

实验目的

通过加载内核模块,为/proc文件系统创建以下内容:

  • 一个名叫proc_test的子目录。
  • 一个名叫current的文件,只读,读出的内容是读它的进程的情况。
  • 一个名叫current_too的链接,指向current。
  • 一个名叫hello的文件,可读可写。读出的内容是上次写的内容前面加两句话。

实验准备

  1. 复制文件到工作目录:
    • 使用将 proc_test.c 文件复制到工作目录。

  1. 进入工作目录:
    • 进入工作目录。

编译内核模块

  1. 编译 proc_test.c 模块:
    • 编写proc_test.c代码
#include <linux/sched.h>
#include <linux/init_task.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>#define MAX_LENGTH 1024static char hello_content[MAX_LENGTH] = "hello world\n";  // 初始化一个长度为 1024 的字符数组,并赋值 "hello world\n"//用于处理对 /proc/proc_test/hello 文件的写操作。它从用户空间接收数据并将其复制到内核空间的 hello_content 数组中,偏移量为12。如果写入的字符数超过了数组长度,会返回错误。
static ssize_t hello_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) {if (count > MAX_LENGTH - 1)  // 如果写入的字符数大于 MAX_LENGTH - 1,则返回错误return -EINVAL;if (copy_from_user(hello_content + 12, buffer, count))  // 将用户空间的数据复制到内核空间的 hello_content 数组中,偏移量为 12return -EFAULT;hello_content[count + 12] = '\0';  // 在 hello_content 数组中写入字符串结束符'\0'return count;  // 返回成功写入的字符数
}
//用于处理对 /proc/proc_test/hello 文件的读操作。它将 hello_content 的内容输出到 seq_file 结构体中,从而在读取文件时显示出来。
static int hello_proc_show(struct seq_file *m, void *v) {seq_printf(m, "%s", hello_content);  // 将 hello_content 的内容输出到 seq_file 结构体 m 中return 0;
}
//用于打开 /proc/proc_test/hello 文件。它调用 single_open 函数来打开文件,并指定 hello_proc_show 函数来显示文件内容。
static int hello_proc_open(struct inode *inode, struct file *file) {return single_open(file, hello_proc_show, NULL);  // 打开 proc 文件,调用 hello_proc_show 函数来显示内容
}
//定义了对 /proc/proc_test/hello 文件的操作集合,包括打开、读取、写入、定位和释放文件。
static const struct proc_ops hello_proc_ops = {.proc_open = hello_proc_open,  // 打开文件操作.proc_read = seq_read,  // 读取文件操作.proc_write = hello_proc_write,  // 写文件操作.proc_lseek = seq_lseek,  // 文件定位操作.proc_release = single_release,  // 释放文件操作
};
//用于处理对 /proc/proc_test/current 文件的读操作。它输出当前进程的相关信息,如进程ID、优先级、进程名等。
static int current_proc_show(struct seq_file *m, void *v) {struct task_struct *cur = current;seq_printf(m, "进程ID: %d\n", cur->pid);  // 输出进程IDseq_printf(m, "优先级: %d\n", cur->prio);  // 输出进程优先级seq_printf(m, "静态优先级: %d\n", cur->static_prio);  // 输出静态优先级seq_printf(m, "正常优先级: %d\n", cur->normal_prio);  // 输出正常优先级seq_printf(m, "策略: %d\n", cur->policy);  // 输出进程调度策略seq_printf(m, "进程名: %s\n", cur->comm);  // 输出进程名return 0;
}
//用于打开 /proc/proc_test/current 文件。它调用 single_open 函数来打开文件,并指定 current_proc_show 函数来显示文件内容。
static int current_proc_open(struct inode *inode, struct file *file) {return single_open(file, current_proc_show, NULL);  // 打开 proc 文件,调用 current_proc_show 函数来显示内容
}
// 定义了对 /proc/proc_test/current 文件的操作集合,包括打开、读取、定位和释放文件。
static const struct proc_ops current_proc_ops = {.proc_open = current_proc_open,  // 打开文件操作.proc_read = seq_read,  // 读取文件操作.proc_lseek = seq_lseek,  // 文件定位操作.proc_release = single_release,  // 释放文件操作
};
//模块的初始化函数,它在内核加载模块时被调用。它创建了一个名为 /proc/proc_test 的目录,并在其中创建了文件 current、current_too 和 hello。
static int __init proc_test_init(void) {struct proc_dir_entry *test_dir;test_dir = proc_mkdir("proc_test", NULL);  // 创建一个目录 /proc/proc_testproc_create("current", 0, test_dir, &current_proc_ops);  // 在 /proc/proc_test 目录下创建一个名为 "current" 的文件proc_symlink("current_too", test_dir, "current");  // 在 /proc/proc_test 目录下创建一个名为 "current_too" 的符号链接,指向 "current"proc_create("hello", 0666, test_dir, &hello_proc_ops);  // 在 /proc/proc_test 目录下创建一个名为 "hello" 的文件,可读可写权限为 0666return 0;
}
//模块的退出函数,它在内核卸载模块时被调用。它移除了之前创建的 /proc/proc_test 目录及其下的文件。
static void __exit proc_test_exit(void) {remove_proc_entry("proc_test/current", NULL);  // 移除 /proc/proc_test 目录下的文件 "current"remove_proc_entry("proc_test/current_too", NULL);  // 移除 /proc/proc_test 目录下的文件 "current_too"remove_proc_entry("proc_test/hello", NULL);  // 移除 /proc/proc_test 目录下的文件 "hello"remove_proc_entry("proc_test", NULL);  // 移除 /proc/proc_test 目录
}MODULE_LICENSE("GPL");  // 指定模块的许可证为 GPL
module_init(proc_test_init);  // 指定模块的初始化函数
module_exit(proc_test_exit);  // 指定模块的退出函数
  • 使用makefile文件编译内核模块。
obj-m:=proc_test.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD       := $(shell pwd)
default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
  • 使用make命令编译

make

加载内核模块

  1. 加载编译后的模块:
    • 使用insmod加载模块。

insmod proc_test.ko

  1. 检查是否加载成功:
  • 使用lsmod命令检查模块是否加载。

lsmod | grep proc_test

  1. 检查是否创建了 /proc/proc_test 目录:
    • 进入/proc目录查看。
cd /proc
ls

  1. 检查 /proc/proc_test 目录下是否创建了三个文件:
    • current、current_too 和 hello。
cd /proc/proc_test
ls

查看和操作文件内容

  1. 查看 current 文件的内容:
    • 使用more命令查看。

more current

  1. 查看 current_too 文件的内容:
    • 使用more命令查看。

more current_too

  1. 查看 hello 文件的内容:
    • 使用more命令查看。

more hello

  1. 写入 hello 文件:
    • 使用echo命令将数据输入到hello文件。

  1. 再次查看 hello 文件的内容:
    • 使用more命令查看。

more hello

卸载内核模块

  1. 卸载加载的内核模块:
    • 使用rmmod卸载模块。

rmmod proc_test

  1. 检查是否卸载成功:
    • 使用lsmod命令检查模块是否卸载。

lsmod | grep proc_test

相关文章:

【操作系统】实验八 proc文件系统

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…...

基于RMF的信贷风控标签客户分层管理

根据美国 数据库营销研究所Arthur Hughes的研究&#xff0c;客户数据库中有3个神奇的要素&#xff0c;这3个要素构成了数据分析最好的指标&#xff1a;最近一次消费 (Recency)、消费频率(Frequency)、消费金额 (Monetary)。这就是RMF模型&#xff0c;RMF模型是用户分层的重要手…...

【MySQL】如何通过DDL去创建和修改员工信息表

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-fmKISDBsFq74ab2Z {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…...

Spring 事务原理一

从本篇博客开始&#xff0c;我们将梳理Spring事务相关的知识点。在开始前&#xff0c;想先给自己定一个目标&#xff1a;通过此次梳理要完全理解事务的基本概念及Spring实现事务的基本原理。为实现这个目标我想按以下几个步骤进行&#xff1a; 讲解事务中的一些基本概念使用Sp…...

creo草绘3个实例学习笔记

creo草绘3个实例 文章目录 creo草绘3个实例草绘01草绘02草绘03 草绘01 草绘02 草绘03...

Modern C++ std::move的实现原理

前言 有一节我们分析了std::bind的实现原理&#xff0c;本节稍作休息分析一个比较简单的std::move 原理 std::move的原理太简单了&#xff0c;一句话&#xff1a;就是把传进来的参数强转为右值引用类型。作用为调用移动构造函数&#xff0c;或移动赋值函数。下面通过例子和代…...

爬虫工作量由小到大的思维转变---<第四十章 Scrapy Redis 实现IP代理池管理的最佳实践>

前言: 本篇是要结合上篇一起看的姊妹篇:爬虫工作量由小到大的思维转变---&#xff1c;第三十九章 Scrapy-redis 常用的那个RetryMiddleware&#xff1e;-CSDN博客 IP代理池的管理对于确保爬虫的稳定性和数据抓取的匿名性至关重要。围绕Scrapy-Redis框架和一个具体的IP代理池中…...

C# 实现 XOR 密码

XOR密码&#xff08;异或密码&#xff09;是一种简单的加密算法&#xff0c;它使用异或&#xff08;XOR&#xff09;操作来对明文和密钥进行加密和解密。 异或操作是一种位运算&#xff0c;它对两个二进制数的对应位进行比较&#xff0c;如果两个位相同&#xff08;都为0或都为…...

【Web前端开发基础】CSS3之空间转换和动画

CSS3之空间转换和动画 目录 CSS3之空间转换和动画一、空间转换1.1 概述1.2 3D转换常用的属性1.3 3D转换&#xff1a;translate3d&#xff08;位移&#xff09;1.4 3D转换&#xff1a;perspective&#xff08;视角&#xff09;1.5 3D转换&#xff1a;rotate3d&#xff08;旋转&a…...

Go实现一个简单的烟花秀效果(附带源码)

在 Go 语言中&#xff0c;要实现烟花秀效果可以使用 github.com/fogleman/gg 包进行绘图。以下是一个简单的例子&#xff1a; 首先&#xff0c;确保你已经安装了&#xff08;有时候需要梯子才可以安装&#xff09; github.com/fogleman/gg 包&#xff1a; go get -u github.c…...

【数学建模】插值与拟合

文章目录 插值插值方法用Python解决插值问题 拟合最小二乘拟合数据拟合的Python实现 适用情况 处理由试验、测量得到的大量数据或一些过于复杂而不便于计算的函数表达式时&#xff0c;构造一个简单函数作为要考察数据或复杂函数的近似 定义 给定一组数据&#xff0c;需要确定满…...

全卷积网络:革新图像分析

一、介绍 全卷积网络&#xff08;FCN&#xff09;的出现标志着计算机视觉领域的一个重要里程碑&#xff0c;特别是在涉及图像分析的任务中。本文深入探讨了 FCN 的概念、它们的架构、它们与传统卷积神经网络 &#xff08;CNN&#xff09; 的区别以及它们在各个领域的应用。 就像…...

ubuntu20.04 格式化 硬盘 扩展硬盘GParted

如何在 Ubuntu 22.04 LTS 上安装分区编辑器 GParted&#xff1f;_gparted安装-CSDN博客 sudo apt install gparted 步骤5&#xff1a;启动GParted 安装完成后&#xff0c;您可以在应用程序菜单中找到GParted。点击它以启动分区编辑器。 通过以上步骤&#xff0c;您可以在Ubun…...

docker的资源限制(cgroup)

前瞻 Docker 通过 Cgroup 来控制容器使用的资源配额&#xff0c;包括 CPU、内存、磁盘三大方面&#xff0c; 基本覆盖了常见的资源配额和使用量控制。 Cgroup 是 ControlGroups 的缩写&#xff0c;是 Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如 CPU、…...

ChatGPT与文心一言:应用示例与体验比较

ChatGPT 和文心一言哪个更好用&#xff1f; 为了更好地感受ChatGPT和文心一言这两款AI助手如何在实际运用中竞相辉映&#xff0c;我将提供一些典型的应用示例。这些示例都取自真实的用户体验&#xff0c;以帮助解释这两种工具如何让日常生活或工作变得更加轻松。 ChatGPT Ch…...

紫光展锐T760_芯片性能介绍_展锐T760安卓核心板定制

展锐T760核心板是一款基于国产5G芯片的智能模块&#xff0c;采用紫光展锐T760制程工艺为台积电6nm工艺&#xff0c;支持工艺具有出色的能效表现。其采用主流的44架构的八核设计&#xff0c;包括4颗2.2GHz A76核心和4颗A55核心设计&#xff0c;内存单元板载可达8GB Ram256GB ROM…...

从动力系统研究看当今数学界

6.3... Milnor’s definition of “attractors” which has been criticized above by us). The work of [KSS2] of asserting the existence of “nice open set” of Ω(p.148) would be likely not verified, for example we think the first sentence “… since f is nont…...

【征服redis15】分布式锁的功能与整体设计方案

目录 1. 分布式锁的概念 2.基于数据库做分布式锁 2.1 基于表主键唯一做分布式锁 2.2 基于表字段版本号做分布式锁 2.3 基于数据库排他锁做分布式锁 3.使用Redis做分布式锁 3.1 redis实现分布式锁的基本原理 3.2 问题一&#xff1a;增加超时机制&#xff0c;防止长期持有…...

MATLAB中实现机械臂逆运动学求解的方法之一是使用阻尼最小二乘法

MATLAB中实现机械臂逆运动学求解的方法之一是使用阻尼最小二乘法。阻尼最小二乘法通常用于处理数值求解问题中的不稳定性和噪声。以下是一个简单的MATLAB代码示例&#xff0c;演示了机械臂逆运动学的阻尼最小二乘法求解&#xff1a; % 机械臂参数 L1 1; % 机械臂长度 L2 1;…...

2024.1.24 GNSS 学习笔记

1.伪距观测值公式 2.载波相位观测值公式 3.单点定位技术(Single Point Positionin, SPP) 仅使用伪距观测值&#xff0c;不使用其他的辅助信息获得ECEF框架下绝对定位技术。 使用广播星历的轨钟进行定位&#xff0c;考虑到轨钟的米级精度&#xff0c;所以对于<1米的误差&…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

Vue3中的computer和watch

computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…...