“操作系统实验”实验报告

proc文件系统的实现

实验名称:proc文件系统的实现

实验日期:2021.7.9

班级:软嵌192

姓名:贾梦娇

学号:1930110798

一、实验目的

  • 掌握虚拟文件系统的实现原理;
  • 实践文件、目录、文件系统等概念。

二、实验环境

本操作系统实验的硬件环境是IA-32(x86)架构的PC机(在实验楼的环境中就是右边的窗口)。

主要软件环境是Bochs + gcc +编辑器/ IDE +操作系统+ Linux 0.11源代码。

三、实验内容

在 Linux 0.11 上实现 procfs(proc 文件系统)内的 psinfo 结点。当读取此结点的内容时,可得到系统当前所有进程的状态信息。

四、实验过程及数据记录

1、 procfs 简介

环境准备:

cd ~/oslab
tar -zxvf hit-oslab-linux-20110823.tar.gz -C /home/shiyanlou
copy

图片描述

cat /proc/meminfo
copy

图片描述

2、 基本思路

Linux 是通过文件系统接口实现 procfs,并在启动时自动将其 mount 到 /proc 目录上。

此目录下的所有内容都是随着系统的运行自动建立、删除和更新的,而且它们完全存在于内存中,不占用任何外存空间。

3、 增加新文件类型

在 include/sys/stat.h 文件中定义了几种文件类型和相应的测试宏: 图片描述

4、 让 mknod() 支持新的文件类型

让mknod()支持新的文件类型,修改/fs/namei.c文件中的sys_mknod()函数的代码,在其中增加关于proc文件系统的判断: 图片描述

进程proc文件初始化,修改linux-0.11/init/main.c,建立/proc目录:

_syscall2(int,mkdir,const char*,name,mode_t,mode)
_syscall3(int,mknod,const char*,filename,mode_t,mode,dev_t,dev)
copy

图片描述

建立/proc目录下的各个结点: 图片描述

编译、运行 0.11 内核后,用 ll /proc 可以看到: 图片描述

5、 让 proc 文件可读

在/fs/read_write.c中添加声明extern: 图片描述

在sys_read()添加proc文件: 图片描述

6、 proc 文件的处理函数

包含 linux/kernel.h 头文件后,就可以使用 malloc() 和 free() 函数。它们是可以被核心态代码调用的,唯一的限制是一次申请的内存大小不能超过一个页面。

7、 实现 sprintf() 函数

Linux 0.11 没有 sprintf(),可以参考 printf() 自己实现一个。

#include <stdarg.h>
//……
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;
}
copy

8、 cat 命令的实现

cat 是 Linux 下的一个常用命令,功能是将文件的内容打印到标准输出。

#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
    char buf[513] = {'\0'};
    int nread;

    int fd = open(argv[1], O_RDONLY, 0);
    while(nread = read(fd, buf, 512))
    {
        buf[nread] = '\0';
        puts(buf);
    }

    return 0;
}
copy

9、 psinfo 的内容

进程的信息就来源于内核全局结构数组 struct task_struct * task[NR_TASKS] 中,具体读取细节可参照 sched.c 中的函数 schedule()。

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

if (*p)
   (*p)->counter = ((*p)->counter >> 1)+...;
copy

10、 hdinfo 的内容

硬盘总共有多少块,多少块空闲,有多少 inode 等信息都放在 super 块中,super 块可以通过 get_super() 函数获得。

struct super_block * sb;
sb = get_super(inode->i_dev);

struct buffer_head * bh;
total_blocks = sb->s_nzones;

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

    bh = sb->s_zmap[i];
    p=(char *)bh->b_data;
}
copy

五、实验结果分析

一次 read() 未必能读出所有的数据,需要继续 read(),直到把数据读空为止。而数次 read() 之间,进程的状态可能会发生变化。

六、实验心得

根据提示一步步的修改文件,最终才能成功运行,run成功额时候有成就感,下次我会做的更好。

最新评论
暂无评论~