0
点赞
收藏
分享

微信扫一扫

增加系统调用以树形结构打印进程pid

small_Sun 2022-02-14 阅读 121

文章目录

一、设计思路

  1. 下载linux内核源码

  2. 在系统调用表中添加系统调用号

  3. 系统调用头文件中写出自定义的系统调用函数

  4. 修改内核源码,添加自定义系统调用函数的实现

  5. 安装依赖工具,重新编译内核,并使用新的内核

  6. 编写测试代码并测试

二、实现过程

1. 下载linux内核源码

官网下载内核源码,网址为:https://mirrors.edge.kernel.org/pub/linux/kernel/

国内源码下载地址:http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/

查看自己系统的内核版本,然后找一个相近的linux版本进行内核升级,这里我选择的是5.14.1

在这里插入图片描述

下载源码包,解压至 /usr/src

mv linux-5.14.1.tar.gz /usr/src

tar xvf linux-5.14.1.tar.gz

在这里插入图片描述

2. 在系统调用表中添加系统调用号

系统调用表路径:/usr/src/linux-5.14.1/arch/x86/entry/syscalls/syscall_64.tbl

<number>     <abi>             <name>             <entry point>
331	        common	          pkey_free	          sys_pkey_free
332	        common	           statx		       sys_statx
333	        common	       io_pgetevents		sys_io_pgetevents
334	        common	           rseq			       sys_rseq
335           64         print_all_process    sys_print_all_process

3. 系统调用头文件中写出自定义的系统调用函数

头文件中加入自定义系统调用声明,头文件路径:/usr/src/linux-5.14.1/arch/x86/include/asm/syscalls.h

#ifndef _ASM_X86_SYSCALLS_H
#define _ASM_X86_SYSCALLS_H

/* Common in X86_32 and X86_64 */
/* kernel/ioport.c */
long ksys_ioperm(unsigned long from, unsigned long num, int turn_on);

/* added by me */
asmlinkage long __x64_sys_print_all_process(void);

#endif /* _ASM_X86_SYSCALLS_H */

4. 修改内核源码,添加自定义系统调用函数的实现

/usr/src/linux-5.14.1/kernel/sys.c 中添加即可,注意不能写到宏里面

// 335 64      print_all_process   sys_print_all_process
static void print_children(struct task_struct* task, int level){
	struct list_head* pos;
	struct task_struct* ptr;

	// 树形结构输出
	int i;
	for(i = level; i > 0; i--){
		printk(KERN_CONT "    ");
	}

	// 进程名称以及pid
	printk(KERN_CONT "|————");
	printk(KERN_CONT "%s[%d]\n", task->comm, task->pid);

	// 利用父task_struct的children双向链表,遍历其子进程
	list_for_each(pos, &task->children){
		// 返回task_struct指针,寻找pos对应的task_struct,便宜相当于sibling
		ptr = list_entry(pos, struct task_struct, sibling);
		if(ptr != NULL){
			level++;
			// 递归打印子进程树
			print_children(ptr, level);
			level--;
		}
	}
}

asmlinkage long __x64_sys_print_all_process(void){
	printk("The Process Tree Is As Follows:");
	print_children(&init_task, 0);
	return 0;
}

5. 安装依赖工具,重新编译内核,并使用新的内核

apt update
apt install libncurses5-dev libssl-dev
apt install build-essential openssl
apt install zlibc minizip
apt install libidn11-dev libidn11
apt install flex bison
apt install libdw-dev
apt install libncurses-dev
apt install dwarves
apt-get install libdw-dev
make mrproper
make clean
make menuconfig

弹出配置菜单,Save->ok->exit->exit即可

在这里插入图片描述

编译内核,这个过程非常长,还会有各种bug,我使用的版本为5.14.1,至少需要60G磁盘,编译至少4小时

cd /usr/src/linux-5.14.1

编译内核:make

编译完成后在控制台中输入命令开始安装模块:sudo make modules_install

模块安装完成后在控制台中输入命令安装内核:sudo make install

安装完成后:reboot

可以看到内核版本已经更新为5.14.1

在这里插入图片描述

6. 编写测试代码并测试

#include <linux/unistd.h>
#include <sys/syscall.h>

int main(){
    syscall(335);
    return 0;
}

由于添加的系统调用的输出语句为printk写的,它将消息送到系统日志中,所以控制台没有输出,输入命令查看日志:dmesg

在这里插入图片描述

三、编译内核遇到的问题以及解决方法

  1. 编译错误 error New address family defined, please update secclass_map.解决

  2. 没有libelf.h libdw.h

  3. 编译Linux内核kernel时遇到的问题与解决方案

  4. BTF: .tmp_vmlinux.btf: pahole (pahole) is not available

  5. arch/x86/boot/compressed/vmlinux.bin.lzma] Error 1

四、参考资料

  • Linux内核分析

  • Ubuntu18向内核增加一个系统调用实验

  • Linux添加系统调用函数并编译

举报

相关推荐

0 条评论