资讯专栏INFORMATION COLUMN

[Linux] 内核模块&proc使用 实例:统计所有进程的信息

alanoddsoff / 1891人阅读

摘要:实例要求编写一个的内核模块,其功能是遍历操作系统所有进程。该内核模块输出系统中每个进程的名字进程进程的状态父进程的名字以及统计系统中进程个数,包括统计系统中等还有其他状态状态进程的个数。

实例要求:

编写一个Linux的内核模块,其功能是遍历操作系统所有进程。该内核模块输出系统中:每个进程的名字、进程pid、进程的状态、父进程的名字;以及统计系统中进程个数,包括统计系统中TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_ZOMBIE、TASK_STOPPED等(还有其他状态)状态进程的个数。同时还需要编写一个用户态下执行的程序,显示内核模块输出的内容。

学习资料:
《边干边学—Linux内核指导》
ArchLinux Wiki

解决方案:

#include  //needed by all modules
#include  //needed for KERN_INFO
#include  //defined struct task_struct
#include  //create proc file
#include  //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
",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:
");//print boot info
    seq_printf(file,"[m] All processes" info:
");
    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
",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
",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
",num_total);
    // printk(KERN_INFO "[m] TASK_RUNNING: %10d
",num_running);
    // printk(KERN_INFO "[m] TASK_INTERRUPTIBLE: %10d
",num_interruptible);
    // printk(KERN_INFO "[m] TASK_UNINTERRUPTIBLE: %10d
",num_uninterruptible);
    // printk(KERN_INFO "[m] TASK_TRACED: %10d
",num_stopped);
    // printk(KERN_INFO "[m] TASK_TRACED: %10d
",num_stopped);
    // printk(KERN_INFO "[m] EXIT_ZOMBIE: %10d
",num_zombie);
    // printk(KERN_INFO "[m] EXIT_DEAD: %10d
",num_dead);
    // printk(KERN_INFO "[m] UNKNOWN: %10d
",num_unknown);
    seq_printf(file,"[m] total tasks: %10d
",num_total);
    seq_printf(file,"[m] TASK_RUNNING: %10d
",num_running);
    seq_printf(file,"[m] TASK_INTERRUPTIBLE: %10d
",num_interruptible);
    seq_printf(file,"[m] TASK_UNINTERRUPTIBLE: %10d
",num_uninterruptible);
    seq_printf(file,"[m] TASK_TRACED: %10d
",num_stopped);
    seq_printf(file,"[m] TASK_TRACED: %10d
",num_stopped);
    seq_printf(file,"[m] EXIT_ZOMBIE: %10d
",num_zombie);
    seq_printf(file,"[m] EXIT_DEAD: %10d
",num_dead);
    seq_printf(file,"[m] UNKNOWN: %10d
",num_unknown);

    return 0;
} 

int init_module(void){// init the kernel module
    printk(KERN_INFO "[m] exp_process started
");//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
");//print finish message
}

MODULE_LICENSE("GPL");//show that this code follow GUN General Public License

archlinux 下的makefile

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/9674.html

相关文章

  • 技术分享 | Linux 入侵检测中进程创建监控

    摘要:简介在入侵检测的过程中,进程创建监控是必不可少的一点,因为攻击者的绝大多数攻击行为都是以进程的方式呈现,所以及时获取到新进程创建的信息能帮助我们快速地定位攻击行为。 作者简介:张博,网易高级信息安全工程师。 0x00 简介 在入侵检测的过程中,进程创建监控是必不可少的一点,因为攻击者的绝大多数攻击行为都是以进程的方式呈现,所以及时获取到新进程创建的信息能帮助我们快速地定位攻击行为。 本...

    kevin 评论0 收藏0
  • Linux Cgroup系列(01):Cgroup概述

    摘要:一般情况下不会用到这个功能,一但最开始关联好了之后,就不会去重新修改它,也即我们一般不会去修改给我们设置好的和树的关联关系。 cgroup和namespace类似,也是将进程进行分组,但它的目的和namespace不一样,namespace是为了隔离进程组之间的资源,而cgroup是为了对一组进程进行统一的资源监控和限制。 cgroup分v1和v2两个版本,v1实现较早,功能比较多,但...

    zorro 评论0 收藏0
  • Linux Cgroup系列(04):限制cgroup内存使用(subsystem之memory)

    摘要:内存控制能控制些什么限制中所有进程所能使用的物理内存总量限制中所有进程所能使用的物理内存交换空间总量一般在上,不太会用到空间,所以不在这里介绍这部分内容。 有了上一篇关于pids的热身之后,我们这篇将介绍稍微复杂点的内存控制。 本篇所有例子都在ubuntu-server-x86_64 16.04下执行通过 为什么需要内存控制? 代码总会有bug,有时会有内存泄漏,或者有意想不到的内存分...

    Ashin 评论0 收藏0
  • Linux CPU使用

    摘要:本人不是内核专家,关于软中断的部分请参考和虚拟机有关,当系统运行在虚拟机中时,当前虚拟机就会和宿主机以及其它的虚拟机共享,就表示当前虚拟机在等待为它服务的时间。 在Linux下面,可以通过top命令看到CPU的负载情况,其输出大概如下(只摘录CPU部分): top - 01:24:41 up 6 min, 2 users, load average: 0.00, 0.03, 0.0...

    xiangchaobin 评论0 收藏0
  • 十分钟看懂docker

    摘要:一些审计或一些统计,主要目的是为了计费。挂起进程,恢复执行进程。线程的划分尺度小于进程,使得多线程程序的并发性高。从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。 ...

    不知名网友 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<