实例要求
编写一个Linux的内核模块,其功能是遍历操作系统所有进程。该内核模块输出系统中:每个进程的名字、进程pid、进程的状态、父进程的名字;以及统计系统中进程个数,包括统计系统中TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_ZOMBIE、TASK_STOPPED等(还有其他状态)状态进程的个数。同时还需要编写一个用户态下执行的程序,显示内核模块输出的内容。
学习资料:
《边干边学—Linux内核指导》 ArchLinux Wiki
解决方案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#include <linux/module.h> //needed by all modules #include <linux/kernel.h> //needed for KERN_INFO #include <linux/sched.h> //defined struct task_struct #include <linux/proc_fs.h> //create proc file #include <linux/seq_file.h> //use seq_file #define FILENAME "osexp" //defile proc file name int myshow( struct seq_file *, void *); int myopen( struct inode *, struct file *); /* custom the operations to the seq_file */ static const struct file_operations myops = { .owner = THIS_MODULE, .open = myopen, .read = seq_read, .release = single_release }; /* do when open the seq file */ int myopen( struct inode *inode, struct file *file){ single_open(file,myshow,NULL); //bind seq_file with myshow function return 0; } /* create proc file */ int init_proc( void ){ struct proc_dir_entry * myfile; myfile = proc_create(FILENAME,0444,NULL,&myops); //create proc file if (myfile == NULL) //deal with error return -ENOMEM; return 0; } /* remove proc file */ void remove_proc( void ){ remove_proc_entry(FILENAME,NULL); //remove proc file printk(KERN_INFO "[m] proc file:%s removed\n" ,FILENAME); //print debug message } /*description: output process's info to log */ int myshow( struct seq_file *file, void *v){ int num_running = 0; //the number of process whose status is running int num_interruptible = 0; //the number of process whose status is interruptible int num_uninterruptible = 0; //the ... status is uninterruptible int num_zombie = 0; //the process exited with status zombie int num_stopped = 0; //the ... status is stopped int num_traced = 0; //the ... status is traced int num_dead = 0; //the process has deaded; int num_unknown = 0; //the process whose status is unknown int num_total = 0; //the total number of process int t_exit_state; //temp var to store task_struct.exit_state int t_state; //temp var to store task_struct.state struct task_struct *p; //pointer to task_struct //printk("[m] All processes' info:\n");//print boot info seq_printf(file, "[m] All processes' info:\n" ); for (p=&init_task;(p=next_task(p))!=&init_task;){ //go througn the linklist //printk(KERN_INFO "[m] Name:%s Pid:%d State:%ld ParName:%s\n",p->comm,p->pid,p->state,p->real_parent->comm); //print the process's info to log seq_printf(file, "[m] Name:%s Pid:%d State:%ld ParName:%s\n" ,p->comm,p->pid,p->state,p->real_parent->comm); num_total++; //total number of process plus one t_state = p->state; //put p->state to variable t_state t_exit_state = p->exit_state; //similar to above if (t_exit_state!=0){ //if the process has exited switch (t_exit_state){ case EXIT_ZOMBIE: //if the exit state is zombie num_zombie++; //variable plus one break ; //break switch case EXIT_DEAD: //if the exit state is dead num_dead++; //variable plus one break ; //break switch default : //other case break ; //break switch } } else { // if the proess hasn't exited switch (t_state){ case TASK_RUNNING: //if the state is running num_running++; //variable plus one break ; //break switch case TASK_INTERRUPTIBLE: //state is interruptible num_interruptible++; //variable plus one break ; //break switch case TASK_UNINTERRUPTIBLE: //state is uninterruptible num_uninterruptible++; //var + 1 break ; //break switch case TASK_STOPPED: //state is stopped num_stopped++; //var +1 break ; //break switch case TASK_TRACED: //state is traced num_traced++; //var +1 break ; //break switch default : //other case num_unknown++; break ; } } } //below instruction is to print the statistics result in above code // printk(KERN_INFO "[m] total tasks: %10d\n",num_total); // printk(KERN_INFO "[m] TASK_RUNNING: %10d\n",num_running); // printk(KERN_INFO "[m] TASK_INTERRUPTIBLE: %10d\n",num_interruptible); // printk(KERN_INFO "[m] TASK_UNINTERRUPTIBLE: %10d\n",num_uninterruptible); // printk(KERN_INFO "[m] TASK_TRACED: %10d\n",num_stopped); // printk(KERN_INFO "[m] TASK_TRACED: %10d\n",num_stopped); // printk(KERN_INFO "[m] EXIT_ZOMBIE: %10d\n",num_zombie); // printk(KERN_INFO "[m] EXIT_DEAD: %10d\n",num_dead); // printk(KERN_INFO "[m] UNKNOWN: %10d\n",num_unknown); seq_printf(file, "[m] total tasks: %10d\n" ,num_total); seq_printf(file, "[m] TASK_RUNNING: %10d\n" ,num_running); seq_printf(file, "[m] TASK_INTERRUPTIBLE: %10d\n" ,num_interruptible); seq_printf(file, "[m] TASK_UNINTERRUPTIBLE: %10d\n" ,num_uninterruptible); seq_printf(file, "[m] TASK_TRACED: %10d\n" ,num_stopped); seq_printf(file, "[m] TASK_TRACED: %10d\n" ,num_stopped); seq_printf(file, "[m] EXIT_ZOMBIE: %10d\n" ,num_zombie); seq_printf(file, "[m] EXIT_DEAD: %10d\n" ,num_dead); seq_printf(file, "[m] UNKNOWN: %10d\n" ,num_unknown); return 0; } int init_module( void ){ // init the kernel module printk(KERN_INFO "[m] exp_process started\n" ); //print start message return init_proc(); //create proc file } void cleanup_module( void ){ //clean up the resources when module finished remove_proc(); //remove proc file printk(KERN_INFO "[m] exp_process finished\n" ); //print finish message } MODULE_LICENSE( "GPL" ); //show that this code follow GUN General Public License |
archlinux 下的makefile
1
2
3
4
5
6
7
8
|
TARGET = os_1_2 KDIR = /lib/modules/$(shell uname -r)/build PWD = $(shell pwd) obj-m += $(TARGET).o all: make -C $(KDIR) M=$(PWD) modules clean: make -C $(KDIR) M=$(PWD) clean |
以上就是一文学会使用Linux内核模块&proc实例统计所有进程信息的详细内容,更多关于Linux内核模块&proc的资料请关注服务器之家其它相关文章!
原文链接:https://segmentfault.com/a/1190000007614350