虚拟机linux在崩溃的情况下取出其中的资料

      最近很不幸的虚拟机突然不能用了,不能用无所谓,但是里面的资料咋办呢?大家都知道,安装在真实计算机上的linux有个救援模式,在虚拟机中我们也是可以使用的,经过笔者摸索,最终终于把资料给取出来了。下面介绍这一使用过程。

 

 

STEP1:打开WMware。

 

 

 

STEP2:<

实验题目如下:1. 实验题目 1.1 实验目的 通过本实验的学习,掌握信创操作系统内核定制中所常用的内核数据结构和函数,具体包 括:i.内核链表;ii. 内核内存的分配释放; iii.内核线程;iv.内核锁; 1.2 实验内容 设计一个内核模块,并在此内核模块中创建一个内核链表以及两个内核线程。 • 线程1需要遍历进程链表并将各个进程的 pid、进程名加入到内核链表中。 • 线程2中需不断从内核链表中取出节点并打印该节点的元素。 在卸载模块时停止内核线程并释放资源。 2. 实验结果 使用 dmesg 命令可以观察到当前系统中运行的所有进程的 pid 与进程名。请按照如下方式一步一步教我如何实现,注意一定要一步一步来:初始化: 创建一个链表用于保存进程的 PID 和进程名。 初始化自旋锁,以保证多线程环境下链表操作的安全性。 创建两个内核线程: 线程1:遍历进程链表,将每个进程的 PID 和进程名保存到内核链表。 线程2:从链表中取出元素并打印进程信息。 线程1: 使用 for_each_process 宏遍历系统中的所有进程。 为每个进程创建一个链表节点,保存其 PID 和进程名,并将其加入链表。 线程2: 不断从链表中取出节点,打印进程的 PID 和进程名,并释放内存。 需要对链表的访问加锁,以避免与线程1的冲突。 模块卸载: 停止线程。 清空链表,释放所有节点的内存。 函数:kernel_module_init() 初始化链表 my_list 初始化自旋锁 lock 创建线程1,执行 thread1_func() 如果线程1创建失败: 打印错误信息并返回错误代码 创建线程2,执行 thread2_func() 如果线程2创建失败: 停止线程1,打印错误信息并返回错误代码 返回 0 函数:thread1_func() while (线程未停止): 进入读保护 (rcu_read_lock) 遍历系统中所有进程 (for_each_process): 为每个进程分配节点内存 将进程 PID 和 进程名 保存到节点 加锁 将节点插入链表尾部 解锁 退出读保护 (rcu_read_unlock) 休眠 5 秒 函数:thread2_func() while (线程未停止): 加锁 遍历链表中的每个节点: 打印 PID 和进程名 从链表中删除节点 释放节点内存 解锁 休眠 5 秒 函数:kernel_module_exit() 停止线程1 停止线程2 加锁 遍历并清空链表: 释放每个节点的内存 解锁 打印 "模块卸载成功" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 关键步骤详解 线程1 使用 for_each_process 宏遍历系统中的所有进程,使用 kmalloc 动态分配内存来存储每个进程的 PID 和进程名,最后将其加入链表。 线程2 定期从链表中取出并打印进程信息,并释放节点的内存。 自旋锁 用来保证线程1和线程2对链表的访问不会出现竞争条件。 卸载模块 时,停止所有线程并清理链表中的节点。 操作步骤 登录虚拟机 本实验使用信创操作系统,登录方法较为特殊。 (1)复制登录命令,登录Pod (2)复制Pod登录密码 (3)复制登录命令,登录虚拟机 (4)复制虚拟机登录密码 至此,你应该已经进入虚拟机内部,输入命令即可操纵机器。 查找资源文件 本次实验文件位于~/lab/1目录下,cd lab/1进入目录 而后将我们已经在本地编辑好的代码复制进去(通过vim),此处需查询vim使用手册。 输入vi 文件名查看文件,按ESC进入编辑模式,而后输入dd删除光标当前行及以下的部分,转到本机编辑好的文件,复制,右击鼠标即可将当前剪贴板里的内容粘贴进去,按ESC,输入:wq保存并退出。 编译模块 输入make,进行编译(应该不会报错,我没有报错,若有错误请自行百度)。
最新发布
04-02
<think>嗯,用户想在信创操作系统上开发一个内核模块,涉及内核链表、线程和自旋锁的应用。首先,我需要回忆一下Linux内核模块开发的基础知识,因为信创系统通常基于Linux内核。接下来,用户的问题具体包括如何创建内核模块、使用内核链表、线程以及锁机制。 首先,内核模块的基本结构是什么?通常包括init和exit函数,分别用于模块加载和卸载。模块的入口和出口需要正确注册。然后,内核链表的使用,Linux内核提供了list.h头文件,里面定义了链表的结构和相关操作,比如INIT_LIST_HEAD、list_add_tail等。用户需要创建链表节点,存储进程的pid和名称,所以结构体需要包含list_head、pid_t和char数组。 接下来是内核线程的创建。内核线程使用kthread_create或者kthread_run函数,后者会创建并唤醒线程。线程函数需要符合特定的签名,返回int,并接受void*参数。线程1需要遍历进程链表,这里可能要用到for_each_process宏,但需要注意进程的遍历需要适当的同步机制,比如RCU或者自旋锁,以防止进程状态变化导致的问题。线程2则从链表中取出节点并打印,这里同样需要考虑并发访问链表时的锁问题。 自旋锁的使用是关键,因为两个线程会同时访问共享资源——内核链表。在添加和删除节点时,必须使用自旋锁来保证操作的原子性。初始化锁用spin_lock_init,在访问链表前加锁,操作完成后解锁。需要注意的是,自旋锁在持有期间会禁用抢占,所以临界区代码必须简短,避免长时间持有锁。 然后,模块的卸载过程需要安全停止线程并释放资源。停止线程可以使用kthread_stop,但线程函数中需要有检查kthread_should_stop的条件,以便线程能及时退出。同时,在卸载时,必须确保链表中的节点都被释放,避免内存泄漏。 可能遇到的问题包括:线程创建失败、锁未正确使用导致死锁、链表操作不当引发内核崩溃。此外,信创操作系统可能有特定的内核配置或安全机制,需要确保模块编译时使用的内核头文件与目标系统一致。 最后,测试和调试内核模块需要使用dmesg查看内核日志,确保线程正确执行,锁有效,资源正确释放。可能需要多次迭代调试,处理并发问题。</think>### 分步实现信创操作系统内核模块开发 #### 一、环境准备 1. 安装信创操作系统开发套件(如麒麟V10) 2. 配置内核头文件:`sudo apt install linux-headers-$(uname -r)` 3. 创建Makefile: ```makefile obj-m += mymodule.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean ``` #### 二、内核链表实现 定义链表节点结构: ```c struct proc_node { pid_t pid; char comm[TASK_COMM_LEN]; struct list_head list; }; ``` #### 三、自旋锁与共享资源 初始化全局资源: ```c static LIST_HEAD(proc_list); static DEFINE_SPINLOCK(proc_lock); ``` #### 四、内核线程实现 1. 线程1(数据采集): ```c static int thread_collect(void *data) { struct task_struct *task; while (!kthread_should_stop()) { spin_lock(&proc_lock); list_for_each_entry(task, &init_task.tasks, tasks) { struct proc_node *node = kmalloc(sizeof(*node), GFP_KERNEL); node->pid = task->pid; strncpy(node->comm, task->comm, TASK_COMM_LEN); list_add_tail(&node->list, &proc_list); } spin_unlock(&proc_lock); schedule_timeout_interruptible(HZ); } return 0; } ``` 2. 线程2(数据打印): ```c static int thread_print(void *data) { while (!kthread_should_stop()) { spin_lock(&proc_lock); if (!list_empty(&proc_list)) { struct proc_node *node = list_first_entry(&proc_list, struct proc_node, list); printk(KERN_INFO "PID: %d, COMM: %s\n", node->pid, node->comm); list_del(&node->list); kfree(node); } spin_unlock(&proc_lock); schedule_timeout_interruptible(HZ/10); } return 0; } ``` #### 五、模块初始化与清理 ```c static struct task_struct *thr1, *thr2; static int __init mymodule_init(void) { thr1 = kthread_run(thread_collect, NULL, "collect_thread"); thr2 = kthread_run(thread_print, NULL, "print_thread"); return 0; } static void __exit mymodule_exit(void) { kthread_stop(thr1); kthread_stop(thr2); struct proc_node *pos, *tmp; list_for_each_entry_safe(pos, tmp, &proc_list, list) { list_del(&pos->list); kfree(pos); } } ``` #### 六、编译与测试 1. 编译模块:`make` 2. 加载模块:`sudo insmod mymodule.ko` 3. 查看输出:`dmesg | tail` 4. 卸载模块:`sudo rmmod mymodule` ### 关键技术要点 1. **自旋锁使用原则**:保护所有链表操作,锁持有时间应短于线程调度时间片[^1] 2. **内存管理**:使用`GFP_KERNEL`标志申请内存,确保模块退出时释放所有节点 3. **线程安全退出**:`kthread_should_stop()`配合`schedule_timeout_interruptible`实现可控退出 4. **内核链表API**:`list_add_tail`保证插入顺序,`list_for_each_entry_safe`确保安全删除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值