• 转 Linux内核 Ps模块


    ricky_proc.c源码:
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/proc_fs.h>
    #include <linux/thread_info.h>
    #include <linux/list.h>
    #include <linux/sched.h>

    #define MODULE_VERSION "1.0"
    #define MODULE_NAME "ricky_proc_info_final"
    #define P_MAX_LEN 30
    #define ARRAYMAX 4096

    static struct proc_dir_entry *ricky_file, *ricky_dir;
    static char c[ARRAYMAX];

    static int proc_read_info(char *page,char **start,off_t off,int count, int *eof,void *data)
    {
        int len=0;
        char *c = (char *)ricky_file->data;
        len=sprintf(page,"%s ",c);
        return len;
    }

    static int __init ricky_info_init(void)
    {
        //get_current() is defined to current
        //so we could get a task by "current"
        struct task_struct *task_c;
        task_c = current;
        struct task_struct *p;
        struct list_head *pos;
        int count=0;
       
        int rv=0;
        //create proc directory
        ricky_dir = proc_mkdir(MODULE_NAME, NULL);
        if(ricky_dir==NULL){
            rv=-ENOMEM;
            goto out;
        }
        ricky_dir->owner = THIS_MODULE;
        //create proc file
        ricky_file=create_proc_entry("rickyps",0644,ricky_dir);
        if(ricky_file==NULL){
            rv=-ENOMEM;
            goto no_rickyps;
        }
        //traversal of task_list
        int length=0;
        int l=0;
        list_for_each(pos, &task_c->tasks){
           
            //get the list_entry
            p=list_entry(pos, struct task_struct, tasks);
            count++;
            if(count==1){
                length+=sprintf(c+l,"No. Pid CMD %d %d %s ",count,p->pid,p->comm);
                l=l+length;
            }
            else{
                length=sprintf(c+l,"%d %d %s ",count,p->pid,p->comm);
                l=l+length;
            }
        }
        printk(KERN_INFO "Total number of processes is: %d ",count);
        length=sprintf(c+l,"Total number of processes is %d ",count);
        l=l+length;
       
        //link proc file
        ricky_file->data=c;
        ricky_file->read_proc=proc_read_info;
        ricky_file->owner=THIS_MODULE;
       
        printk(KERN_INFO "%s %s initialized. ", MODULE_NAME, MODULE_VERSION);
        return 0;
       
        no_rickyps:
            remove_proc_entry("rickyps",ricky_dir);
        out:
            return rv;
    }

    static void __exit ricky_info_exit(void)
    {
        remove_proc_entry("rickyps",ricky_dir);
        remove_proc_entry(MODULE_NAME,NULL);
        printk(KERN_INFO "%s %s has been removed. ",MODULE_NAME,MODULE_VERSION);
    }

    MODULE_AUTHOR("Ricky Song");
    MODULE_LICENSE("GPL");

    module_init(ricky_info_init);
    module_exit(ricky_info_exit);


    Makefile文件:
    obj-m := ricky_proc.o
    all:
        make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
    clean:
        rm -rf *.o *.mod.c *.ko Modules.symvers

    内核模块创建在proc文件系统上建立_ps文件.遍例进程内核链表task_struct.将遍例结果存入缓冲区.影射到/proc/_ps文件中.用户态的程序去读取 这个文件.打印显示 当前进程的的pid,ppid 和进程名.

     
    CODE:
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/proc_fs.h>
    #include <linux/init.h>
    #include <linux/sched.h>

    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("mq110");

    static int ps_read(char *page, char **start, off_t offset,int count, int *eof, void *data)  
    {
        static char buf[1024*8]={0};
        char tmp[128];
        struct task_struct *p;
       

        if(offset >0)
            return 0;
        memset(buf,0,sizeof(buf));
        read_lock(&tasklist_lock);
        for_each_process(p)   //遍例内核进程链表.
        {
            sprintf(tmp,"%d %d %s ",p->pid,p->parent->pid,p->comm);
            strcat(buf,tmp);
            memset(tmp,0,sizeof(tmp));
        }
        read_unlock(&tasklist_lock);
        *start=buf;
        return strlen(buf);
    }

    static __init int ps_init(void)
    {
        struct proc_dir_entry *entry;

        entry = create_proc_entry("_ps", 0444, &proc_root);  //建立/proc/_ps文件.
        if(entry == 0)
        {
            printk(KERN_ERR "create_proc_entry failed! ");
            return -1;
        }
        entry->mode = S_IFREG | 0444;
        entry->size = 0;
        entry->read_proc = ps_read;
        return 0;
    }
    static __exit void ps_cleanup(void)
    {
        remove_proc_entry("_ps", &proc_root);
    }

    module_init(ps_init);
    module_exit(ps_cleanup);


    以下是Makefile. TARGET改名成程序名就OK了.

     
    CODE:
    TARGET = 006
    obj-m := $(TARGET).o
    KERNELDIR=/lib/modules/`uname -r`/build
    PWD=`pwd`

    default :
       $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

    install :
       insmod $(TARGET).ko
    uninstall :
       rmmod $(TARGET).ko

    clean :
       rm -rf *.o *.mod.c *.ko


    以下是用户态程序:

     
    CODE:
    #include <stdio.h>
    #include <error.h>

    int main()
    {
        FILE *fp;
        char buf[1024];

        fp=fopen("/proc/_ps","r");
        if(fp==NULL)
        {
            perror("fopen");
            return -1;
        }
        printf("pid ppid command ");
        while(!feof(fp))
        {
            if(fgets(buf,sizeof(buf),fp)!=NULL)
                printf("%s",buf);
        }
        fclose(fp);
        return 0;
    }


    make ;make install 之后 编译用户态程序.
    执行结果:
    [root@Firewall 006]# ./likeps
    pid             ppid                    command
    1               0                       init
    2               1                       migration/0
    3               1                       ksoftirqd/0
    4               1                       watchdog/0
    5               1                       migration/1
    6               1                       ksoftirqd/1
    7               1                       watchdog/1
    8               1                       migration/2
    9               1                       ksoftirqd/2
    10              1                       watchdog/2
    11              1                       migration/3
    12              1                       ksoftirqd/3
    13              1                       watchdog/3
    14              1                       events/0
    15              1                       events/1
    16              1                       events/2
    17              1                       events/3
    18              1                       khelper
    19              1                       kthread
    24              19                      kacpid
    100             19                      kblockd/0
    101             19                      kblockd/1
    102             19                      kblockd/2
    103             19                      kblockd/3
    106             19                      khubd
    197             19                      pdflush
    198             19                      pdflush
    199             1                       kswapd0
    200             19                      aio/0
    201             19                      aio/1
    202             19                      aio/2
    203             19                      aio/3
    288             19                      kseriod
    392             1                       kjournald
    1224            1                       udevd
    1941            1                       kjournald
    1944            1                       kjournald
    1967            1                       kjournald
    2820            1                       syslogd
    2824            1                       klogd
    2840            1                       sshd
    2852            1                       vsftpd
    2862            1                       gpm
    2882            1                       atd
    3184            1                       mingetty
    3185            1                       mingetty
    3186            1                       mingetty
    3187            1                       mingetty
    3188            1                       mingetty
    3189            1                       mingetty
    6819            1                       mysqld_safe
    6846            6819                    mysqld
    7475            1                       smbd
    7476            7475                    smbd
    7480            1                       nmbd
    19400           2840                    sshd
    19404           19400                   bash

    ------------------------------------------------------------

    让我们先来看看一个重要的结构体吧...struct task_struct 自己用sourceinsight看下在linuxsched.h里...  pid parent->pid comm就是我们要的pid ppid cmd
       注意当你添加了linuxsched.h后就有个current给你使用了,也是struct task_struct的...可以打印自身的pid cmd等
     
    pid.c

    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/proc_fs.h>
    #include <linux/init.h>
    #include <linux/sched.h>

    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("kenthy@163.com");

    static int ps_read(char *page, char **start, off_t offset,int count, int*eof, void *data) 
    {
        static char buf[1024*8]={0};
        char tmp[128];
        struct task_struct *p;
       

        if(offset >0)
            return 0;
        memset(buf,0,sizeof(buf));
        read_lock(&tasklist_lock);
        for_each_process(p) 
        {
            sprintf(tmp,"%d %d %s ",p->pid,p->parent->pid,p->comm);
            strcat(buf,tmp);
            memset(tmp,0,sizeof(tmp));
        }
        read_unlock(&tasklist_lock);
        *start=buf;
        return strlen(buf);
    }

    static __init int ps_init(void)
    {
        struct proc_dir_entry *entry;

        entry = create_proc_entry("_ps", 0444, &proc_root);
        if(entry == 0)
        {
            printk(KERN_ERR "create_proc_entry failed! ");
            return -1;
        }
        entry->mode = S_IFREG | 0444;
        entry->size = 0;
        entry->read_proc = ps_read;

        printk("%d, %d, %s ", current->pid, current->parent->pid, current->comm);
        return 0;
    }

    static __exit void ps_cleanup(void)
    {
        remove_proc_entry("_ps", &proc_root);
    }

    module_init(ps_init);
    module_exit(ps_cleanup);


     user.c

    #include <stdio.h>
    #include <error.h>

    int main()
    {
        FILE *fp;
        char buf[1024];

        fp=fopen("/proc/_ps","r");
        if(fp==NULL)
        {
            perror("fopen");
            return -1;
        }
        printf("pid ppid command ");
        while(!feof(fp))
        {
            if(fgets(buf,sizeof(buf),fp)!=NULL)
                printf("%s",buf);
        }
        fclose(fp);
        return 0;
    }

    Makefile:

    obj-:= pid.o

    KDIR := /lib/modules/$(shell uname -r)/build/
    PWD := $(shell pwd)

    all:module

    module:
        $(MAKE) -C $(KDIR) M=$(PWD) modules


    clean:
        rm -rf *.ko *.mod.*.o Module.* modules.* .*.cmd .tmp_versions

    可以对ps_read做如下改进

    static int ps_read(char *page, char **start, off_t off,int count, int*eof, void *data) 
    {
                int len = 0;
                struct task_struct *p;
              
               read_lock(&tasklist_lock);
                for_each_process(p)
                         len += sprintf(page+len,"%d %d %s ",p->pid,p->parent->pid,p->comm);
                read_unlock(&tasklist_lock);

                if (len <= off+count) *eof = 1;
                *start = page + off;
                len -= off;
                if (len>count) len = count;
                if (len<0) len = 0;
                return len;
    }

     for_each_process(p)遍历每一个进程

     
     
    还可以用seq写个
     

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/proc_fs.h> //proc_fs

    #include <linux/seq_file.h> //seq_file

    #include <linux/fs.h> //struct file,struct inode

    #include <linux/sched.h> //next_task()


    MODULE_AUTHOR("xunil@bmy");
    MODULE_LICENSE("GPL");
    MODULE_DESCRIPTION("a test module utilise the seq_file mechanism");

    static void *ps_seq_start(struct seq_file *s,loff_t *pos){
            struct task_struct *task;
                    
            seq_printf(s,"%s %s %s %s %s ","pid","ppid","uid","gid","comm");
            
            if(*pos>0)
                    return NULL;
            else{
                    task=next_task(current);
                    return task;
            }
    }

    static void *ps_seq_next(struct seq_file *s,void *v,loff_t *pos){
            struct task_struct *task=(struct task_struct *)v;
            ++*pos;
            if(task->pid== current->pid){
                    return NULL;
            }else{
                    task=next_task(task);
                    return task;
            }
    }

    static void ps_seq_stop(struct seq_file *s,void *v){}

    static int ps_seq_show(struct seq_file *s,void *v){
            rwlock_t lock = RW_LOCK_UNLOCKED;
            struct task_struct *task=(struct task_struct *)v;
            read_lock(&lock);
            seq_printf(s,"%d %d %d %d %s ",task->pid,task->parent->pid,task->uid,task->gid,task->comm);
            read_unlock(&lock);
            return 0;
    }

    static struct seq_operations ps_seq_ops = {
            .start = ps_seq_start,
            .next = ps_seq_next,
            .stop = ps_seq_stop,
            .show = ps_seq_show
    };

    static int ps_open(struct inode *inode,struct file *file){
            return seq_open(file,&ps_seq_ops);
    }

    static struct file_operations ps_file_ops = {
            .owner = THIS_MODULE,
            .open = ps_open,
            .read = seq_read,
            .llseek = seq_lseek,
            .release= seq_release
    };



    static int __init ps_init(void){
            struct proc_dir_entry *entry;
            entry = create_proc_entry("myps",0,NULL);
            if(entry)
                    entry->proc_fops = &ps_file_ops;
            return 0;
    }

    static void __exit ps_exit(void){
            remove_proc_entry("myps",NULL);
    }

    module_init(ps_init);
    module_exit(ps_exit);

  • 相关阅读:
    HDU 6043 KazaQ's Socks
    HDU 6033 Add More Zero
    D
    D
    L
    关于G
    excel函数实现下拉框控制显示不同内容
    牛客网暑期ACM多校训练营(第五场)J-plan (模拟)
    牛客网暑期ACM多校训练营(第五场)G-max (math)
    牛客网暑期ACM多校训练营(第五场)A-gap (二分答案)
  • 原文地址:https://www.cnblogs.com/i0ject/p/3656460.html
Copyright © 2020-2023  润新知