文章目录

实验目的

掌握虚拟文件系统的实现原理

实践文件、目录、文件系统等概念

实验内容

在Linux0.11上实现procfs(proc文件系统)内的psinfo节点,当读取此节点的内容的时候,可得到系统当前所有进程的状态信息,例如,用cat命令显示/proc/procfo的内容,可得到:

# cat /proc/psinfo

pid state father counter start_time

0 1 -1 0 0

1 1 0 28 1

4 1 1 1 73

3 1 1 27 63

6 0 4 12 817

# cat /proc/hdinfo

total_blocks: 62000;

free_blocks: 39037;

used_blocks: 22963;

procfs及其节点要在内核启动时自动创建,相关功能的实现放在fs/proc.c文件。

实验过程

第一步: 增加新文件类型,在include/sys/stat.h文件中定义了几种文件类型和相应的测试宏:

//已有的宏定义

#define S_IFMT 00170000 //文件类型(都是8进制表示)

#define S_IFREG 0100000//普通文件

#define S_IFCHAR 0020000 //字符设备文件

#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) //测试m是否是普通文件

#define S_ISCHAR(m) (((m) & S_IFMT) == S_IFCHAR) //测试m是否是字符设备文件

//proc文件的宏定义/宏函数

#define S_IFPROC 0030000

#define S_ISPROC(m) (((m) & S_IFMT) == S_IFPROC) //测试m是否是proc文件

第二步: 让mknod()支持新的文件类型,文件/proc/psinfo以及/proc/hdinfo索引节点需要通过mknod()系统调用建立,所以要让它支持新的文件类型,直接修改fs/namei.c文件中的sys_mknod()函数的代码,在其中增加关于proc文件系统的判断:

if(S_ISBLK(mode) || S_ISCHAR(mode) || S_ISPROC(mode))

inode->izone[0] = dev;

第三步: 进程proc文件初始化,可以在系统启动时就建立那些proc文件系统(根目录/proc)下的proc文件(其下的子文件/proc/psinfo、/proc/hdinfo),通常Linux操作系统也都是在系统启动以后就直接创建那些proc文件的,显然要修改系统启动时的调用的main(),因为是要创建文件,所以当然应该在文件系统已经挂载以后才可以操作,在main()的最后会从内核态切换到用户态,并调用init(),而init()要做的第一件事就是挂载根文件系统:

void init(void)

{

setup((void *) &drive_info);

}

显然在执行setup((void *) &drive_info)的时候,也就是根文件系统挂载以后就可以创建proc文件了,首先建立/proc目录,然后再建立该目录下的各个proc文件节点,建立目录用mkdir(),建立文件用mknod()。

现在可以调用mkdir()来创建proc目录,调用mknod()来创建proc目录下的各个proc文件节点了。

内核初始化的全部工作是在main()中完成,而/init/main()在最后从内核态切换到用户态,并调用init()。init()做的第一件事情就是挂载根文件系统:setup((void *) &drive_info);

procfs的初始化工作应该在根文件系统挂载之后开始。它包括两个步骤:

建立/proc目录

建立/proc目录下的各个结点

建立目录和结点分别需要调用mkdir()和mknod()系统调用。因为初始化时已经在用户态,所以不能直接调用sys_mkdir()和sys_mknod()。必须在初始化代码所在文件中实现这两个系统调用的用户态接口,即API:

_syscall2(int,mkdir,const char*,name,mode_t,mode)

_syscall3(int,mknod,const char *,filename,mode_t,mode,dev_t,dev)

mkdir()时mode参数的值可以是“0755”(rwxr-xr-x),表示只允许root用户改写此目录,其它人只能进入和读取此目录。

procfs是一个只读文件系统,所以用mknod()建立psinfo结点时,必须通过mode参数将其设为只读。建议使用“S_IFPROC|0444”做为mode值,表示这是一个proc文件,权限为0444(r--r--r--),对所有用户只读。

