Linux内核编译(通过内核模块显示进程控制块信息)

实验说明

在内核中,所有进程控制块都被一个双向链表连接起来,该链表中的第一个进程控制块为init_task。编写一个内核模块,模块接收用户传递的一个参数num,num指定要打印的进程控制块的数量﹔若用户不指定num或者num<0,模块则打印所有进程控制块的信息。需要打印的进程控制块信息有:进程PID和进程的可执行文件名。

解决方案

(1)定义模块参数
该模块需要接受用户传递的参数,在使用该参数之前,需要在代码中预先定义好该参数,将该参数的类型设置为整型,并且在sysfs文件系统中的权限是只读的。定义的方法为:
static int num=–1;
module_pararm(num, int, s_IRUGO);
该参数的初始值被设置为-1。-1将作为打印所有进程控制块的标记,默认值为-1,意味着当用户不传入任何参数时,模块将打印所有的进程的信息。
(2)访问进程控制块链表
在内核中,进程控制块被组织成多个双向链表,其中有一个双向链表包含所有的进程控制块,只需要访问该双向链表,就可以访问到所有进程控制块。Linux内核中几乎所有双向链表都采用相同的数据结构来实现,内核中定义list_head通用数据结构,其定义如下:
struct list_head {
struct list head *next,*prev;
};
list_head 中,next指向链表中的下一个list_head 数据结构,prev指向链表中的前一个list_head 数据结构。之所以说该结构是用于实现一个通用的双向链表是因为:如果一个数据结构包含list_head结构,开发者就可以通过内核提供的一组宏创建并操作一个双向链表,而该链表中元素的类型为该数据结构,如图12-1所示。


