编写模块遍历系统中的进程(续)

上一次写了一个简单的通过模块 遍历进程链表。代码比较粗糙,而且每次需要用不同的方法进行遍历时需要修改源代码,这样很不方便。今天把这个重新修改了一下,增加了下面几个功能:

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


   这个程序现在主要问题就是写文件这块比较麻烦,我对文件读写这块不了解,等弄清了文件读写这部分之后再继续改进。

你可能感兴趣的:(list,function,struct,Module,each,traversal)