一 题目介绍

题目内容:

(1)当模块被载入内核时会向系统日志文件中写入“hello,world”;当被卸载时,会向系统写入“goodbye”。

(2)设计一个模块,要求列出系统中所有内核线程的程序名、PID、进程状态、进程优先级、父进程的PID。

(3)设计一个带参数的模块,其参数为某个进程的PID号,模块的功能是列出该进程的家族信息,包括父进程、兄弟进程和子进程的程序名、PID号及进程状态。

二 实验思路

三 遇到问题及解决方法

一开始使用for_each_process(p)来找到与用户输入pid相匹配的进程,并且通过判断state是否为空来判断pid是否存在,虽然最后结果正确,但是make的时候对p->state==NULL中的”==”报错

使用实验一中pid_task(find_get_pid(pid),PIDTYPE_PID);来找到task_struct,然后通过判断p是否是否指向空来判断pid是否存在。

四 核心代码及实验结果展示

  1. 实验一

在home文件夹中创建hello文件夹,新建myhello.c和Makefile

myhello.c

#include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h>static int  hello_init(void){printk(KERN_ALERT"hello,word\n");return 0;}static void  hello_exit(void){printk(KERN_ALERT"goodbye\n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");

Makefile

obj-m :=hello.ohello-objs:=myhello.oKDIR :=/lib/modules/$(shell uname -r)/buildPWD :=$(shell pwd)default:/*-C指定内核源码目录,M指定模块源码所在目录*/make -C $(KDIR) M=$(PWD) modulesclean:make -C $(KDIR) M=$(PWD) clean

进入hello文件夹,输入make

输入sudo insmod ./hello.ko加载模块命令

输入lsmod查看模块是否被编译

输入dmesg查看是否在日志输出

输入sudo rmmod hello卸载模块

输入dmesg查看结果

  1. 实验二

在home文件中新建process文件夹,新建module1.c和Makefile文件

module1.c

#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/init_task.h>static int hello_init(void){struct task_struct *p;/*进程描述符指针p*/p=&init_task;/*p指向init_task内核中init_task变量就是是进程0(调度程序)使用的进程描述符,也是Linux系统中第一个进程描述符,贯穿于整个Linux系统的初始化过程,所以不可能不存在*/printk(KERN_ALERT"名称\t进程号\t状态\t优先级\t父进程号\t");/*#define KERN_EMERG KERN_SOH "0"     /*系统无法使用*/#define KERN_ALERT   KERN_SOH "1"     /*必须马上输出*/#define KERN_CRIT      KERN_SOH "2"     /*临界*/#define KERN_ERR KERN_SOH "3"     /*错误*/#define KERN_WARNING    KERN_SOH "4"     /*警告*/#define KERN_NOTICE KERN_SOH "5"     /*正常但重要*/#define KERN_INFO     KERN_SOH "6"     /*信息*/#define KERN_DEBUG  KERN_SOH "7"     /*调试级别信息*/*/for_each_process(p)/* for_each_process是宏循环控制语句,内核开发者可它扫描整个进程链表。#define for_each_process(p) \for (p = &init_task ; (p = next_task(p)) != &init_task ; )一直循环下去,直到再次碰上init_task为止,因为循环链表*/{if(p->mm == NULL){/* mm是指向被映射的用户地址空间的内存管理结构的指针struct mm_struct *mm, *active_mm;#ifdef CONFIG_COMPAT_BRKunsigned brk_randomized:1;#endif#if defined(SPLIT_RSS_COUNTING)struct task_rss_stat rss_stat;#endif内核进程始终在内核空间运行,从来不切换到用户空间去,所以没有用户态地址空间,所以它们的mm成员总是为NULL*/printk(KERN_ALERT"%s\t%d\t%ld\t%d\n",p->comm,p->pid, p->state,p->normal_prio,p->parent->pid);/*struct task_struct {volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */int prio, static_prio, normal_prio;pid_t pid;char comm[TASK_COMM_LEN]; /* executable name excluding path */…};相应的程序名char common[TASK_COMM_LEN]进程标识符pid_t pid进程状态volatile long state常规静态优先级int normal_prio*/}}return 0;}// 清理函数static void hello_exit(void){printk(KERN_ALERT"goodbye~\n");}// 函数注册module_init(hello_init); module_exit(hello_exit); // 模块许可申明MODULE_LICENSE("GPL");

Makefile

obj-m:=module1.oKDIR:= /lib/modules/$(shell uname -r)/buildPWD:= $(shell pwd)all:default testdefault:$(MAKE) -C $(KDIR) M=$(PWD) modules clean:@sudo rmmod module1$(MAKE) -C $(KDIR) M=$(PWD) clean@dmesg | tail -10test:/*清除原有信息*/@sudo dmesg -C@sudo insmod module1.ko@dmesg

在cd process进入process文件夹

输入make

检验:输入ps -u root查看root用户的进程

经检查与结果一致

输入make clean

  1. 实验三
