2基于proc的Linux进程控制块信息读取-拓展实验 显示Linux进程控制块中更多的信息

2基于proc的Linux进程控制块信息读取-拓展实验 显示Linux进程控制块中更多的信息

一.实验目的

·了解Linux进程控制块task_strcut,并理解其重要成员变量的含义。
·理解基于seq_file机制的proc伪文件操作机制
·熟练掌握生成proc伪文件的Linux内核模块代码实现方法。
·认识Linux的进程概念,深入理解操作系统的进程概念

二.实验背景

·Linux进程调度策略

/* * Scheduling policies */
#define SCHED_NORMAL		0 //用于普通进程的分时调用
#define SCHED_FIFO		1 //先入先出调度算法
#define SCHED_RR		2   //轮流调度算法
#define SCHED_BATCH		3  //用于非交互式的批处理进程
/* SCHED_ISO: reserved but not implemented yet */
#define SCHED_IDLE		5 //在系统负载很低时使用

·Linux进程优先级
在task_struct结构体中有多个与进程优先级相关的成员变量,定义如下:
int prio, static_prio, normal_prio;
unsigned int rt_priority;
·prio 指的是任务当前的动态优先级,其值影响任务的调度顺序
·normal_prio 指的是任务的常规优先级,该值基于 static_prio和调度策略计算
·static_prio 指的是任务的静态优先级
·rt_priority 指的是任务的实时优先级。若为0表示非实时任务。

二.关键代码及分析

在这里插入图片描述
在这里插入图片描述

static int my_seq_show(struct seq_file *m, void *v)
{//获取进程的相关信息
  //printk(KERN_INFO"Invoke show\n");
  seq_printf( m,  "#%-3d ", taskcounts++ );
  seq_printf( m,  "%5d ", task->pid );
  seq_printf( m,  "%lu ", task->state );
  seq_printf( m,  "%-15s ", task->comm );
  seq_printf( m,  "%-5d ", task->prio); //优先级
  seq_printf( m,  "%-5d ", task->static_prio);
  seq_printf( m,  "%-5d ", task->normal_prio);
  seq_printf( m,  "%-5d ", task->rt_priority);
  seq_printf( m,  "%u ", task->policy);//调度策略
  seq_printf( m,  "%lu ", task->nvcsw);//上下文切换
  seq_printf( m,  "%lu ", task->nivcsw);
  seq_printf( m,  "%lu ", task->utime);//运行时间
  seq_printf( m,  "%lu ", task->stime);
seq_printf( m,  "%llu ", task->real_start_time);
  // 或则:seq_printf( m,  "%llu ", task->real_start_time);
  seq_puts( m, "\n" );
  return 0;
}

·将原来代码中的 seq_printf( m, "%lu ", task->real_start_time.tv_sec);
改为: seq_printf( m, "%llu ", task->real_start_time); // ns
其中real_start_time 为纳秒ns。
在这里插入图片描述

三.实验结果与分析

·make

在这里插入图片描述
·ls
在这里插入图片描述

·sudo insmod tasklist.ko
在这里插入图片描述
·dmesg
在这里插入图片描述
·sudo rmmod tasklist.ko
在这里插入图片描述
·dmesg
在这里插入图片描述

.cat /proc/tasklist
在这里插入图片描述

输出的信息增多了,分别显示了进程的 pid 、state、名称、优先级、运行时间、调度策略、上下文切换等信息,最后一项的单位为ns。

练习

在这里插入图片描述

13-1:源码:

#include <stdio.h>
#include <stdlib.h>

int main(int argv, char **args){

        char buf[100] = {0};
        if(argv > 1){
                FILE *f = fopen(args[1], "r");

                if(!f){
                        printf("error:cannot open file!\n");
                        return 0;
                }
                while(!feof(f)){
                        fgets(buf, sizeof(buf), f);

                        printf("%s", buf);
                }
        }
        return 0;
}

·编译运行

在这里插入图片描述

13-2

#include <linux/module.h>       // for init_module()
#include <linux/proc_fs.h>      // for create_proc_info_entry()
#include <linux/sched.h>        // for init_task
#include <linux/seq_file.h>     // for sequence files
#include <linux/slab.h>       // for kzalloc, kfree

char modname[] = "tasklist";
struct task_struct  *task;
int  taskcounts=0;                      // 'global' so value will be retained

static int my_seq_show(struct seq_file *m, void *v)
{//获取进程的相关信息
  //printk(KERN_INFO"Invoke show\n");
 for_each_process(task) {
        seq_printf( m,  "#%-3d ", taskcounts++ );
        seq_printf( m,  "%5d ", task->pid );
        seq_printf( m,  "%lu ", task->state );
        seq_printf( m,  "%-15s ", task->comm );
        seq_puts( m, "\n" );

 }
        return 0;
}


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


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>\nRemoving \'%s\' module\n", modname );
}

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

·make
在这里插入图片描述

·sudo insmod tasklist.ko
在这里插入图片描述

· cat /proc/tasklist
在这里插入图片描述
在这里插入图片描述

13-3

//tasklist.c

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

static ssize_t my_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos )
{
    char *tmp = kzalloc((count+1), GFP_KERNEL);
    if (!tmp)
        return -ENOMEM;
    if ( copy_from_user(tmp, buffer, count) ) {
        kfree(tmp);
        return -EFAULT;
    }

    kfree(str);

    str = tmp;

    return count;
}
//tasklist_test.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFSIZE 4096
char buf[BUFSIZE];

int main()
{
        unsigned long tmp,addr;
        int fd,len;
        char str[] = {"copy_from_user"};

        fd = open("/proc/tasklist",O_RDWR);
        write(fd,str,sizeof(str));
        len = read(fd, buf, BUFSIZE);
        printf("the read length is %d and the buf content is: \n%s\n",len,buf);
        sleep(2);
        close(fd);
        return 0;
}

·make
在这里插入图片描述
·sudo insmod tasklist.ko
在这里插入图片描述
·./tasklist_test
在这里插入图片描述
·cat /proc/tasklist
在这里插入图片描述

发布了170 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wct3344142/article/details/104133011