在Linux内核之中取得进程名是比较简单的,

task_struct结构的comm成员就是进程名,

但要取得进程合路径名,就比较难一点.

以下代码对此过程进行演示.

 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/dcache.h>
#include <linux/fs.h>
#include <linux/err.h>

#include <linux/string.h>
#include <linux/errno.h>

#include <asm/fcntl.h>
#include <asm/processor.h>
#include <asm/uaccess.h>

 

MODULE_LICENSE("Dual BSD/GPL");
int add_integar(int a,int b)

 return (a + b);
}

int sub_integar(int a,int b)
{
  return (a - b);
}

EXPORT_SYMBOL(add_integar);
EXPORT_SYMBOL(sub_integar);

 

int init_module(void)
{
  int result = 0;
 struct task_struct *task = NULL;
 char *path = NULL,*ptr = NULL;
 char *read_buf = NULL;
 struct file* filp = NULL;
 mm_segment_t old_fs;


 task = current;
 read_buf = kmalloc(PAGE_SIZE,GFP_KERNEL);
 if (!read_buf)
 {
  printk("KK Read Buf Alloc Error!\r\n");
  return 0;
 }
 path = kmalloc(PAGE_SIZE,GFP_KERNEL);
 if (!path)
 {
  printk("KK Allocate Error\r\n");
  return 0;
 }

 for_each_process(task)
 {
  //if (task && task->mm && task->mm->exe_file && task->mm->exe_file->f_path)
  if (task && task->mm && task->mm->exe_file) // && (task->mm->exe_file->f_path))
  {
   //if (task->mm->exe_file->f_path)
   {
    ptr = d_path(&task->mm->exe_file->f_path,path,PAGE_SIZE);
   }
   //else
   //{
   // printk("KK path is NULL");
   //}
  }
  else
  {
   printk("task list NULL \r\n");
  }
  //task->mm->exe_file->f_path;
  printk("ProcName:%s PID:[%d]\n",task->comm,task->pid);
  printk(KERN_ALERT"PATH:%s\r\n",IS_ERR(ptr)?"NULL":ptr);    //此时ptr就是进程全路径名

  if (!IS_ERR(ptr))
  {
   printk("Read FileName:%s \n",ptr);
   filp = filp_open(ptr,O_RDONLY,0);  //打开进程文件
   if (!filp)
   {
    printk("Open File:%s  Failture \n",ptr);
   }  
   else
   {
    printk("Open File:%s Successful \n",ptr);
    
    old_fs = get_fs();
    set_fs(get_ds());

    if (filp->f_op && filp->f_op->read)
    {
     result = filp->f_op->read(filp,read_buf,PAGE_SIZE,&filp->f_pos);  //读进程文件
    }
    
    if (0 == result)
    {
     printk("Read File:%s Error \n",ptr);
    }
    else
    {
     printk("Read File:%s Length:%d Success \n",ptr,result);

    }

    

    set_fs(old_fs);

    filp_close(filp,NULL);
    //read(filp,read_buf,PAGE_SIZE)
   }
  }
  //printk("%x",task->thread);

  //printk("%d %d ",current->pid,t);

 }

 //==================test  read write log file=====================
#define MY_FILE  "/root/log_file.log"
 filp = filp_open(MY_FILE,O_CREAT|O_RDWR,0600);
 if (filp)
 {
  old_fs = get_fs();
  set_fs(get_ds());

  result = filp->f_op->write(filp,read_buf,PAGE_SIZE,&filp->f_pos);
  if (result)
  {
   printk("New Log Write OK Length:%d \n",result);
  }
  else
  {
   printk("Write Log File Error \n");
  }

  set_fs(old_fs);

  filp_close(filp,NULL);
 }
 else
 {
  printk("Create New Log file failtrue!!\n");
 }
 

 

 kfree(read_buf);
 read_buf = NULL;
 kfree(path);
 path = NULL;

 printk(KERN_INFO"Loading the module ...KK\n");
 return 0;
}

void cleanup_module(void)
{
 printk(KERN_INFO"Unloading the module...KK...\n");

 return ;
}

要注意的地方:

set_fs(get_ds())函数的作用是设置进程能访问的虚拟地址的空间范围。
如果不设置,系统会认为是用户空间,只有3G,所以在内核时,特别是
在调用其它的系统调用时,也必须如此,否则,就会出错!!!!!!!