JH_Zhai的博客

破帽遮颜过闹市,漏船载酒泛中流。

Linux实践 | 如何打补丁 和 使用proc

作业:
1.通过模块传参,传入进程名隐藏相应进程
2.将tasklist.c与修改后的tasklist.c生成补丁

1.创建显示系统进程信息的proc模块

前置内容:
创建显示系统进程信息的proc模块
模块传参

1 编写tasklist.c

2 安装模块(参数传递 就是在这里传参的

sudo insmod tasklist.ko hide_task_name=systemd

3 查看模块

lsmod

这里写图片描述
4 卸载模块

sudo rmmod tasklist.ko

tasklist.c代码如下:

//-------------------------------------------------------------------
//  tasklist.c: 本内核文件创建一个proc伪文件,'/proc/tasklist'
//  通过如下命令可以显示系统中所有进程的部分信息
//  注意:Makefile文件必须正确放置在当前目录下。
//  编译命令: make 
//  内核模块添加:$sudo insmod tasklist.ko
//  添加内核模块后读取并信息tasklist内核信息: $ cat /proc/tasklist
//  内核模块删除:$sudo rmmod tasklist
//  NOTE: Written and tested with Linux kernel version 4.15.6 
//  strace函数可用于追踪系统调用,命令格式如下所示:
//  $ strace cat /proc/tasklist
//-------------------------------------------------------------------

#include <linux/module.h>   // for init_module() 
#include <linux/proc_fs.h>  // for create_proc_info_entry() 
#include <linux/sched/task.h>   // for init_task
#include <linux/seq_file.h> // for sequence files
#include <linux/slab.h>       // for kzalloc, kfree  
#include <linux/sched/signal.h>   //for next_task
char modname[] = "tasklist";
struct task_struct  *task;
int  taskcounts=0;          // 'global' so value will be retained

static char *hide_task_name;
module_param(hide_task_name, charp, 0);


static void * my_seq_start(struct seq_file *m, loff_t *pos)
{
   ///printk(KERN_INFO"Invoke start\n");   //可以输出调试信息
   if ( *pos == 0 )  // 表示遍历开始
   {
       task = &init_task;   //遍历开始的记录地址
       return &task;   //返回一个非零值表示开始遍历
  }
  else //遍历过程中
  { 
    if (task == &init_task )    //重新回到初始地址,退出
        return NULL;
    return (void*)pos   ;//否则返回一个非零值
  }  
}
static int my_seq_show(struct seq_file *m, void *v)
{//获取进程的相关信息
  //printk(KERN_INFO"Invoke show\n");
  //输出进程序号              
  seq_printf( m,  "#%-3d\t %d\t %ld\t %s",taskcounts++, task->pid,task->state,task->comm );  
  //输出进程pid?
  //输出进程state?
  //输出进程名称(comm)?
  seq_puts( m, "\n" );                    
  return 0; 
}

static void * my_seq_next(struct seq_file *m, void *v, loff_t *pos)
{
  //printk(KERN_INFO"Invoke next\n");  
 task=next_task(task);
 if (!(strcmp(task->comm ,hide_task_name)))
    task=next_task(task);
 (*pos)++;   
  //task指向下一个进程?
  return NULL;

}
static void my_seq_stop(struct seq_file *m, void *v)
{
    //printk(KERN_INFO"Invoke stop\n");     
    // do nothing        
}

static struct seq_operations my_seq_fops = {//序列文件记录操作函数集合
        .start  = my_seq_start,
        .next   = my_seq_next,
        .stop   = my_seq_stop,
        .show   = my_seq_show
};

static int my_open(struct inode *inode, struct file *file)  
{  
    return seq_open(file, &my_seq_fops); //打开序列文件并关联my_seq_fops
}  


static const struct file_operations my_proc =   
{  //proc文件操作函数集合
    .owner      = THIS_MODULE,  
    .open       = my_open,
    .read       = seq_read,     
    .llseek     = seq_lseek,
    .release    = seq_release       
}; 

int __init my_init( void )
{
    struct proc_dir_entry* my_proc_entry;
    printk( "<1>\nInstalling \'%s\' module\n", modname );
    my_proc_entry = proc_create(modname, 0x644, NULL, &my_proc);//生成proc文件
    if (NULL == my_proc_entry)
    {
        return -ENOMEM;
    }
    return  0;  //SUCCESS
}

void __exit my_exit( void )
{
    remove_proc_entry( modname, NULL );//删除proc文件
    printk( "<1>Removing \'%s\' module\n", modname );   
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL"); 

2.将tasklist.c与修改后的tasklist.c生成补丁

tasklist.c 原始文件

tasklist_o.c 修改好的文件

1、 生成补丁

diff -uN tasklist.c tasklist_o.c > x.patch

这里写图片描述
2、 给tasklist.c 打上补丁

patch tasklist.c < x.patch

这里写图片描述
x.patch

—源文件
+++变化后的文件
@@ -21,6 +21,10 @@变化位置
+添加内容
-删除内容

由于历史原因,diff有三种格式:
* 正常格式(normal diff)
* 上下文格式(context diff)
* 合并格式(unified diff)<——本文中看到的这种

--- tasklist.c  2018-04-15 07:17:38.997622096 -0700
+++ tasklist_o.c        2018-04-15 07:18:25.763577015 -0700
@@ -21,6 +21,10 @@
 struct task_struct  *task;
 int  taskcounts=0;                     // 'global' so value will be retained

+static char *hide_task_name;
+module_param(hide_task_name, charp, 0);
+
+
 static void * my_seq_start(struct seq_file *m, loff_t *pos)
 {
    ///printk(KERN_INFO"Invoke start\n");   //可以输出调试信息
@@ -40,7 +44,7 @@
 {//获取进程的相关信息
   //printk(KERN_INFO"Invoke show\n");
   //输出进程序号
-  seq_printf( m,  "#%-3d\t ", taskcounts++ );  
+  seq_printf( m,  "#%-3d\t %d\t %ld\t %s",taskcounts++, task->pid,task->state,task->comm );  
   //输出进程pid?
   //输出进程state?
   //输出进程名称(comm)?
@@ -51,7 +55,10 @@
 static void * my_seq_next(struct seq_file *m, void *v, loff_t *pos)
 {
   //printk(KERN_INFO"Invoke next\n");
-  (*pos)++;   
+ task=next_task(task);
+ if (!(strcmp(task->comm ,hide_task_name)))
+       task=next_task(task);
+ (*pos)++;   
   //task指向下一个进程?
   return NULL;

这里写图片描述

阅读更多
个人分类: Linux
上一篇论文阅读 | 知识图谱构建
下一篇在利用支持向量机进行分类的时候怎么选择合适的核函数?
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