本次测试环境和上次相同
-
Linux中的文件系统
文件系统中要存贮文件的内容,文件的属性,和目录,这些不同的数据类型的东西,Linux采用了一个简单的方法,将他们存贮在磁盘上面。(下面这个张图是鸟哥的Linux私房菜上面文件系统示意图)
下面我们要重点关注的就是superblock,inode table和data block三部分。 -
Linux如何读取一个文件
现在先说一下大概的方式,后面举一个详细的例子。文件名是存贮在目录中的,所以首先我们为找到一个文件,==内核第一步得到它的所在目录去找到相对应的名字和其对应的Indoe节点编号;内核第二步得在该文件系统中的i-节点区域找到第一步中的i-节点;内核第三步就是去读取该i-节点所对应的信息,有文件的属性,其文件实际数据所存发的data block的编号。==当然,如果该用户没有对应的权限,是无法读取文件的信息的,就是会在第三步出现问题,例如open函数就会返回一个-1。 -
实现pwd命令所要用到的函数
int result=opendir(char *filename);
struct dirent *direntp=readdir(DIR *dir);
int result=stat(char *filename,struct stat *buf);
int result=chdir( const char *path);
这里我特别想要说的就是关于readdir这个函数,它是会返回目录流dir下面的目录的进入点。这个struct dirent的结构可以自己去Linux中#include<drient.h>文件中找,他里面没有一个字符数组是用来存贮该目录下的文件/目录的名字的。那么它是怎么返回的捏?;所以,在使用readdir函数的时候,通常得和while一起使用,因为读取发生错误或者读取到目录文件尾的时候就会返回NULL; -
系统怎么知道当前目录是什么的?
借用Unix/Linux编程实践书本上面的一段话:“Unix上的每一个运行的程序都有一个当前的目录,chdir系统调用改变进程的当前目录。在系统内部,进程有一个存放当前目录i-节点号的变量。从一个目录到另一个目录只是改变了这个变量的值。”至于为什么Unix的设计者不将根目录的父级目录设计为NULL,而是设计为其本身,(以下是个人观点)。如果你设计为空后,之后就无法再次跳转了,如果,跳转到其子目录,但是你如果发现到了根目录后,还是可以进去子目录。设计为NULL后,就可能导致连续操作的中断,但是设计为其本身就会不用担心这一点。 -
pwd命令实现流程
从当前目录开始上溯,知道“…”目录和“.”目录的i-节点的值是一个的时候,证明到达了文件系统的根目录,就可以停止了。 -
pwd01.c代码
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<dirent.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("."));
putchar('\n');
return 0;
}
void printpathto(ino_t this_inode)
{
ino_t my_inode;
char its_name[BUFSIZ];
if(get_inode("..")!=this_inode)
{
chdir("..");
inum_to_name(this_inode,its_name,BUFSIZ);
my_inode=get_inode(".");
printpathto(my_inode);
printf("/%s",its_name);
}
}
void inum_to_name(ino_t inode_to_find,char *namebuf,int buflen)
{
DIR *dir_ptr;
struct dirent *direntp;
dir_ptr=opendir(".");
if(dir_ptr==NULL)
{
perror(".");
exit(1);
}
while((direntp=readdir(dir_ptr))!=NULL)
{
printf("inode_to_find.d_ino=%ld,direntp->d_ino=%ld\n",inode_to_find,direntp->d_ino);
// printf("dir=%s\n",direntp->d_name);
if(direntp->d_ino==inode_to_find)
{
strncpy(namebuf,direntp->d_name,buflen);
namebuf[buflen-1]='\0';
closedir(dir_ptr);
return;
}
}
// fprintf(stderr,"error looking for inum %d\n",inode_to_find);
exit(1);
}
ino_t get_inode(char *fname)
{
struct stat info;
if(stat(fname,&info)==-1)
{
fprintf(stderr,"cannot stat");
perror(fname);
exit(1);
}
return info.st_ino;
}```