mknod()的第三个参数dev用来说明结点所代表的设备编号。对于procfs来说,此编号可以完全自定义。proc文件的处理函数将通过这个编号决定对应文件包含的信息是什么。例如,可以把0对应psinfo,1对应hdinfo,2对应inodeinfo。

上述步骤完成以后,就可以使用make all编译内核,然后./run运行内核,使用ll /proc可以看到:

inode->i_mode就是通过mknod()设置的mode。信息中的XXX和你设置的S_IFPROC有关。通过此值可以了解mknod()工作是否正常。这些信息说明内核在对psinfo进行读操作时不能正确处理,向cat返回了EINVAL错误。因为还没有实现处理函数,所以这是很正常的。

注意:博主在此没截使用cat命令的图片,但是就是这个么道理,嘻嘻。

这些信息至少说明,psinfo被正确open()了。所以我们不需要对sys_open()动任何手脚,唯一要打补丁的,是sys_read()。

第四步: 让proc文件(psinfo、hdinfo、inodeinfo)可读

open()没有问题,那么需要修改的就是sys_read()了。

首先在fs/read_write.c中添加extern,表示proc_read函数是从外部调用的。

在.c文件中要引入另一个文件,而且是另一个.c文件的全局变量或者函数,就需要用extern来说明一下。

然后仿照其他if语句,添加proc文件的proc_read()调用。

第五步: 实现上述的proc_read()函数,用于读取proc文件内容,实现在fs/proc.c文件下。

#include

#include

#include

#include

#include

extern int vsprintf(char * buf, const char * fmt, va_list args);

//Linux0.11没有sprintf(),该函数是用于输出结果到字符串中的,所以就实现一个,这里是通过vsprintf()实现的。

int sprintf(char *buf, const char *fmt, ...){

va_list args; int i;

va_start(args, fmt);

i=vsprintf(buf, fmt, args);

va_end(args);

return i;

}

int proc_read(int dev, char * buf, int count, unsigned long * pos){

struct task_struct ** p;

int output_count=0;

char * proc_buf=NULL;

int file_size=0;

int offset=*pos;

struct super_block * sb;

struct buffer_head * bh;

int total_blocks, total_inodes;

int used_blocks=0, free_blocks=0;

int i,j,k;

char * db=NULL;

//硬盘总共有多少块(空闲 + 非空闲),有多少inode索引节点等信息都放在super块中。

sb=get_super(current->root->i_dev);

total_blocks = sb->s_nzones;

total_inodes=sb->s_ninodes;

s_imap_blocks = sb->s_imap_blocks;

s_zmap_blocks = sb->s_zmap_blocks;

//psinfo: 对应的就是输出系统此时的全部进程的状态信息

if(dev==0)

{

proc_buf=(char *)malloc(sizeof(char *)*1024);

file_size=sprintf(proc_buf,"pid\tstate\tfather\tcounter\tstart_time\n");

//这里借鉴了,进程切换函数schedule()的代码,也就是遍历系统全部的进程。

for(p = &LAST_TASK ; p >= &FIRST_TASK ; --p)

if(*p)

file_size+=sprintf(proc_buf+file_size,"%d\t%d\t%d\t%d\t%d\n",(*p)->pid,(*p)->state,(*p)->father,(*p)->counter,(*p)->start_time);

*(proc_buf+file_size)='\0';

}

//hdinfo: 打印出硬盘的一些信息,

//s_imap_blocks、ns_zmap_blocks、

//total_blocks、free_blocks、used_blocks、total_inodes

if(dev==1)

{

for(i=0;is_zmap_blocks;i++)

{

bh=sb->s_zmap[i];

db=(char*)bh->b_data;

for(j=0;j<1024;j++){

for(k=1;k<=8;k++){

if((used_blocks+free_blocks)>=total_blocks)

break;

if( *(db+j) & k)

used_blocks++;

else

free_blocks++;

}

}

}

proc_buf=(char*)malloc(sizeof(char*)*512);

file_size=sprintf(proc_buf,"s_imap_blocks:%d\ns_zmap_blocks:%d\n",s_imap_blocks,s_zmap_blocks);

file_size+=sprintf(proc_buf+file_size,"total_blocks:%d\nfree_blcoks:%d\nused_blocks:%d\ntotal_indoes:%d\n",total_blocks,free_blocks,used_blocks,total_inodes);

}

//将proc_buf缓冲区的内容放入文件

while(count>0)

if(offset>file_size)

break;

put_fs_byte(*(proc_buf+offset),buf++);

offset++;

output_count++;

count--;

}

