西安交通大学操作系统实验报告.docx
《西安交通大学操作系统实验报告.docx》由会员分享,可在线阅读,更多相关《西安交通大学操作系统实验报告.docx(36页珍藏版)》请在冰豆网上搜索。
![西安交通大学操作系统实验报告.docx](https://file1.bdocx.com/fileroot1/2022-12/1/83b59d60-3d5e-4816-a9dd-b8c5d6a89cbc/83b59d60-3d5e-4816-a9dd-b8c5d6a89cbc1.gif)
西安交通大学操作系统实验报告
操作系统实验报告
实验一:
用户接口实验
一.实验目的
1.理解面向操作命令的接口Shell。
2.学会简单的shell编码。
3.理解操作系统调用的运行机制。
4.掌握创建系统调用的方法。
操作系统给用户提供了命令接口和程序接口(系统调用)两种操作方式。
用户接口实验也因此而分为两大部分。
首先要熟悉Linux的基本操作命令,并在此基础上学会简单的shell编程方法。
然后通过想Linux内核添加一个自己设计的系统调用,来理解系统调用的实现方法和运行机制。
在本次实验中,最具有吸引力的地方是:
通过内核编译,将一组源代码变成操作系统的内核,并由此重新引导系统,这对我们初步了解操作系统的生成过程极为有利。
二.实验内容
1)控制台命令接口实验
该实验是通过“几种操作系统的控制台命令”、“终端处理程序”、“命令解释程序”和“Linux操作系统的bash”来让实验者理解面向操作命令的接口shell和进行简单的shell编程。
Ø查看bash版本。
Ø编写bash脚本,统计/my目录下c语言文件的个数
2)系统调用实验
该实验是通过实验者对“Linux操作系统的系统调用机制”的进一步了解来理解操作系统调用的运行机制;同时通过“自己创建一个系统调用mycall()”和“编程调用自己创建的系统调用”进一步掌握创建和调用系统调用的方法。
Ø编程调用一个系统调用fork(),观察结果。
Ø编程调用创建的系统调用foo(),观察结果。
Ø自己创建一个系统调用mycall(),实现功能:
显示字符串到屏幕上。
Ø编程调用自己创建的系统调用。
三.实验步骤
系统调用实验:
1.首先将Linux-3.0.tar.bz2拷贝到/usr/src目录下
——命令:
cplinux-3.0.tar.bz2/usr/src/
2.打开终端,获得root权限
——命令:
sudo–s
3.进入/usr/src目录
——命令:
cd/usr/src
4.解压linux源码
——命令:
tarxvzflinux-3.0.tar.bz2
5.进入目录linux-3.0.5
——命令:
cdlinux-3.0
6.添加系统调用
——操作:
geditkernel/myservice.c在文本编辑器中添加
#include
#include
asmlinkagevoidsys_mycall()
{
printk(KERN_INFO"Hello,world!
\n");
return;
}
7.修改kernel/Makefile添加生成myservice.c添加到Makefile的编译规则中:
obj-y+=myservice.o
8..修改arch/x86/include/asm/unistd_32.h,添加以下内容:
#define__NR_mycallSYS_ID
//SYS_ID表示新添加系统调用的调用号
并修改文件中的NR_syscalls,将其值增加1
9.修改arxh/x86/include/asm/syscalls.h添加以下内容:
asmlinkagevoidsys_mycall();
10.修改arch/x86/kernel/syscall_table_32.S,添加以下内容:
.longsys_mycall
11.配置内核(仅仅修改localversions即可)——命令:
makemenuconfig
12.编译内核——命令:
make–j4bzImage(开4个线程编译)
13.编译内核模块——命令:
make–j4modules
14.安装内核模块——命令:
makemodules_install
15.安装内核——命令:
makeinstall
16.重启系统,在系统选择页面选择进入自己编译的linux-3.0内核
17.在桌面建立测试的C程序test.c程序内容如下:
#include
intmain(intargc,char*argv[])
{
syscall(SYS_ID);//SYS_ID表示新添加系统调用的调用号
return0;
}
18.编译程序——gcctest.c–oa.out
19.运行程序——./a.out
20.查看内核日志(printk的输出信息在内核日志中):
dmesg
四.实验结果
1.成功完成内核编译的任务,结果显示图如下:
2.下图为添加系统调用结果
五.实验小结
这次实验的内核编译需要进行一系列比较花时间的操作过程,但同时也锻炼了实际动手能力,在实践中对于操作系统这门课有了进一步的了解。
同时,在本次实验中,学习了linux系统的使用方法,掌握了很多的基本命令,也明白了添加系统调用的方法,为以后的学习提供了很大的帮助。
实验四:
一个简单文件系统的实现
一.实验目的
1.熟悉Ext文件系统的原理
2.根据Ext文件系统的数据结构和构建方法,自行实现一个简单的内存文件系统
二.实验内容
1.设计并实现一个一级(单用户)文件系统程序
a.提供以下操作:
a)文件创建/删除接口命令create/delete
b)目录创建/删除接口命令mkdir/rmdir
c)显示目录内容命令ls
b.创建的文件不要求格式和内容
2.设计并实现一个二级文件系统程序
a.提供用户登录;
b.文件、目录要有权限
三.实验原理
Ext文件系统结构:
1.引导块BootBlock
每个硬盘分区的开头1024字节,即0byte至1023byte是分区的启动扇区。
存放由ROMBIOS自动读入的引导程序和数据,但这只对引导设备有效,而对于非引导设备,该引导块不含代码。
这个块与ext2没有任何关系。
2.超级块SuperBlock
每个分区均有一个superblock块,定义了文件系统的全局信息,包括块的大小,总块数,空闲块,索引结点数,各种位图和i节点表的地址和大小等信息。
3.数据块位图
这是ext2管理存储空间的方法。
即位图法。
每个位对应一个数据块,位值为0表示空闲,1表示已经分配。
数据块位图定义为一个块大小。
于是,一个组中的数据块个数就决定了。
假设块大小为b字节。
可以区别的块数为b*8个
4.数据块DataBlocks
每个组的数据最大个数是在块大小定义后就确定了的。
所以组容量也就确定了。
假设块大小为b字节。
那么组容量就确定为(b*8)*b 字节
若1块=4K,则组块大小=4K*8*4K=128M
5.inode位图
与数据块位图相似,用来表示索引结点是否已经被使用。
假设块大小为b字节,每个索引结点数据结构大小为128字节。
最多可以有b*8个索引结点,索引结点表需要占用的存储空间大小为(b*8)*128字节。
即(b*8)*128/b=8*128个块
6.inode表
索引结点表由若干个索引结点数据结构组成,需要占用若干个块。
Ext2中的每个索引结点数据结构大小为128字节。
每个索引结点即对应一个文件或是目录。
是对其除文件名(目录名)以外的所有属性的描述。
例如:
文件类型,文件创建时间,访问时间,修改时间,文件所占数据块的个数,指向数据块的指针。
其中,数据块指针是由15个元组的数据组成
四.实验步骤运行结果
1.根据要求编写源程序,实验源代码见附录1。
2.运行程序,运行结果如图:
1.根据提示输入help,结果如图:
2.输入ls列出根目录下的项目,然后创建文件目录c再输入ls观察是否创建成功:
5.进入文件目录c并在c中创建文件a
6.打开a,并读取a
7.关闭a
7.删除a
9.删除文件目录c
五.实验小结
本次实验要求建立一个文件系统,由于在专业课上的基本知识学习比较薄弱,所以参考了网上的一些代码,进行了一些修改后最后获得结果。
最后,也算完成了一个简单的文件系统,具备了题目中的要求。
但在以后的学习中,还要对这一方面的知识进行一些补充。
附录1:
实验源码:
#include
#include
#include
#include
#defineDATA_BLOCK263680//数据块起始地址
#defineBLOCK_SIZE512//块大小
#defineDISK_START0//磁盘开始地址
#defineBLOCK_BITMAP512//块位图起始地址
#defineINODE_BITMAP1024//inode位图起始地址
#defineINODE_TABLE1536//索引节点表起始地址
#defineINODE_SIZE64//structinode的大小
structgroup_desc{
charbg_volume_name[16];//卷名
unsignedshortbg_block_bitmap;//保存块位图的块号
unsignedshortbg_inode_bitmap;//保存索引结点位图的块号
unsignedshortbg_inode_table;//索引结点表的起始块号
unsignedshortbg_free_blocks_count;//本组空闲块的个数
unsignedshortbg_free_inodes_count;//本组空闲索引结点的个数
unsignedshortbg_used_dirs_count;//本组目录的个数
charbg_pad[4];//填充(0xff)
};
structinode{
unsignedshorti_mode;//文件类型及访问权限
unsignedshorti_blocks;//文件的数据块个数
unsignedlongi_size;//大小(字节)
unsignedlongi_atime;//访问时间
unsignedlongi_ctime;//创建时间
unsignedlongi_mtime;//修改时间
unsignedlongi_dtime;//删除时间
unsignedshorti_block[8];//指向数据块的指针
chari_pad[24];//填充(0xff)
};
structdir_entry{//目录项结构
unsignedshortinode;//索引节点号
unsignedshortrec_len;//目录项长度
unsignedshortname_len;//文件名长度
charfile_type;//文件类型(1:
普通文件,2:
目录..)
charname[9];//文件名
};
charBuffer[512];//针对数据块的缓冲区
chartempbuf[4097];//
unsignedcharbitbuf[512];//位图缓冲区
unsignedshortindex_buf[256];
shortfopen_table[16];//文件打开表
unsignedshortlast_alloc_inode;//最近分配的节点号
unsignedshortlast_alloc_block;//最近分配的数据块号
unsignedshortcurrent_dir;//当前目录的节点号
structgroup_descsuper_block[1];//组描述符缓冲区
structinodeinode_area[1];//节点缓冲区
structdir_entrydir[32];//目录项缓冲区
charcurrent_path[256];//当前路径名
unsignedshortcurrent_dirlen;
FILE*fp;
voidupdate_group_desc()
{
fseek(fp,DISK_START,SEEK_SET);
fwrite(super_block,BLOCK_SIZE,1,fp);
}
voidreload_group_desc()//载入组描述符
{
fseek(fp,DISK_START,SEEK_SET);
fread(super_block,BLOCK_SIZE,1,fp);
}
voidupdate_inode_bitmap()//更新inode位图
{
fseek(fp,INODE_BITMAP,SEEK_SET);
fwrite(bitbuf,BLOCK_SIZE,1,fp);
}
voidreload_inode_bitmap()//载入inode位图
{
fseek(fp,INODE_BITMAP,SEEK_SET);
fread(bitbuf,BLOCK_SIZE,1,fp);
}
voidupdate_block_bitmap()//更新block位图
{
fseek(fp,BLOCK_BITMAP,SEEK_SET);
fwrite(bitbuf,BLOCK_SIZE,1,fp);
}
voidreload_block_bitmap()//载入block位图
{
fseek(fp,BLOCK_BITMAP,SEEK_SET);
fread(bitbuf,BLOCK_SIZE,1,fp);
}
voidupdate_inode_entry(unsignedshorti)//更新第i个inode入口
{
fseek(fp,INODE_TABLE+(i-1)*INODE_SIZE,SEEK_SET);
fwrite(inode_area,INODE_SIZE,1,fp);
}
voidreload_inode_entry(unsignedshorti)//载入第i个inode入口
{
fseek(fp,INODE_TABLE+(i-1)*INODE_SIZE,SEEK_SET);
fread(inode_area,INODE_SIZE,1,fp);
}
voidreload_dir(unsignedshorti)//更新第i个目录
{
fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);
fread(dir,BLOCK_SIZE,1,fp);
}
voidupdate_dir(unsignedshorti)//载入第i个目录
{
fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);
fwrite(dir,BLOCK_SIZE,1,fp);
}
voidreload_block(unsignedshorti)//载入第i个数据块
{
fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);
fread(Buffer,BLOCK_SIZE,1,fp);
}
voidupdate_block(unsignedshorti)//更新第i个数据块
{
fseek(fp,DATA_BLOCK+i*BLOCK_SIZE,SEEK_SET);
fwrite(Buffer,BLOCK_SIZE,1,fp);
}
intalloc_block()//分配一个数据块,返回数据块号;
{
unsignedshortcur=last_alloc_block;
unsignedcharcon=128;
intflag=0;
if(super_block[0].bg_free_blocks_count==0)
{
printf("Thereisnoblocktobealloced!
\n");
return(0);
}
reload_block_bitmap();
cur=cur/8;
while(bitbuf[cur]==255)
{
if(cur==511)cur=0;
elsecur++;
}
while(bitbuf[cur]&con)
{
con=con/2;
flag++;
}
bitbuf[cur]=bitbuf[cur]+con;
last_alloc_block=cur*8+flag;
update_block_bitmap();
super_block[0].bg_free_blocks_count--;
update_group_desc();
returnlast_alloc_block;
}
voidremove_block(unsignedshortdel_num)//删除一个block
{
unsignedshorttmp;
tmp=del_num/8;
reload_block_bitmap();
switch(del_num%8)//更改block位图
{
case0:
bitbuf[tmp]=bitbuf[tmp]&127;break;
case1:
bitbuf[tmp]=bitbuf[tmp]&191;break;
case2:
bitbuf[tmp]=bitbuf[tmp]&223;break;
case3:
bitbuf[tmp]=bitbuf[tmp]&239;break;
case4:
bitbuf[tmp]=bitbuf[tmp]&247;break;
case5:
bitbuf[tmp]=bitbuf[tmp]&251;break;
case6:
bitbuf[tmp]=bitbuf[tmp]&253;break;
case7:
bitbuf[tmp]=bitbuf[tmp]&254;break;
}
update_block_bitmap();
super_block[0].bg_free_blocks_count++;
update_group_desc();
}
//
intget_inode()//分配一个inode,返回序号
{
unsignedshortcur=last_alloc_inode;
unsignedcharcon=128;
intflag=0;
if(super_block[0].bg_free_inodes_count==0)
{
printf("ThereisnoInodetobealloced!
\n");
return0;
}
reload_inode_bitmap();
cur=(cur-1)/8;
while(bitbuf[cur]==255)
{
if(cur==511)cur=0;
elsecur++;
}
while(bitbuf[cur]&con)
{
con=con/2;
flag++;
}
bitbuf[cur]=bitbuf[cur]+con;
last_alloc_inode=cur*8+flag+1;
update_inode_bitmap();
super_block[0].bg_free_inodes_count--;
update_group_desc();
returnlast_alloc_inode;
}
//
voidremove_inode(unsignedshortdel_num)
{
unsignedshorttmp;
tmp=(del_num-1)/8;
reload_inode_bitmap();
switch((del_num-1)%8)//更改block位图
{
case0:
bitbuf[tmp]=bitbuf[tmp]&127;break;
case1:
bitbuf[tmp]=bitbuf[tmp]&191;break;
case2:
bitbuf[tmp]=bitbuf[tmp]&223;break;
case3:
bitbuf[tmp]=bitbuf[tmp]&239;break;
case4:
bitbuf[tmp]=bitbuf[tmp]&247;break;
case5:
bitbuf[tmp]=bitbuf[tmp]&251;break;
case6:
bitbuf[tmp]=bitbuf[tmp]&253;break;
case7:
bitbuf[tmp]=bitbuf[tmp]&254;break;
}
update_inode_bitmap();
super_block[0].bg_free_inodes_count++;
update_group_desc();
}
//dir
voiddir_prepare(unsignedshorttmp,unsignedshortlen,inttype)//新目录和文件初始化.and..
{
reload_inode_entry(tmp);//得到新目录的节点入口地址
if(type==2)//目录
{
inode_area[0].i_size=32;
inode_area[0].i_blocks=1;
inode_area[0].i_block[0]=alloc_block();
dir[0].inode=tmp;
dir[1].inode=current_dir;
dir[0].name_len=len;
dir[1].name_len=current_dirlen;
dir[0].file_type=dir[1].file_type=2;
for(type=2;type<32;type++)
dir[type].inode=0;
strcpy(dir[0].name,".");
strcpy(dir[1].name,"..");
update_dir(inode_area[0].i_block[0]);
inode_area[0].i_mode=01006;//drwxrwxrwx:
目录
}
else
{
inode_area[0].i_size=0;
inode_area[0].i_blocks=0;
inode_area[0].i_mode=0407;//drwxrwxrwx:
文件
}
update_inode_entry(tmp);
}
//
unsignedshortreserch_file(chartmp[9],intfile_type,unsignedshort*inode_num,unsignedshort*block_num,unsign