#include <linux/kernel.h>#include <linux/sched.h>#include <linux/module.h>#include <linux/init.h>#include <linux/moduleparam.h>#include <linux/sched/signal.h>/*在使用宏之前,先声明无符号变量*/static unsigned int pid;/*module_param(name,type,perm)name既是用户看到的参数名,有事模块内接收参数的变量type表示数据的类型,例如:int,double,bool,unit...perm对于全局可读的变量为0444,对于根目录可写为0644。*/module_param(pid, uint, 0644);static int list_init(void){/*parent 指向其父进程children 表示当前进程的子进程sibling 表示当前进程的链表*//*定义类型为结构体的指针*/struct task_struct *p;struct task_struct *parent;struct task_struct *children;struct task_struct *sibling;struct list_head *list;p=NULL;/*根据进程号pid得到进程描述符struct pidstruct pid *find_get_pid(pid_t nr){struct pid *pid;rcu_read_lock();/*读端临界区,阻塞写者*/pid = get_pid(find_vpid(nr));/*find_vpid(nr)根据nr也就是namespace下的局部pid找到对应的struct pid结构体get_pid 将struct pid结构体中的count字段(记录被使用的次数)加1 后,返回struct pid*/rcu_read_unlock();/*写者可以进行下一步操作*/return pid;}pid_task(struct pid *pid, enum pid_type type) PIDTYPE_PID是enum pid_type type中进程的进程号,返回进程的task_struct */p=pid_task(find_get_pid(pid),PIDTYPE_PID);if(p==NULL)printk(KERN_ALERT"Pid does not exit\n");else{parent=p->parent;printk(KERN_ALERT"This is parent:\n");printk(KERN_ALERT"程序名\t\tPID号\t进程状态\t优先级\n");printk(KERN_ALERT"%-10s\t%5d\t%ld\t\t%d\n",parent->comm, parent->pid, parent->state, parent->prio);/*sibling.next指向进程的下一个兄弟进程的进程描述符sibling成员,若其后没有其他兄弟进程,则指向父进程sibling.prev指向进程的上一个兄弟进程,若其之前没有兄弟进程,则指向父进程children.next指向父进程的第一个子进程的sibling成员(而不是children成员!)children.prev指向父进程的最后一个子进程的sibling成员。*/printk(KERN_ALERT"This is sibling:");printk(KERN_ALERT"程序名\t\tPID号\t进程状态\t优先级\n");/*遍历兄弟进程*//*#define list_for_each(pos,head)\for(pos=(head)->next;pos!=(head);pos=pos->next)pos是指向list_head的指针,用来具体地对每一个list_head进行操作*/list_for_each(list,&parent->children){/*#define list_entry(ptr,type,member)\container_of(ptr,type,member)#define container_of(ptr,type,member)({\const typeof( ((type *)0)->member)*_mptr=(ptr);(type *)( (char *)_mptr - offsetof(type,member));}offsetof获得该成员变量基于其包含体地址的偏移量ptr指向该数据存储在链表中的地址值type是数据项的类型member是数据项类型定义中list_head成员的变量名计算tpye结构体中成员member在结构体中的偏移量,然后用ptr的值减去这个偏移量,就得出type数据结构的首地址*/sibling=list_entry(list,struct task_struct,sibling);printk(KERN_ALERT"%-10s\t%5d\t%ld\t\t%d\n", sibling->comm, sibling->pid, sibling->state, sibling->prio);}printk(KERN_ALERT"This is children:\n");printk(KERN_ALERT"程序名\t\tPID号\t进程状态\t优先级\n");/*遍历子进程*/list_for_each(list,&p->children){children=list_entry(list,struct task_struct,sibling);printk(KERN_ALERT"%-10s\t%5d\t%ld\t\t%d\n", children->comm, children->pid, children->state, children->prio);}}return 0;}static void list_exit(void){printk(KERN_ALERT"goodbye~\n");}module_init(list_init);module_exit(list_exit);MODULE_LICENSE("GPL");

Makefile

obj-m := list.oKDIR := /lib/modules/`uname -r`/buildPWD := $(shell pwd)default:sudo make -C $(KDIR) M=$(PWD) modules@sudo dmesg -Cclean:- sudo rmmod listsudo make -C $(KDIR) M=$(PWD) clean

pid不存在

五 个人实验改进与总结

5.1 个人实验改进

通过遍历所有进程for_each_process(p)检查每个进程的pid是否和用户输入的pid相同,若找到pid相同的进程则输出此进程的父进程、兄弟进程、子进程,然后退出遍历。

5.2 个人实验总结

所有进程都是pid为1的init进程的后代。

结构体list_head包含两个指针成员:next,prev。这两个指针成员都是list_head类型,以此构成链表。实际应用中,list_head结构体往往实例化为其他结构体的成员,例如task_struct中的children,sibling。