//重置文件的pos位置,也就是指向文件末尾的指针

(*pos)+=output_count;

free(proc_buf);

return output_count;

}

由于添加了一个文件proc.c,所以需要改下fs/Makefile,

上述的代码,是用的这位同学的,在此表示感谢!

(但是我搞不清为什么是proc_dev,添加的文件不是proc.c吗,如果有人可以解答,可以评论下。)

然后make all编译内核,./run运行内核,输出cat命令,即可查看psinfo(当前系统进程状态信息)和hdinfo(硬盘信息)的信息。

实验问题

如果要求你在psinfo之外再实现另一个结点,具体内容自选,那么你会实现一个给出什么信息的结点?为什么?

我会实现meminfo、cpuinfo这些节点,分别对应的信息是系统内存信息和cpu的信息,原因是我只知道这两个名词了

一次read()未必能读出所有的数据,需要继续read(),直到把数据读空为止。而数次read()之间,进程的状态可能会发生变化。你认为后几次read()传给用户的数据,应该是变化后的,还是变化前的? 如果是变化后的,那么用户得到的数据衔接部分是否会有混乱?如何防止混乱? 如果是变化前的,那么该在什么样的情况下更新psinfo的内容?

我认为后几次read()传递给用户的数据应该是变化前的,因为读完一部分数据之后,之前读取的进程状态信息可能已经发生了改变了,那么读给proc_buf缓冲区的内容还是读之前的,所以可能会导致读到的数据出现混乱(数据不正确?),要使得数据读的正确、不混乱,就要在读的时候让想要变化的进程先等待,等读完了数据放到了文件中以后,再唤醒要更新的进程。

注:我的答案很可能不准确,请别被我误导了。

HIT-OS-LAB参考资料:

1.《操作系统原理、实现与实践》-李治军、刘宏伟 编著

2.《Linux内核完全注释》

3.两个哈工大同学的实验源码

4.Linux-0.11源代码

(上述资料,如果有需要的话,请主动联系我))

标签:文件,blocks,int,proc,char,哈工大,lab8,buf

来源: https://blog.csdn.net/qq_41708792/article/details/93719759

