Chinaunix首页 | 论坛 | 博客
  • 博客访问: 927213
  • 博文数量: 146
  • 博客积分: 3321
  • 博客等级: 中校
  • 技术积分: 1523
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-29 10:32
文章分类

全部博文(146)

文章存档

2014年(2)

2013年(5)

2012年(4)

2011年(6)

2010年(30)

2009年(75)

2008年(24)

分类: LINUX

2010-04-01 12:31:22

    上一次写了一个简单的通过模块遍历进程链表。代码比较粗糙,而且每次需要用不同的方法进行遍历时需要修改源代码,这样很不方便。今天把这个重新修改了一下,增加了下面几个功能:
1.通过模块参数选择使用那个方法进行遍历
2.可以将测试的结果写入文件

trave_process.c

/*****************************************
 *功能:利用进程链表遍历当前系统中的所有进程
 *同时可以打印出进程的相关信息
 *此程序可以将比较信息输出到指定的文件中
 *
 *author:孟阿龙(XiyouLinux)

 *url:http://boyan.cublog.cn
 * ***************************************/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/mm.h>


MODULE_AUTHOR( "Along" );
MODULE_LICENSE( "GPL" );

struct task_struct *task = NULL, *p = NULL;
struct list_head *pos = NULL;
struct timeval start, end;
int count = 0;

/*function_use表示使用哪一种方法测试,
 * 0:三个方法同时使用,
 * 1:list_for_each,
 * 2:list_for_each_entry,
 * 3:for_each_process
 */

int function_use = 0;
char *method;
char *filename="testlog";

void print_message(void);
void writefile( char* filename, char *data );
void traversal_list_for_each(void);
void traversal_list_for_each_entry(void);
void traversal_for_each_process(void);


static int init_module_list(void)
{
    switch(function_use) {
        case 1:
            traversal_list_for_each();
            break;
        case 2:
            traversal_list_for_each_entry();
            break;
        case 3:
            traversal_for_each_process();
            break;
        default:
            traversal_list_for_each();
            traversal_list_for_each_entry();
            traversal_for_each_process();
            break;
    }
    return 0;
}
static void exit_module_list(void)
{
    printk( KERN_ALERT "GOOD BYE!!\n");
}

module_init( init_module_list );
module_exit( exit_module_list );
module_param(function_use, int, S_IRUGO);

