1、 熟悉Linux文件系统的文件和目录结构,掌握Linux文件系统的基本特征;
2、模拟实现Linux文件系统的简单I/O流操作:备份文件。
1、浏览Linux系统根目录下的子目录,熟悉每个目录的文件和功能;
2、设计程序模拟实现Linux文件系统的简单I/O流操作:备份文件。
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() 来实现简单的文件备份, 即将一个文件的内容拷贝到另一个文件中去。
实验只是模拟实现文件的备份功能,不需要系统调用函数。
//test.c
#include
#include
#include
#define BUFFER_SIZE 4
#define SOURCE_FILE "./source.txt"
#define BACKUP_FILE "./backup.txt"
int main()
{
char buffer[BUFFER_SIZE]; //建立缓冲区
FILE* sf, * bf; // FILE结构指针
sf = fopen(SOURCE_FILE, "rt+"); // 以读的方式打开source.txt
bf = fopen(BACKUP_FILE, "wt+"); // 以写的方式打开backup.txt
if (sf)
{
printf("success in opening source file.\n");
}
else
{
printf("Error in opening source file.\n");
exit(1);
}
if (bf)
{
printf("success in opening backup file.\n");
}
else
{
printf("Error in creating backup file.\n");
exit(1);
}
while (fread(buffer, BUFFER_SIZE, 1, sf)) // 用fread函数读取source.txt一个BUFFER_SIZE大小的数据到缓冲区
{
if(!fwrite(buffer, BUFFER_SIZE, 1, bf)) // 用fread函数讲一个BUFFER_SIZE大小的缓冲区数据写入backup
{
printf("Error in writing file.\n");
exit(1);
}
}
printf("backup backup.\n");
// 关闭流
if (fclose(sf))
{
printf("Error in close source file.\n");
exit(1);
}
else
{
printf("success in close source file.\n");
}
if (fclose(bf))
{
printf("Error in close backup file.\n");
exit(1);
}
else
{
printf("success in close backup file.\n");
}
return 0;
}
//test1.c
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 4
#define SOURCE_FILE "./source.txt"
#define BACKUP_FILE "./backup1.txt"
int main()
{
char buffer[BUFFER_SIZE];
int sf, bf;
long long ret;
sf = open(SOURCE_FILE, 0);
bf = open(BACKUP_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (sf == -1)
{
printf("Error in opening source file.\n");
exit(1);
}
if (bf == -1)
{
printf("Error in creating backup1 file.\n");
exit(1);
}
while ((ret = read(sf, buffer, BUFFER_SIZE)) != 0)
{
if (ret == -1)
{
printf("Error in reading file.\n");
exit(1);
}
int status = write(bf, buffer, ret);
if (status == -1)
{
printf("Error in writing file.\n");
exit(1);
}
}
printf("sbackup in backup1.\n");
if (close(sf) == -1)
{
printf("Error in close source file.\n");
exit(1);
}
else
{
printf("success in close source file.\n");
}
if (close(bf) == -1)
{
printf("Error in close backup file.\n");
exit(1);
}
else
{
printf("success in close backup file.\n");
}
}
实验通过使用两种方式实现了txt文件的备份。使用系统调用函数是通过文件描述符来实现文件的备份。C库函数则FILE结构指针实现。
1、使用系统调用函数open(),read(),write(),close()实现简单文件备份的原理是什么?
系统调用函数open(),read(),write(),close()是通过文件描述符来实现文件的备份。系统调用 open 用于创建一个新的文件描述符。open 建立了一条到文件或设备的访问路径。在调用失败时,将返回 -1;如果调用成功,它将返回一个可以被 read、write 和其他系统调用使用的文件描述符。从文件描述符相关联的文件里读入 BUFFER_SIZE长的数据,并把它们放到数据区 buffer 中。系统调用 write 的作用是把数据区 buffer 的前BUFFER_SIZE长的数据写入与文件描述符关联的文件中。它返回实际写入的字节数。系统调用 close 可以用来终止文件描述符与其对应文件之间的关联。当 close 系统调用成功时,返回 0,文件描述符被释放并能够重新使用。从而实现简单的文件备份。
2、使用C库函数fopen(), fread(), fwrite(), fclose() 来实现简单文件备份的原理是什么?
通过调用库函数fopen()打开一个流,库函数fopen()的返回值为一个FILE结构指针,此结构中包含对所打开的流进行操作所需的全部信息。Fread()函数从文件中读入数据到指定的地址中的指定长度。fwrite() 是 C 语言标准库中的一个文件处理函数,功能是向指定的文件中写入若干数据块,如成功执行则返回实际写入的数据块数目。该函数以二进制形式对文件进行操作,不局限于文本文件。当流操作完成后,这个时候需要将流关闭,调用函数fclose()来完成,使用fclose就可以把缓冲区内最后剩余的数据输出到磁盘文件中,并释放文件指针和有关的缓冲区。
3、上述二者的区别在哪里?
前者(open)属于低级IO,后者(fopen)是高级IO。
前者返回一个文件描述符,后者返回一个文件指针。
前者无缓冲,后者有缓冲。
前者与 read, write 等配合使用, 后者与 fread, fwrite等配合使用。
后者是在前者的基础上扩充而来的,在大多数情况下,用后者。
fopen() 是 C 标准库中的函数,而 open() 是 Linux 中的系统调用函数。
但前者是在内核模式中运行的,且是在文件描述符的基础上进行,而后者则是在用户模式下运行的,且是在数据流的基础上进行,