第4章 文件系统:编写pwd
1.从用户角度看文件系统
从用户角度看unix系统中硬盘上的文件组成一棵目录树,每个目录能包含文件或其他目录。
du(disk usage 的简称)是用于查找文件和目录的磁盘使用情况的命令,df(disk filesystem 的简称)用于显示 Linux 系统的磁盘利用率。
2.unix文件系统的内部结构
第一层抽象:从磁盘到分区;第二层抽象:从磁盘到块序列,为磁盘块编号;第三层抽象:从块序列到三个区域划分
文件系统中的第一个块称为超级块,这个块存放文件系统本身的结构信息;
每个文件都有一些属性,这些性质被记录在一个称为i- 节点的结构中;
文件系统的第三个部分是数据区,文件内容保存在这里。
创建一个文件的过程
(1)存储属性:内核先找到一个空的i- 节点;
(2)存储数据:内核从*块的列表中找出*块;
(3)记录分配情况:内核在i-节点的磁盘分布区记录了上述的块序列;
(4)添加文件名到目录:文件名和i-节点对应的文件内容和属性连接了起来。
比例创建一个新文件 who > userlist
目录是包含了文件名字列表的特殊文件,它的抽象模型是一个包含i-节点号和文件名的表,其中i-节点包含了文件的属性和数据块的列表。根目录的"."当前目录和".."父目录都指向自己。
cat命令的工作原理
(1)在目录中寻找文件名
(2)定位i-节点并读取其内容
(3)访问存储文件内容的数据块
所有从文件读取数据的命令,例如cat、cp、more、who等,都是将文件名传给open来访问文件内容。对open的每次调用都是先在目录中寻找文件名,然后根据目录中的i-节点号获取文件的属性,最终找到文件内容。
unix使用间接块存储大文件
3.理解目录
从用户角度看,目录是一个文件名的列表;从unix角度看是一个被命名的指针列表。
使用ls -iaR可以列出一棵树中的所有文件的i-节点号。
目录包含的是文件的引用,每个引用被称为链接。文件的内容存储在数据块,文件的属性被记录在i-节点中。
文件没有文件名,仅拥有i-节点号,但是链接具有名字。
unix使用mkdir、rmdir、mv(rename)、ln(link)、cd(chdir)和rm(unlink)等命令对树状目录结构进行管理。
4.编写pwd
(1)得到“.”的i-节点号,称其为n(使用stat)
(2)chdir .. (使用chdir)
(3)找到i-节点号n链接的名字(使用opendir、readdir、closedir)
重复直到到达树的顶端
pwd命令重复循环直到一个目录的“.”和“..”的i-节点号相同时,就可以认为已经到达文件树的顶端。
建立一个循环,使用strcat或sprintf建立目录名字的字符串序列。通过一个递归的程序逐步到达树的顶端来一个接一个地显示目录名,从而避免了字符串的管理。
/* spwd.c: a simplified version of pwd
*
* starts in current directory and recursively
* climbs up to root of filesystem, prints top part
* then prints current part
*
* uses readdir() to get info about each thing
*
* bug: prints an empty string if run from "/"
**/
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>
#include<stdlib.h>
#include<string.h>
ino_t get_inode(char *);
void printpathto(ino_t);
void inum_to_name(ino_t , char *, int );
int main()
{
printpathto( get_inode( "." ) ); /* print path to here */
putchar('\n'); /* then add newline */
return 0;
}
void printpathto( ino_t this_inode )
/*
* prints path leading down to an object with this inode
* kindof recursive
*/
{
ino_t my_inode ;
char its_name[BUFSIZ];
if ( get_inode("..") != this_inode )
{
chdir( ".." ); /* up one dir */
inum_to_name(this_inode,its_name,BUFSIZ);/* get its name*/
my_inode = get_inode( "." ); /* print head */
printpathto( my_inode ); /* recursively */
printf("/%s", its_name ); /* now print */
/* name of this */
}
}
void inum_to_name(ino_t inode_to_find , char *namebuf, int buflen)
/*
* looks through current directory for a file with this inode
* number and copies its name into namebuf
*/
{
DIR *dir_ptr; /* the directory */
struct dirent *direntp; /* each entry */
dir_ptr = opendir( "." );
if ( dir_ptr == NULL ){
perror( "." );
exit(1);
}
/*
* search directory for a file with specified inum
*/
while ( ( direntp = readdir( dir_ptr ) ) != NULL )
if ( direntp->d_ino == inode_to_find )
{
strncpy( namebuf, direntp->d_name, buflen);
namebuf[buflen-1] = '\0'; /* just in case */
closedir( dir_ptr );
return;
}
fprintf(stderr, "error looking for inum %ld\n", inode_to_find);
exit(1);
}
ino_t get_inode( char *fname )
/*
* returns inode number of the file
*/
{
struct stat info;
if ( stat( fname , &info ) == -1 ){
fprintf(stderr, "Cannot stat ");
perror(fname);
exit(1);
}
return info.st_ino;
}
多文件系统的组合:由多棵构成的树。unix允许将一个磁盘的存储组织成一棵由多棵树相互连接的树,每个磁盘或磁盘上的每个分区都包含一棵目录树,unix提供一种方法将这些树整合成一棵更大的树。
5.符号链接
硬链接是将目录链接到树的指针,硬链接同时也是将文件名和文件本身链接起来的指针,原文件和硬链接i-节点相同,文件属性也相同,删除原文件硬链接无影响。创建硬链接使用ln命令
软链接通过名字引用文件,和原文件的i-节点号不同,相当于原文件的快捷方式,删除原文件,软连接失效。创建软连接ln -s