设计一个模块,功能是列出系统中所有内核线程的程序名、PID号和进程状态。
来源:互联网 发布:魔兽对战平台mac版 编辑:程序博客网 时间:2024/04/28 08:47
设计一个模块,功能是列出系统中所有内核线程的程序名、PID号和进程状态。主要步骤:
阅读内核源代码,了解进程描述符task_struct中与本实验有关的成员项,以及访问进程队列的宏for_each_process;
分析内核模块实例,掌握内核模块的主要构成;
阅读Makefile文件,理解内核模块编译、加载过程;
以下是hello.c文件
#include <linux/sched.h>
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
//#define for_each_process(p)
static int hello_init(void)
{
struct task_struct *p;
printk(KERN_ALERT"名称\t进程号\t状态\t");
// p=NULL;
for_each_process(p)
{
printk(KERN_ALERT"%d\t%d\t%d\n",p->comm,p->pid, p->state);
}
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "hello world exit\n");
}
module_init(hello_init);//加载函数
module_exit(hello_exit); //卸载函数
MODULE_LICENSE("GPL"); //许可证申明
MODULE_DESCRIPTION("hello module");
MODULE_AUTHOR("liguangcai");
以下是Makefile文件:
ifneq ($(KERNELRELEASE),)
obj-m:=readprocess.o
else
KDIR:= /lib/modules/$(shell uname -r)/build
PWD:= $(shell pwd)
default://注意,default前面最好不要有空格,刚开始做的时候前面加空格报错了
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:://注意,前面最好不要有空格
$(MAKE) -C $(KDIR) M=$(PWD) clean
endif://注意,前面最好不要有空格
编写完上述两个文件后回到这两个文件所在的目录键入命令: make
#insmod hello.ko
查看加载模块是否成功:
#dmesg
一、Linux的内核模块
内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),简称模块。Linux内核之所以提供模块机制,是因为它本身是一个单内核(monolithic kernel)。单内核的最大优点是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。
模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。
总之,模块是一个为内核(从某种意义上来说,内核也是一个模块)或其他内核模块提供使用功能的代码块。
1. 利用内核模块的动态装载性的优点:
将内核映象的尺寸保持在最小,并具有最大的灵活性;便于检验新的内核代码,而不需重新编译内核并重新引导。
2. 内核模块的缺点:
装入的内核模块和其他内核部分一样,具有相同的访问权限,因此,差的内核模块会导致系统崩溃;为了使内核模块访问所有内核资源,内核必须维护符号表,并在装入和卸载模块时修改这些符号表;有些模块要求利用其他模块的功能,因此,内核要维护模块之间的依赖性。内核必须能够在卸载模块时通知模块,并且要释放分配给模块的内存和中断等资源;内核版本和模块版本的不兼容,也可能导致系统崩溃。
相关操作说明:
a、必需模块函数
加载函数 module_init(hello_init);
卸载函数 module_exit(hello_exit);
b、可选模块函数
MODULE_LICENSE(“*******”); 许可证申明
MODULE_AUTHOR(“********”); 作者申明
MODELE_DESCRIPTION(“***”); 模块描述
MODULE_VERSION(“V1.0”); 模块版本
MODULE_ALIAS("*********"); 模块别名
c、加载内核模块
载入模块使用insmod命令:
#insmod hello.ko
卸载内核模块使用rmmod命令:
#rmmod hello
d、查看加载模块是否成功
dmesg可以看到系统的内核模块信息。
三、与本次试验相关的内核代码:
1. 进程控制块的相关内容:
linux/sched.h文件中:
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define __TASK_STOPPED 4
#define __TASK_TRACED 8
#define EXIT_ZOMBIE 16
#define EXIT_DEAD 32
#define TASK_DEAD 64
#define TASK_WAKEKILL 128
#define TASK_WAKING 256
#define TASK_PARKED 512
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
struct list_head tasks;
struct mm_struct *mm;
pid_t pid;
pid_t tgid;
struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */
char comm[TASK_COMM_LEN]; /* executable name excluding path */
}
2. for_each_process(p)宏:
宏for_each_process(p)的功能是扫描整个进程链表:
#define for_each_process(p) \ for (p = &init_task ; (p = next_task(p)) != &init_task ; )
使用方法:
struct task_struct *p;
for_each_process(p){
//对p指向的进程描述符进行操作
}
- 设计一个模块,功能是列出系统中所有内核线程的程序名、PID号和进程状态。
- 列出系统中所有的线程信息的方法
- 内核遍历进程中所有的线程
- [原创]C#列出系统中所有运行的程序
- 列出系统中所有的app程序信息
- 列出数据库中所有的表名
- 列出数据库中所有的表名
- 编写内核模块遍历进程的PID
- 加载内核模块,实现新的系统调用:遍历系统当前所有进程的任务描述符,并将pid组织成树状结构显示
- 遍历查询一个数据库中所有表,列出表名和每个表中的数据行数
- [程序段] 列出指定目录下的所有文件夹名和文件名
- WRK列出进程和线程的详情
- sql列出一个表所有列的列名
- Android - 在一个应用程序中启动另外一个已经安装的应用程序或系统程序(前提是要知道该应用程序的主activity和包名)
- win32内核程序中进程的pid,handle,eprocess之间相互转换的方法
- 内核程序中进程的pid,handle,eprocess之间相互转换的方法
- 内核程序中进程的pid,handle,eprocess之间相互转换的方法
- unix 环境高级编成 程序清单1-1 列出一个目录中所有的文件
- 用深度优先和广度优先遍历文件夹下符合条件的文件
- 参与流片是一种怎样的体验?
- API
- 多种GUI对图像进行简单操作(qt【linux和win7环境】、MFC、MATLAB)
- pthread_create 未定义的引用
- 设计一个模块,功能是列出系统中所有内核线程的程序名、PID号和进程状态。
- Cacti-rrd安装
- 14,include全面解刨
- 个人博客&作业部落
- 如何给MFC的菜单项添加快捷键。
- oc语言中的isa指针以及其面向对象语言的设计原理
- 笔记三(创建一个旋转动画)
- php通过JavaBridge调用matlab
- 设计模式--观察者模式【Observer Pattern】