示例需求:编写一个Linux内核模块,其功能是遍历操作系统的所有进程。内核模块在系统中输出:各个进程的名称、进程pid、进程的状态、父进程的名称;以及统计系统中的进程数,包括TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_ZOMBIE、TASK_STOPPED等统计系统中(及其他状态)状态进程的数量。同时,还需要编写一个在用户态下执行的程序,用于显示内核模块的输出内容。学习资料:《边干边学—Linux内核指导》ArchLinuxWiki解决方案:#include//所有模块都需要#include//KERN_INFO需要#include//definedstructtask_struct#include//createprocfile#include//使用seq_file#defineFILENAME"osexp"//defileprocfilenameintmyshow(structseq_file*,void*);intmyopen(structinode*,structfile*);/*自定义对seq_file的操作*/staticconststructfile_operationsmyops={.owner=THIS_MODULE,.open=myopen,.read=seq_read,.release=single_release};/*打开seq文件时执行*/intmyopen(structinode*inode,structfile*file){single_open(file,myshow,NULL);//用myshow函数绑定seq_filereturn0;}/*创建proc文件*/intinit_proc(void){structproc_dir_entry*myfile;myfile=proc_create(FILENAME,0444,NULL,&myops);//创建proc文件if(myfile==NULL)//处理错误return-ENOMEM;return0;}/*删除proc文件*/voidremove_proc(void){remove_proc_entry(FILENAME,NULL);//删除proc文件printk(KERN_INFO"[m]procfile:%sremoved\n",FILENAME);//printdebugmessage}/*description:输出进程的信息到日志*/intmyshow(structseq_file*file,void*v){intnum_running=0;//状态为运行的进程数intnum_interruptible=0;//状态为可中断的进程数intnum_uninterruptible=0;//the...statusisuninterruptibleintnum_zombie=0;//进程以僵尸状态退出intnum_stopped=0;//...状态已停止intnum_traced=0;//跟踪...状态intnum_dead=0;//进程已经死亡;intnum_unknown=0;//状态未知的进程intnum_total=0;//进程总数intt_exit_state;//临时变量存储task_struct.exit_stateintt_state;//项目pvartostoretask_struct.statestructtask_struct*p;//指向task_struct的指针//printk("[m]所有进程的信息:\n");//打印引导信息seq_printf(file,"[m]所有进程的信息:\n");for(p=&init_task;(p=next_task(p))!=&init_task;){//遍历链表//printk(KERN_INFO"[m]Name:%sPid:%dState:%ldParName:%s\n",p->comm,p->pid,p->state,p->real_parent->comm);//打印进程信息到日志seq_printf(file,[m]Name:%sPid:%dState:%ldParName:%s\n",p->comm,p->pid,p->state,p->real_parent->comm);num_total++;//进程总数加一t_state=p->state;//把p->state赋给变量t_statet_exit_state=p->exit_state;//和上面类似if(t_exit_state!=0){//如果进程已经退出switch(t_exit_state){caseEXIT_ZOMBIE://iftheexitstateiszombienum_zombie++;//变量加上休息;//breakswitchcaseEXIT_DEAD://iftheexitstateisdeadnum_dead++;//variableplusonebreak;//breakswitchdefault://othercasebreak;//breakswitch}}else{//如果进程没有'texitedswitch(t_state){caseTASK_RUNNING://ifstateisrunningnum_running++;//变量加一break;//breakswitchcaseTASK_INTERRUPTIBLE://stateisinterruptiblenum_interruptible++;//变量加一break;//breakswitchcaseTASK_UNINTERRUPTIBLE://stateisuninterruptiblenum_uninterruptible++;//var+1break;//breakswitchcaseTASK_STOPPED://stateisstoppednum_stopped++;//var+1break;//breakswitchcaseTASK_TRACED://状态被追踪num_traced++;//var+1break;//breakswitchdefault://othercasenum_unknown++;休息;}}}//下面的指令是打印上面代码中的统计结果//printk(KERN_INFO"[m]totaltasks:%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]未知:%10d\n",num_unknown);seq_printf(文件,[m]总任务:%10d\n",num_total);seq_printf(文件,[m]TASK_RUNNING:%10d\n",num_running);seq_printf(文件,[m]TASK_INTERRUPTIBLE:%10d\n",num_interruptible);seq_printf(文件,“[m]TASK_UNINTERRUPTIBLE:%10d\n”,num_uninterruptible);seq_printf(文件,“[m]TASK_TRACED:%10d\n”,num_stopped);seq_printf(文件,“[m]TASK_TRACED:%10d\n”,num_stopped);seq_printf(文件,[m]EXIT_ZOMBIE:%10d\n",num_zombie);seq_printf(文件,[m]EXIT_DEAD:%10d\n",num_dead);seq_printf(文件,[m]未知:%10d\n",num_unknown);return0;}intinit_module(void){//初始化内核模块printk(KERN_INFO"[m]exp_processstarted\n");//打印开始消息returninit_proc();//创建proc文件}voidcleanup_module(void){//模块完成时清理资源remove_proc();//删除proc文件printk(KERN_INFO"[m]exp_processfinished\n");//打印完成消息}MODULE_LICENSE("GPL");//显示这段代码遵循GUNGeneralPublicLicensearchlinux下的makefileTARGET=os_1_2KDIR=/lib/modules/$(shelluname-r)/buildPWD=$(shellpwd)obj-m+=$(TARGET).oall:make-C$(KDIR)M=$(PWD)modulesclean:使-C$(KDIR)M=$(PWD)干净