void print_message(void)
{
    char *str1 = "the method is: ";
    char *str2 = "系统当前共 ";
    char *str3 = " 个进程\n";
    char *str4 = "开始时间: ";
    char *str5 = "\n结束时间: ";
    char *str6 = "\n时间间隔: ";
    char *str7 = ".";
    char *str8 = "ms";
    char data[1024];
    char tmp[50];
    int cost;

    printk("系统当前共 %d 个进程!!\n", count);
    printk("the method is : %s\n", method);
    printk("开始时间:%10i.%06i\n", (int)start.tv_sec, (int)start.tv_usec);
    printk("结束时间:%10i.%06i\n", (int)end.tv_sec, (int)end.tv_usec);
    printk("时间间隔:%10i\n", (int)end.tv_usec-(int)start.tv_usec);

    memset(data, 0, sizeof(data));
    memset(tmp, 0, sizeof(tmp));

    strcat(data, str1);
    strcat(data, method);
    strcat(data, str2);
    snprintf(tmp, sizeof(count), "%d", count);
    strcat(data, tmp);
    strcat(data, str3);
    strcat(data, str4);


    memset(tmp, 0, sizeof(tmp));
    /*
     * 下面这种转换秒的方法是错误的,因为sizeof最终得到的长度实际是Int类型的
     * 长度,而实际的妙数有10位数字,所以最终存到tmp中的字符串也就只有三位
     * 数字
     * snprintf(tmp, sizeof((int)start.tv_sec),"%d",(int)start.tv_usec );
    */

    
    /*取得开始时间的秒数和毫秒数*/

    snprintf(tmp, 10,"%d",(int)start.tv_sec );
    strcat(data, tmp);
    snprintf(tmp, sizeof(str7),"%s",str7 );
    strcat(data, tmp);
    snprintf(tmp, 6,"%d",(int)start.tv_usec );
    strcat(data, tmp);

    strcat(data, str5);
    
    /*取得结束时间的秒数和毫秒数*/

    snprintf(tmp, 10,"%d",(int)end.tv_sec );
    strcat(data, tmp);
    snprintf(tmp, sizeof(str7),"%s",str7 );
    strcat(data, tmp);
    snprintf(tmp, 6,"%d",(int)end.tv_usec );
    strcat(data, tmp);

    /*计算时间差,因为可以知道我们这个程序花费的时间是在
     *毫秒级别的,所以计算时间差时我们就没有考虑秒,只是
     *计算毫秒的差值
     */

    strcat(data, str6);
    cost = (int)end.tv_usec-(int)start.tv_usec;
    snprintf(tmp, sizeof(cost),"%d", cost );

    strcat(data, tmp);
    strcat(data, str8);
    strcat(data, "\n\n");

    writefile(filename, data);
    printk("%d\n", sizeof(data));


}
void writefile( char* filename, char *data )
{
    struct file *filp;
    mm_segment_t fs;

    filp = filp_open(filename, O_RDWR|O_APPEND|O_CREAT, 0644); ;
    if(IS_ERR(filp)) {
        printk("open file error...\n");
        return ;
    }
    fs = get_fs();
    set_fs(KERNEL_DS);
    filp->f_op->write(filp, data, strlen(data), &filp->f_pos);
    set_fs(fs);
    filp_close(filp, NULL);
}
void traversal_list_for_each(void)
{

    task = &init_task;
    count = 0;
    method="list_for_each\n";

    do_gettimeofday(&start);
    list_for_each( pos, &task->tasks ) {
        p = list_entry( pos, struct task_struct, tasks );
        count++;
        printk( KERN_ALERT "%d\t%s\n", p->pid, p->comm );
    }
    do_gettimeofday(&end);
    
    print_message();
    
}

void traversal_list_for_each_entry(void)
{

    task = &init_task;
    count = 0;
    method="list_for_each_entry\n";

    do_gettimeofday(&start);
    list_for_each_entry( p, &task->tasks, tasks ) {
        count++;
        printk( KERN_ALERT "%d\t%s\n", p->pid, p->comm );
    }
    do_gettimeofday(&end);

    print_message();
}

void traversal_for_each_process(void)
{
    count = 0;
    method="for_each_process\n";

    do_gettimeofday(&start);
    for_each_process(task) {
        count++;
        printk( KERN_ALERT "%d\t%s\n", task->pid, task->comm );
    }
    do_gettimeofday(&end);
            
    print_message();
}


Makefile:


obj-m := trave_process.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
    make -C $(KERNELDIR) M=$(PWD) modules
clean:
    make -C $(KERNELDIR) M=$(PWD) clean
    rm -fr *.markers *.order


测试方法:
insmod trave_process.ko             /*选择同时使用三种方法进行遍历*/
insmod trave_process.ko function_use=1        /*选择使用list_for_each*/
insmod trave_process.ko function_use=2         /*选择使用list_for_each_entry*/
insmod trave_process.ko function_use=3         /*选择使用for_each_process*/

模块加载完成之后,会在当前模块所在目录下生成相应的测试报告 testlog。

along@along-laptop:~/code/modules/list_process_tofile$ cat testlog
the method is: list_for_each
系统当前共 160 个进程
开始时间: 127009604.25840
结束时间: 127009604.25892
时间间隔: 520ms

the method is: list_for_each_entry
系统当前共 160 个进程
开始时间: 127009604.25906
结束时间: 127009604.25956
时间间隔: 499ms

the method is: for_each_process
系统当前共 160 个进程
开始时间: 127009604.25962
结束时间: 127009604.26011
时间间隔: 497ms


   这个程序现在主要问题就是写文件这块比较麻烦,我对文件读写这块不了解,等弄清了文件读写这部分之后再继续改进。
阅读(1146) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~