【推荐阅读】
【操作系统实验】内存管理
一、 实验目的
1、 熟悉Linux文件系统的文件和目录结构,掌握Linux文件系统的基本特征;
2、 模拟实现Linux文件系统的简单I/O流操作:备份文件。
二、 实验内容
1、 浏览Linux系统根目录下的子目录,熟悉每个目录的文件和功能;
2、 设计程序模拟实现Linux文件系统的简单I/O流操作:备份文件。
环境: ubuntu操作系统 Ubuntu下载
三、 实验原理
1、 Linux各种发行版的目录结构基本一致,各个目录简单介绍如下:
目录 描述
/ 根目录
/bin 做为基础系统所需要的最基础的命令就是放在这里。比如 ls、cp、mkdir等命令;功能和/usr/bin类似,这个目录中的文件都是可执行的,普通用户都可以使用的命令。
/boot Linux的内核及引导系统程序所需要的文件,比如 vmlinuz initrd.img 文件都位于这个目录中。在一般情况下,GRUB或LILO系统引导管理器也位于这个目录;启动装载文件存放位置,如kernels,initrd,grub。一般是一个独立的分区。
/dev 一些必要的设备,声卡、磁盘等。还有如 /dev/null. /dev/console /dev/zero /dev/full 等。
/etc 系统的配置文件存放地. 一些服务器的配置文件也在这里;比如用户帐号及密码配置文件;
/etc/opt:/opt对应的配置文件
/etc/X11:Xwindows系统配置文件
/etc/xml:XML配置文件
……
/home 用户工作目录,和个人配置文件,如个人环境变量等,所有的账号分配一个工作目录。一般是一个独立的分区。
/lib 库文件存放地。bin和sbin需要的库文件。类似windows的DLL。
/media 可拆卸的媒介挂载点,如CD-ROMs、移动硬盘、U盘,系统默认会挂载到这里来。
/mnt 临时挂载文件系统。这个目录一般是用于存放挂载储存设备的挂载目录的,比如有cdrom 等目录。可以参看/etc/fstab的定义。
/opt 可选的应用程序包。
/proc 操作系统运行时,进程(正在运行中的程序)信息及内核信息(比如cpu、硬盘分区、内存信息等)存放在这里。/proc目录伪装的文件系统proc的挂载目录,proc并不是真正的文件系统,它的定义可以参见 /etc/fstab 。
/root Root用户的工作目录
/sbin 和bin类似,是一些可执行文件,不过不是所有用户都需要的,一般是系统管理所需要使用得到的。
/tmp 系统的临时文件,一般系统重启不会被保存。
/usr 包含了系统用户工具和程序。
/usr/bin:非必须的普通用户可执行命令
/usr/include:标准头文件
/usr/lib:/usr/bin/ 和 /usr/sbin/的库文件
/usr/sbin:非必须的可执行文件
/usr/src:内核源码
/usr/X11R6:X Window System, Version 11, Release 6.
/srv 该目录存放一些服务启动之后需要提取的数据
2、 Linux的文件结构是单个的树状结构.可以用tree进行展示。文件操作命令见附录1,
3、 Linux文件系统:Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等。通过使用同一套文件 I/O 系统 调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体文件系统格式;更进一步,对文件的 操作可以跨文件系统而执行。“一切皆是文件”是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、 套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。
4、 虚拟文件系统(Virtual File System, 简称 VFS), 是 Linux 内核中的一个软件层,用于给用户空间的程序提供文件系统接口;同时,它也提供了内核中的一个 抽象功能,允许不同的文件系统共存。系统中所有的文件系统不但依赖 VFS 共存,而且也依靠 VFS 协同工作。为了能够支持各种实际文件系统,VFS 定义了所有文件系统都支持的基本的、概念上的接口和数据 结构;同时实际文件系统也提供 VFS 所期望的抽象接口和数据结构,将自身的诸如文件、目录等概念在形式 上与VFS的定义保持一致。换句话说,一个实际的文件系统想要被 Linux 支持,就必须提供一个符合VFS标准 的接口,才能与 VFS 协同工作。实际文件系统在统一的接口和数据结构下隐藏了具体的实现细节,所以在VFS 层和内核的其他部分看来,所有文件系统都是相同的。
5、利用C库函数fopen(), fread(), fwrite(), fclose() 来实现简单的文件备份, 即将一个文件的内容拷贝到另一个文件中去。
四、 实验中用到的系统调用函数
1、Ssize_t read (int fd, void buf, size_t count);
会把参数fd所指的文件传送count个字节到buf指针所指的内存中。
若参数count为0,则read()不会有作用并返回0,返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。
2、Ssize_t write (int fd, const void buf, size_t count);
会把参数buf所指的内存写入count个字节到参数fd所指的文件内。当然,文件读写位置也会随之移动。
3、int open (const char pathname, int flags);
参数pathname指向欲打开的文件路径字符串。
4、int close (int fd);
当使用完文件后若已不再需要则可使用close ()关闭该文件,而close ()会让数据写回磁盘,并释放该文件所占用的资源。
参数fd为先前由open ()或creat ()所返回的文件描述词。
5、size_t fwrite(const voidptr,size_t size,size tnmemb,FILEstream);fwrite()用来将数据写入文件流中。
参数stream为已打开的文件指针,参数pr指向欲写入的数据地址,总共写入的字符数以参数sizenmemb来决定。
fwrite()会返回实际写入的nmemb数目。
6、int fclose(FILEstream);fclose()用来关闭先前fopen()打开的文件。此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源。
7、FILEfopen(const char"path,const charmode);参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。mode有下列几种形态字符串.
8、Size_t fread(voidptr,size_t size,size_t nmemb,FILEstream);fread()用来从文件流读取数据。参数stream为已打开的文件指针,参数pr指向欲存放读取进来的数据空间,读取的字符数以参数sizenmemb来决定。
fread()会返回实际读取到的nmemb数目,如果此值比参数nmemb来得小,则代表可能读到了文件尾或有错误发生,这时必须用feof()或ferror()来决定发生什么情况。
五、实验要求
1、 对文件系统命令和库函数要提前熟悉;
2、 画出备份文件的过程图;
代码
//fopen(), fread(), fwrite(), fclose()
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void main()
{
FILE *fr = NULL,*fw = NULL;
fr = fopen("test.txt", "r"); //读取文件
if (!fr)
printf("test.txt open is fail!\n");
fw = fopen("test_copy.txt", "w");//写入文件
if (!fw)
printf("test_copy.txt open is fail!\n");
char* stream = (char*)malloc(sizeof(char)* 1024); //存贮区
bool flag=true;
while (flag) //进行读写操作
{
int size = fread(stream, sizeof(char), 1024, fr);//size:缓存区的实际大小
if (size <= 0)
{
flag = false;
continue; //copy end
}
fwrite(stream, sizeof(char), size, fw);
}
fclose(fr); //关闭文件
fclose(fw);
}
//open(),read(),write(),close()
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>
int main()
{
int r, w, size;
r = open("test.txt", O_RDONLY); //读取的文件
if (!r)
printf("test.txt open is fail!\n");
w = open("test_copy.txt", O_CREAT | O_WRONLY); //写入的文件
if (!w)
printf("test_copy.txt open is fail!\n");
char stream[1024];
bool flag = true;
while (flag) //进行读写操作
{
size = read(r, stream, 1024);
if (size <= 0)
{
flag = false;
continue; //copy end
}
write(w, stream, size);
}
close(r); //关闭文件
close(w);
return 0;
}
结果展示
【回见】