基于Linux内核模块的进程与内存监控工具(CentOS 7实现)
以下是在CentOS 7上开发完整监控工具的详细步骤和代码实现,完全符合题目要求:
一、环境准备
bash
# 安装开发工具
sudo yum install -y gcc make
sudo yum install -y kernel-devel-$(uname -r)
二、模块实现
1. 进程监控模块 (process_monitor.c)
c
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/time.h>
#include <linux/seq_file.h>
static int __init process_monitor_init(void)
{
struct task_struct *task;
struct timespec64 now;
ktime_get_real_ts64(&now);
printk(KERN_INFO "[%lld.%09ld] Process Monitor Loaded\n",
(long long)now.tv_sec, now.tv_nsec);
rcu_read_lock();
for_each_process(task) {
printk(KERN_INFO "PID:%-6d | Name:%-16s | State:%c | CPU: user%llu/sys%llu ns",
task->pid, task->comm,
task_state_to_char(task),
task->utime, task->stime);
}
rcu_read_unlock();
return 0;
}
static void __exit process_monitor_exit(void)
{
printk(KERN_INFO "Process monitor unloaded\n");
}
module_init(process_monitor_init);
module_exit(process_monitor_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Real-time process monitoring module");
2. 内存监控模块 (memory_monitor.c)
c
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/sysinfo.h>
static int __init memory_monitor_init(void)
{
struct sysinfo si;
si_meminfo(&si);
printk(KERN_INFO "=== Memory Statistics ===");
printk(KERN_INFO "Total Pages: %lu", si.totalram);
printk(KERN_INFO "Free Pages: %lu", si.freeram);
printk(KERN_INFO "Used Pages: %lu", si.totalram - si.freeram);
return 0;
}
static void __exit memory_monitor_exit(void)
{
printk(KERN_INFO "Memory monitor unloaded\n");
}
module_init(memory_monitor_init);
module_exit(memory_monitor_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Memory page frame monitoring module");
3. PID查询模块 (pid_query.c)
c
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/pid.h>
static int target_pid = 0;
module_param(target_pid, int, 0644);
MODULE_PARM_DESC(target_pid, "Target process ID");
static int __init pid_query_init(void)
{
struct task_struct *task;
struct pid *pid_struct;
if (target_pid <= 0) {
printk(KERN_ERR "Invalid PID specified");
return -EINVAL;
}
pid_struct = find_get_pid(target_pid);
if (!pid_struct) {
printk(KERN_ERR "Process %d not found", target_pid);
return -ESRCH;
}
task = pid_task(pid_struct, PIDTYPE_PID);
if (!task) {
printk(KERN_ERR "Task struct not found");
return -ESRCH;
}
printk(KERN_INFO "=== Process Details ===");
printk(KERN_INFO "PID: %d", task->pid);
printk(KERN_INFO "Name: %s", task->comm);
printk(KERN_INFO "State: %c", task_state_to_char(task));
printk(KERN_INFO "CPU Time: user%llu/sys%llu ns", task->utime, task->stime);
printk(KERN_INFO "PPID: %d", task->real_parent->pid);
return 0;
}
static void __exit pid_query_exit(void)
{
printk(KERN_INFO "PID query unloaded\n");
}
module_init(pid_query_init);
module_exit(pid_query_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Process detail query by PID");
三、编译配置 (Makefile)
makefile
obj-m := process_monitor.o memory_monitor.o pid_query.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
# 禁用格式警告
ccflags-y := -Wno-format
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
四、操作流程
1. 编译模块
bash
make
2. 加载模块
bash
sudo insmod process_monitor.ko
sudo insmod memory_monitor.ko
ps 查询进程 pid
sudo insmod pid_query.ko target_pid=1 # 查询PID为1的进程
3. 查看监控结果
bash
dmesg | tail -30
4. 卸载模块
bash
sudo rmmod process_monitor memory_monitor pid_query
一、功能实现验证
二、输出结果解读
-
进程监控模块:
- 捕获了系统所有进程(包括
gnome-terminal、bash、sleep等) - 显示状态标识:
S(可中断睡眠)、R(运行中) - CPU时间精确到纳秒级
- 捕获了系统所有进程(包括
-
内存监控:
- 总页框:4,692,373
- 空闲页框:4,078,424
- 已用页框:613,949
- 符合物理内存页框统计逻辑
-
PID查询:
- 成功查询PID 1906的进程(bash)
- 显示父进程ID(PPID):1888
- 状态:
S(睡眠) - 用户态CPU:36,000,000 ns
- 内核态CPU:74,000,000 ns
一、实时进程信息查看
命令:dmesg | grep "PID:" | tail -20
二、内存页框分配统计
命令:dmesg | grep -A3 "Memory Statistics"
三、PID查询结果
命令:dmesg | grep -A5 "Process Details"
解读
一、实时进程监控(process_monitor模块)
[ 3830.601393] PID:6384 | Name:insmod | State:R | CPU: user3000000/sys10000000 ns
- PID: 6384(加载内核模块的进程)
- 进程名: insmod(内核模块加载工具)
- 状态: R(Running,正在运行)
- CPU占用 :
- 用户态: 3,000,000 ns (0.003秒)
- 内核态: 10,000,000 ns (0.01秒)
该输出展示了系统正在运行的进程详细信息,包括特殊进程如
insmod
二、内存页框监控(memory_monitor模块)
[ 3839.013640] === Memory Statistics ===
[ 3839.013642] Total Pages: 4692373
[ 3839.013645] Free Pages: 4078424
[ 3839.013646] Used Pages: 613949
- 总页框: 4,692,373(约18.77GB,假设页框大小为4KB)
- 空闲页框: 4,078,424(约16.31GB)
- 已用页框: 613,949(约2.46GB)
内存使用率 = 613949 / 4692373 ≈ 13.1%,系统内存压力较小
三、PID查询(pid_query模块)
[ 3857.522788] === Process Details ===
[ 3857.522795] PID: 1906
[ 3857.522798] Name: bash
[ 3857.522799] State: S
[ 3857.522802] CPU Time: user36000000/sys74000000 ns
[ 3857.522803] PPID: 1888
- 查询目标: PID 1906
- 进程名: bash(Shell终端)
- 状态: S(Sleeping,可中断睡眠)
- CPU时间 :
- 用户态: 36,000,000 ns (0.036秒)
- 内核态: 74,000,000 ns (0.074秒)
- 父进程ID: 1888
该进程是一个bash终端,处于睡眠状态(等待用户输入)
ime: user36000000/sys74000000 ns
3857.522803\] PPID: 1888 - **查询目标**: PID 1906 - **进程名**: bash(Shell终端) - **状态**: S(Sleeping,可中断睡眠) - **CPU时间**: - 用户态: 36,000,000 ns (0.036秒) - 内核态: 74,000,000 ns (0.074秒) - **父进程ID**: 1888 > 该进程是一个bash终端,处于睡眠状态(等待用户输入)