转 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\n",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.\tPid\tCMD\n%d\t%d\t%s\n",count,p->pid,p->comm);
            l=l+length;
        }
        else{
            length=sprintf(c+l,"%d\t%d\t%s\n",count,p->pid,p->comm);
            l=l+length;
        }
    }
    printk(KERN_INFO "Total number of processes is: %d\n",count);
    length=sprintf(c+l,"Total number of processes is %d\n",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.\n", 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.\n",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\t\t%d\t\t\t%s\n",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!\n");
        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\t\tppid\t\t\tcommand\n");
    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看下在linux\sched.h里...  pid parent->pid comm就是我们要的pid ppid cmd
   注意当你添加了linux\sched.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\t\t%d\t\t\t%s\n",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!\n");
        return -1;
    }
    entry->mode = S_IFREG | 0444;
    entry->size = 0;
    entry->read_proc = ps_read;

    printk("%d, %d, %s\n", 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\t\tppid\t\t\tcommand\n");
    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\t\t%d\t\t\t%s\n",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\t%s\t%s\t%s\t%s\n","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\t%d\t%d\t%d\t%s\n",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);

posted @ 2014-04-10 14:35  i0ject  阅读(577)  评论(0编辑  收藏  举报