在进程控制块task_struct中,包含一个名为tasks的成员,该成员的类型为list_head,这意味着进程控制块能够通过该成员将进程控制块串成一个双向链表。Linux 内核通过该成员将所有的进程都放入同一个双向链表,因为 list_head 结构中的 next 和 prev指针并不是指向包含list_head的数据结构,而是指向另一个list_head 数据结构。为了访问包含list_head 的数据结构,内核提供一个宏:
list_entry(ptr,type,member);
在该宏中, ptr是一个指向list_head的指针, type是包含list_head的数据结构类型,而member是list_head在该数据结构中的成员名。例如,若一个进程控制块中的tasks 的地址为p,为了访问该进程控制块,可以采用:
list_entry(p,struct task _struct,tasks);该宏便会返回该进程控制块的地址。
知道如何使用双向链表后,就可以方便地访问内核中所有的进程控制块,因为它通过tasks成员串成一个双向链表,如果得到一个进程控制块的地址p,开发者可以通过:
list_entry(p->tasks.next, struct task _struct, tasks);
访问该双向链表中的下一个进程控制块。在该双向链表中,第一个进程控制块为init_task,如果开发者发现下一个进程控制块为init_task时,说明已经完整地遍历过所有进程控制块。
内核定义宏for_each process 用于遍历所有的进程控制块,开发者通过该宏就能将所有的进程控制块访问一遍,该宏展开的形式为:
for (p = &init_task ; (p = list_entry(§->tasks.next, struct task_struct, tasks) !=&init_task ; )(3)输出进程控制块信息
进程控制块中包含进程大部分信息,根据实验要求,模块需要打印进程的pid和可执行文件名,在进程控制块的数据结构中,成员pid 为进程的PID,而成员comm包含进程的可执行文件名。在内核中,模块可以通过printk()内核函数将这些信息打印到系统日志中。

listprocess.c文件程序框架

实验步骤

对listprocess.c文件进行补充
在模块清理函数中加入:

printk("Good bye.\n");

将listprocess.c文件与makefile文件放在一个文件夹中
使用终端进入文件夹,直接编译

sudo make

报错一:
error: function declaration isn’t a prototype [-Werror=strict-prototypes]
意思是函数参数表没指明,进入listprocess.c文件在exp_init和exp_exit的括号里加上void

报错二:for_each_process报错
原因是for_each_process函数位置不同,在头文件中加入

#include <linux/sched.h>
#include <linux/kernel.h>

报错三:obj-m:=listprocess.o
/bin/sh: 1: obj-m:=listprocess.o: not found
Makefile:6: recipe for target ‘default’ failed
make: *** [default] Error 127
示例代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/kernel.h>MODULE_LICENSE("GPL");static int num = -1;module_param(num, int, S_IRUGO);static __init int exp_init(void){struct task_struct *p = NULL;for_each_process(p){if (num==0 )break;printk("pid=%d,path=%s\n", p->pid, p->comm);num--;}return 0;
}static __exit void exp_exit(void){printk("Good bye.\n");
}module_init(exp_init);
module_exit(exp_exit);
obj-m:=listprocess.oKERNELDIR ?= /lib/modules/$(shell uname -r)/buildPWD       := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

打开makefile文件删除最后一句obj-m:=listprocess.o即可

接着在编译一次

在终端输入

sudo demsg

查看结果

卸载内核可以使用

sudo insmod listprocess.ko

至此,实验部分内容结束。

PS:以上实验题目均来自指导书。

Linux内核编译(通过内核模块显示进程控制块信息)相关推荐

  1. linux内核编译与内核模块

    linux内核简介.配置编译与内核模块 Linux系统架构 主要分为用户空间和内核空间.用户空间包括应用程序和C库等.内核空间包括系统调用接口,linux内核以及体系结构相关代码.关于linux要区分 ...

  2. LINUX内核编译(ZT)

    LINUX内核编译(ZT) 在这里转贴一些关于内核编译的文章,绝非笔者原创,也无意注明出处.有些内容有重复之处,请原谅. ==================================== 一. ...

  3. Linux 内核编译配置选项简介(转)

    Linux 内核编译配置选项简介 作者:金步国 版权声明 本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布.任何人都可以自由使用.转载.复制和再分发,但必须保留作者署名 ...

  4. Linux 内核编译配置选项简介

    Linux 内核编译配置选项简介 作者:金步国 版权声明 本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布.任何人都可以自由使用.转载.复制和再分发,但必须保留作者署名 ...

  5. 【Linux 内核】编译 Linux 内核 ④ ( 打开 Linux 内核编译 菜单配置 |菜单配置中的光标移动与选中状态 | 保存配置 | 配置项帮助文档 )

    文章目录 一.打开 Linux 内核编译 菜单配置 二.菜单配置中的光标移动与选中状态 三.保存配置 四.配置项帮助文档 一.打开 Linux 内核编译 菜单配置 执行 make menuconfig ...

  6. Linux内核编译与安装[转]

    Linux内核介绍 Linux内核是一个用C语言写成的,符合POSIX标准的类Unix操作系统.内核是操作系统中最基本的一部分,提供了众多应用程序访问计算机硬件的机 制.Linux内核的一大特点就是采 ...

  7. Linux内核编译基础

    2.6  Linux内核编译基础 当完成对Linux内核的配置以后,此时仍然以源代码的方式存在,不能直接下载到嵌入式系统中运行,因此,需要对内核进行编译,生成最终可以在嵌入式系统上运行的可执行代码. ...

  8. Linux内核源码分析《进程管理》

    Linux内核源码分析<进程管理> 前言 1. Linux 内核源码分析架构 2. 进程原理分析 2.1 进程基础知识 2.2 Linux进程四要素 2.3 进程描述符 task_stru ...

  9. 编译linux内核成vmlinuz,Linux内核编译与安装

    原标题:Linux内核编译与安装 Linux内核是一个用C语言写成的,符合POSIX标准的类Unix操作系统,内核是操作系统中最基本的一部分,提供了众多应用程序访问计算机硬件的机制.Linux内核的一 ...

最新文章

  1. 前端三十五:图片的基本概念
  2. java接口示例_【基础篇】java-接口及其示例
  3. 号称要打败阿尔法狗的DeepZenGo 高调挑战人类
  4. es 指定排序字段_ES里多字段分组后排序
  5. 《Getting Real》读书笔记
  6. 数学狂想曲(十一)——高阶统计, 最速降线, 泛函 变分
  7. python实现将一个文件夹下的文件路径写入到指定的txt文件中
  8. python导入模块介绍_详解Python模块导入方法
  9. Python封装的获取文件目录的函数
  10. idea里查找maven的jar包冲突
  11. 独家:为了永不停机的计算服务 - 三月月刊
  12. 一键破解宝塔面板的专业版本权限
  13. 如何通过API接口,获取拼多多商品详情数据
  14. 前后端交互、Node、npm、Express、mysql基础
  15. 《东周列国志》第三十五回 晋重耳周游列国 秦怀嬴重婚公子
  16. KEIL MDK中的RO、RW和ZI
  17. 在Word里怎么设置每页不同的页眉
  18. 【PIL案例精讲】252行Python代码制作透明背景的电子印章
  19. 百度音乐爬取文件练习
  20. 尚硅谷MySQL基础部分的笔记

热门文章

  1. 如何不装app也不用数据线手机向电脑传照片视频
  2. 支持向量机(SVM)学习笔记
  3. 13寸MacBook Air 与 Pro低配、Pro高配到底有啥区别?
  4. php校园晨跑,学校晨跑的作文(精选3篇)
  5. json与formdata格式相互转换
  6. ubuntu 安装/卸载微信
  7. 裸眼立体(自由立体)显示原理与器件制作
  8. python之pdfminer:从PDF文档中抽取信息的工具
  9. Linux下Qt 5.15.2源码下载及编译
  10. 手写稿怎么变成电子稿?这个办法值得一试