杭电操作系统实验二---linux内核模块编译(完整实验报告)相关推荐

  1. 杭电操作系统实验二 --- Linux 内核模块编程(arm架构华为云)

    一.题目介绍 掌握Linux 内核模块的基本概念 ·阅读教材7.3.2节Linux内核模块简介 ,网上查找资料,了解Linux内核模块的基本概念. ·阅读教材7.3.3内核模块编程基础 ,网上查找资料 ...

  2. linux命令实验设备,实验二 Linux系统的常用命令

    实验二Linux系统的常用命令 一.实验目的 1.X-windows的简单配置,掌握进入命令行模式和图形化模式的方法2.GNOME桌面的使用,包括注销与登录,系统信息的查看,GNOME下软件的使用3. ...

  3. Linux启动和退出系统的方法,实验二 Linux的启动与关闭

    实验二 Linux的启动与关闭 一.实验目的 (1)掌握linux操作系统正确的启动与关闭方法: (2)理解系统运行级的概念,掌握查看和设置的方法: (3)理解系统运行级服务的概念,掌握查看.开启和关 ...

  4. linux编译内核实验,实验六 Linux内核编译实验.doc

    实验六 Linux内核编译 讲师:杨行 [实验目的] 1.掌握Linux内核编译 2.了解Linux内核Makefile 3.了解Linux内核Kbuild系统 [实验原理] 网站可以下载标准内核文件 ...

  5. linux写入系统状态到文件夹,实验二 Linux系统简单文件操作命令

    *实验二** Linux系统简单文件操作命令 项目内容 这个作业属于哪个课程 这个作业的要求在哪里 学号-姓名 17041518-孙小文 作业学习目标 学习在Linux系统终端下进行命令行操作 :掌握 ...

  6. Linux应用基本命令实验,实验二 linux基本命令的使用

    实验二 linux基本命令的使用 一. 实验目的 熟练掌握linux基本命令的使用 二. 实验设备 1)PC机一台 2)实验箱一台 3)虚拟机vmware,ubantu10 三. 实验讲解 1. 登录 ...

  7. 沁恒CH32V103C8T6(二): Linux RISC-V编译和烧录环境配置

    目录 沁恒CH32V103C8T6(一): 核心板焊接和Windows开发环境配置 沁恒CH32V103C8T6(二): Linux RISC-V编译和烧录环境配置 硬件准备 CH32V103 开发板 ...

  8. 实验4 Linux安装与配置实验报告(部分英文)

    实验题目 实验4  Linux安装与配置 实验目的 (1) 掌握使用 RPM 进行软件安装与包管理的方法: (2) 掌握 yum 在线安装方法和 yum 源替换方法: (3) 掌握从源代码开始安装软件 ...

  9. 计算机远程桌面连接实验报告,实验二 常见网络测试命令使用实验

    实验二常见网络测试命令使用实验: 实验项目名称:常见网络测试命令使用 实验项目性质:专业类 所属课程名称:计算机网络 试验计划学时:4学时9月18号 一.实验的目的 通过本实验的学习,使学生了解并掌握 ...

最新文章

  1. 自然语言推理:微调BERT
  2. OpenCV像素点处理
  3. Jenkins + GitHub + fir-cli 一行命令从源码到fir.im
  4. 2021年春季学期-信号与系统-第六次作业参考答案-第十一小题
  5. 网页设计千千万,网站建设万万千
  6. 【转】c# [Serializable]的作用
  7. 专业测试工程师浅谈功能测试用例模板设计
  8. 看看老外是怎么对待免费软件的。
  9. AI:人工智能技术层企业简介(更新中)
  10. 如何在android运行lua脚本(最简单的讲解,一看就懂)
  11. python日历模块_Python日历模块总结
  12. 牛奶可乐经济学之Q7:为什么官僚们喜欢使用语焉不详的句子?
  13. ICA与PCA的区别
  14. 打造不死的asp木马
  15. 三星note2 7100国行刷机android4.4版
  16. 商业励志书籍的那些流行词
  17. 基于YOLOv5实现中药饮片识别(含源码)【目标检测项目】
  18. 大沥计算机学院,2021年南海区大沥水星学校电脑随机摇号录取名单
  19. HTML制作年历,年历制作.html
  20. 配有Tesla K40c的服务器新装Ubuntu16.04并安装CUDA8.0、Anaconda3、Matlab2016a、OPENCV3.1、CuDNN5.1、MXNet...

热门文章

  1. 目标检测任务中常用的数据集格式(voc、coco、yolo)
  2. js百度搜索框功能模拟
  3. QT 系统学习 day05 事件 HTTP网络请求, 音乐播放器,上位机串口通行
  4. 企业管理软件选型九大误区
  5. linux-sfdisk用法说明
  6. 阿娇赵雅芝等众女星撩人透视照
  7. VC操作Excel之用ChartWizard自动生成图表
  8. SpringBoot2.0实现服务器主动推送SSE技术
  9. C++静态成员变量初始化和赋值
  10. 微信小程序自定义页面Title