linux实验报告哈工大,哈工大操作系统实验---lab8:proc文件的实现相关推荐

  1. 西工大计算机操作系统实验报告,西工大操作系统实验报告os4.doc

    西工大操作系统实验报告os4 篇一:西北工业大学-操作系统实验报告-实验四 实验四 进程与线程 一. 实验目的 (1)理解进程的独立空间: (2)理解线程的相关概念. 二. 实验内容与要求 1.查阅资 ...

  2. 可变分区存储管理实验报告总结_操作系统实验报告-可变分区存储管理方式的内存分配回收...

    一.实验目的 ( 1 )深入了解可变分区存储管理方式的内存分配回收的实现. 二.实验内容 编写程序完成可变分区存储管理方式的内存分配回收,要求有内存空间分配表, 并采用最优适应算法完成内存的分配与回收 ...

  3. 山东大学linux实验四CSDN,山东大学操作系统实验报告材料4进程同步实验

    <山东大学操作系统实验报告材料4进程同步实验>由会员分享,可在线阅读,更多相关<山东大学操作系统实验报告材料4进程同步实验(15页珍藏版)>请在人人文库网上搜索. 1.实用标准 ...

  4. 苏州大学linux课程实验报告,苏州大学实验报告-定时溢出中断实验报告

    苏州大学实验报告-定时溢出中断实验报告 本文关键词:实验,报告,溢出,中断,定时 苏州大学实验报告-定时溢出中断实验报告 本文简介:苏州大学实验报告院.系年级专业姓名学号课程名称成绩指导教师同组实验者 ...

  5. 计算机应用基础实验报告册,计算机应用基础实验报告(flash)

    实 验 报 告 计算机应用基础实验报告 姓名 班级 学号 实验日期 课程名称 计算机应用基础 指导教师 成绩 实验名称:简单动画制作 实验目的: 掌握逐帧动画.形状渐变动画.运动渐变动画的制作方法 实 ...

  6. 安徽工程大学C语言程序设计实验报告,安徽工业大学嵌入式实验报告.docx

    安徽工业大学嵌入式实验报告 <嵌入式系统实验报告>指导教师:陆勤姓名:程少锋学号:139074366班级:物联网131班实验一B 熟悉实验开发环境一.实验目的熟悉ADS1.2 开发环境,学 ...

  7. 计算器软件C语言课程设计实验报告,c简单计算器实验报告_相关文章专题_写写帮文库...

    时间:2019-05-15 12:55:15 作者:admin 计算器实验报告 班级: 07计本(1)班 姓名: 王林 学号: 20706031047 指导老师: 韩静 一. 需求分析 (1)制作一个 ...

  8. 第四次c语言实验报告模板,C语言实验报告模板.doc

    C语言实验报告模板.doc 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下载的文档,不会出现我们的网址水印. 3.该文档所得 ...

  9. c语言选择循环实验报告,C语言程序设计实验报告选择与循环结构程序设计.doc

    C语言程序设计实验报告选择与循环结构程序设计.doc 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下载的文档,不会出现我们的 ...

  10. 实验报告格计算机,计算机实验报告格式大全

    课程:大学计算机基础 班级 : ***** 学号:** 姓名:*** 组别: 同组者姓名: 仪器编号: 实验日期: 实验 windows 2000 操作 [实验目的] 1. 掌握windows 200 ...

最新文章

  1. 姚班三兄弟3万块创业八年,旷视终冲刺港股
  2. IPsec 隧道模式和传输模式下的AH和ESP包封装格式
  3. java arraylist comparable_Java 两种ArrayList集合自定义对象属性排序,Comparator接口 或 Comparable接口...
  4. nmap之扫描端口(附加hping3隐藏扫描)
  5. 平均分辨准确率对网络隐藏层节点数的非线性变化关系03
  6. hibernate一对一外键单向关联
  7. PDF文件加密有什么方法?如何给PDF文件加密
  8. 让Python中类的属性具有惰性求值的能力
  9. 网博士自助建站系统_自助建站:自助建站到底好还是不好?
  10. python对象_Python对象()
  11. sqlserver 触发器语法
  12. 《西窗法雨》一天读完,怕不怕
  13. Latex 只在首页添加页眉页脚 修改局部字体大小
  14. 4816 江哥的dp题b
  15. shell中大于号和小于号
  16. Elite Graphix Elite Cms SQL注入漏洞(CVE-2022-24263)
  17. Codeforces1153D-Serval and Rooted Tree(树形dp)
  18. 历史经验之js个200经验收藏
  19. 端午节,我用Python画了一盘粽子
  20. java hypot_Java Math类静态double hypot(double d1,double d2)与示例

热门文章

  1. 第1关:分支结构:是闰年吗
  2. 嘻哈c语言,功夫胖在嘻哈圈的地位如何?说唱组合C-BLOCK了解一下
  3. 【老王的脑科学谬论】从“遗忘”这件事聊一聊大分子编码说和老王谬论
  4. Java 七大设计原则 - 依赖倒置原则/面向接口编程
  5. 通达信l2接口Type-C功能
  6. Linux字符驱动开发
  7. Excel如何快速将一个工作表复制到多个工作簿中
  8. angularjs 验证身份证格式 和 一般JS验证身份证格式
  9. 权限管理框架Shiro简介
  10. 看到了Pixel 3的刘海,互联网都笑了。。