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