操作系统原理课内实验报告学生姓名司默涵专业/班级计算机11班学号2110505018所在学院电信学院指导教师何晖张航提交日期2013年12月25日操作系统原理课内实验1.实验目的1.1用户接口实验(1)理解面向操作命令的接口Shell;(2)学会简单的shell编码;(3)理解操作系统调用的运行机制;(4)掌握创建系统调用的方法。操作系统给用户提供了命令接口和程序接口(系统调用)两种操作方式。用户接口实验也因此而分为两大部分。首先要熟悉Linux的基本操作命令,并在此基础上学会简单的shell编程方法。然后通过想Linux内核添加一个自己设计的系统调用,来理解系统调用的实现方法和运行机制。在本次实验中,最具有吸引力的地方是:通过内核编译,将一组源代码变成操作系统的内核,并由此重新引导系统,这对我们初步了解操作系统的生成过程极为有利。1.2文件系统实验(1)掌握文件系统的工作机理;(2)理解文件系统的主要数据结构;(3)学习较为复杂的LINUX下的编程。这是相对来说有一定难度的实验,它含盖了一个简单的二级文件系统的设计以及相关的接口命令编写的内容,也鉴于此把它放在了最后一个实验。“一分耕耘,一分收获”,在完整的完成本实验,你将获得的收益是:对文件系统工作的机理,特别是linux的ext2文件系统工作机理了如指掌;linux下较强的编程能力。(注)文件系统实验由吴治诚(2110505021)和司默涵(2110505018)分工合作完成。具体分工如下:吴治诚同学主要负责程序主体算法(例如用户目录等)和有关文件功能的实现;司默涵同学主要负责子文件系统有关功能、位示图的实现和错误调试。2.实验方法详述2.1用户接口实验通过将自行创建的系统调用添加到linux内核中实现。2.2文件系统实验实际上是利用了高级语言对jinux的文件系统进行了模拟。真正的文件系统对外存进行管理,涉及到许多硬件、设备管理方面的底层技术,一方面这些技术不属于操作系统核心内容,一方面过多的内容不免造成实验者顾此失彼,所以这里推荐一种使用内存来模拟外存的方式,可以跳过这些硬件技术而直接把精力放在数据结构设计和操作算法设计上面。3.详细实验过程3.1用户接口实验对于linux-3.0.2版本的系统添加方法:提示:建议使用Gcc-4.6版本(如果使用Ubuntu,建议使用Ubuntu12.04)1.修改arch/x86/include/asm/unistd_32.h,添加以下内容:#define__NR_mycallSYS_ID并修改文件中的NR_syscalls,将其值增加12.修改arxh/x86/include/asm/syscalls.h添加以下内容:asmlinkagevoidsys_mycall();3.修改arch/x86/kernel/syscall_table_32.S,添加以下内容:.longsys_mycall编译内核(请尽量避免使用makeclean)1.配置内核(建议使用默认配置,仅仅修改localversions即,可当然也可以把一些无用的模块去掉)makemenuconfig2.编译内核(-jN中的N表示使用多少个线程编译,一般为处理器数目+1)make-j5bzImage3.编译内核模块make-j5modules4.安装内核模块(需要root权限)提示:模块被安装在/lib/modules/versions/下(比如2.6.31内核在config时设定其的localversions为-myservice,那么versions为2.6.31-myservice)sudomakemodules_install5.安装内核提示:在较新的Linux发行版中会自动生成init内存文件系统,并将配置文件、内核及init内存文件系统拷贝到/boot目录下,最后更新引导。sudomakeinstall6.(可选步骤)提示:在较旧的发行版中,可能需要手动生成init内存文件系统及更改引导。生成init内存文件系统:mkinitramfs-k-oinitrd.img-versionsversions更改引导(grub文件):参考原有的启动项,添加新内核的启动项即可。使用系统调用#includestdio.hintmain(intargc,char*argv[]){syscall(SYS_ID);return0;}运行程序后使用以下命令查看内核日志(printk的输出信息在内核日志中):dmesg3.2文件系统实验3.2.1外存管理其实很早人们设计操作系统的时候就意识到一个问题:所有的程序和数据不可能都放在内存当中。所以为了腾出宝贵的内存空间,也为了方便用户管理外存上的文件,文件系统应运而生。文件系统是一个含有大量的文件及其属性,对文件进行操作、管理的软件,以及向用户提供使用文件的接口的一个集合。在逻辑上它的层次结构是这样的:文件系统接口对对象的操作和管理的软件集合逻辑文件系统基本I/O管理程序(文件组织模块)基本文件系统(物理I/O层)I/O控制层(设备驱动程序)对象及其属性说明作为产品的操作系统目前种类已经很多了,一般来说它们有各自的文件系统。比如MS的WINDOWS系列使用的是FAT16、FAT32或NTFS的文件系统、LINUX使用的是EXT2、EXT3文件系统等等。linux的EXT2文件系统文件系统是操作系统中负责管理和存取文件信息的软件机构,负责文件的建立、撤消、存入、读写、修改和复制,还负责完成对文件的按名存取和进行存取控制,以及向用户提供使用文件系统的接口。LINUX使用了虚拟文件系统(VFS)的技术,从而可以支持多达几十种不同类型的文件系统,其中EXT2是LINUX自己的文件系统。无论是VFS,还是EXT2都是采用UNIX的文件系统模型来构造的。EXT2有几个重要的数据结构,一个是超级块,用来描述目录和文件在磁盘上的物理位置、文件大小和结构等信息。inode也是一个重要的数据结构。文件系统中的每个目录和文件均由一个inode描述。它包含:文件模式(类型和存取权限)、数据块位置等信息。如果希望详细学习EXT2文件系统可以参看linux内核代码include/linux/ext2_fs.h、include/linux/ext2_fs_sb.h等文件。一个文件系统除了重要的数据结构之外,还必须为用户提供有效的接口操作。比如EXT2提供的OPEN/CLOSE接口操作。图9Linux的EXT2文件系统可能用到的编程技术(1)fopen,打开文件格式:FILE*fopen(constchar*filename,constchar*mode)需要头文件stdio.hfilename:待打开的文件名,如果不存在就创建改文件。mode:打开方式,常用的有“w”写方式打开,文件不存在就被创建,否则清除原来内容;“r”读方式打开,文件必须存在;“a”添加方式打开;“w+”读写方式打开,有清楚功能;“r+”读写方式打开,文件必须存在;“a+”“t”TEXT方式打开;“b”二进制方式打开fwrite和fread,读写文件size_tfwite(constvoid*buffer,size_tsize,size_tcount,FILE*stream);size_tfread(void*buffer,size_tsize,size_tcount,FILE*stream);buffer:待读写的内容;size:一次读写的量;count:需读写buffer的次数;stream:打开的文件指针fseek,定位文件intfseek(FILE*stream,longoffset,intorigin);stream:文件指针;offset:偏移量;origin:初始位置,有三个常量,SEEK_CUR是当前位置,SEEK_SET文件开头,SEEK_END文件尾。3.2.2用内存来模拟外存真正的文件系统对外存进行管理,涉及到许多硬件、设备管理方面的底层技术,一方面这些技术不属于操作系统核心内容,一方面过多的内容不免造成实验者顾此失彼,所以这里推荐一种使用内存来模拟外存的方式,可以跳过这些硬件技术而直接把精力放在数据结构设计和操作算法设计上面。假定pInode是一个指向inode结构的指针,而且它已经放入的需要放入的数值了,现在需要将其写入到特定位置。可用如下代码:……fd=fopen(“filesystem”,”w+b”);//fd是FILE指针类型,w便是写方式,b表示二进制fseek(fd,specific_area,SEEK_SET);//fd是文件指针;specific_area为整形,//为需要入pInode的位置fwrite(pInode,1,sizeof(inode),fd);//写入pInode信息……3.2.3实验指导3.2.3.1文件系统的数据结构a)i节点structinode{structinode*i_forw;structinode*i_back;charI_flag;unsignedinti_into;/*磁盘i节点标号*/unsignedinti_count;/*引用计数*/unsignedshortdi_number;/*关联文件书,当为0时,则删除该文件*/unsignedshortdi_mode;/*存取权限*/unsignedshortdi_uid;/*磁盘i节点用户*/unsignedshortdi_gid;/*磁盘i节点组*/Unsignedintdi_addr[NADDR];/*物理块号*/}b)磁盘i结点structdinode{unsignedshortdi_number;/*关联文件数*/unsignedshortdi_mode;/*存取权限*/unsignedshortdi_uid;unsignedshortdi_gid;unsignedlongdi_size;/*文件大小*/unsignedintdi_addr[NADDR];/*物理块号*/}c)目录项结构structdirect{chard_name[DIRSIZ];/*目录名*/unsignedintd_ino;/*目录号*/}d)超级块structfilsys{unsignedshorts_isize;/*i节点块块数*/unsignedlongs_fsize;/*数据块块数*/unsignedints_nfree;/*空闲块块数*/unsignedshorts_pfree;/*空闲块指针*/unsignedints_free[NICFREE];/*空闲块堆栈*/unsignedints_ninode;/*空闲i节点数*/unsignedshorts_pinode;/*空闲i节点指针*/unsignedints_inode[NICINOD];/*空闲i节点数组*/unsignedints_rinode;/*铭记i节点*/chars_fmod;/*超级块修改标志*/};e)用户密码structpwd{unsignedshortP_uid;unsignedshortP_gid;charpassward[PWOSIZ];}f)目录structdir{strutdirectdirect[DIRNUM];intsize;}g)查找i内存节点的hash表structhinode{strutinode*iforw;}h)系统打开表structfile{charf_flag;/*文件操作标志*/unsignedintf_count;/*引用计数*/structinode*f_inode;/*指向内存节点*/unsignedlongf_off;/*读/写指针*/}i)用户打开表structuser{unsignedshortu_default_mode;unsignedshortu_uid;/*用户标志*/unsignedshortu_gid;/*用户组标志*/unsignedshortu_ofile[NOFILE];/*用户打开表*/}3.2.3.2主要函数(1)i节点