linux命令自己写

<span style="font-family: 'Microsoft YaHei'; font-size: 18px; background-color: rgb(255, 255, 255);">其实这个命令不是非常常用的命令,至少对于我来说这个命令的使用频率不是那么的高。但是学习这个编写这个命令有助于了解文件系统的相关知识。</span>

对于这个命令需要了解的重要知识点就是i-node.

首先从文件系统的内部结构谈起,unix/linux的文件系统其实是经过了三层抽象的。

1.磁盘到分区

很简单,那就是一个磁盘被分为了几个区域,就像国家被分为不同的省市一样。

每个分区可以看作是独立的磁盘。

2.磁盘到块序列

将每个磁盘表面划分为同心圆,这些同心圆又被分作扇区,就像街道被划分为住宅单元。于是就就构成了基本的储存单元—-扇区。每个扇区是可以储存一定字节的数据,例如每个扇区的大小是512字节。

将这些扇区编号使得系统可以计数磁盘上的每个块,,就像给街道的房屋编号一样,给磁盘的每个块分配一个序号。

一个将磁盘扇区编号的系统使得我们可以把磁盘视作一系列块的系统。

3.块序列到三个区域的划分

文件系统是用来储存文件内容,文件属性(文件所有者,日期等)和目录,这些不同的数据是如何储存在被编号的磁盘快上的呢?

unix中将磁盘块分为了三个部分:超级块(super-block),i-节点表(i-node table),数据区(data)。

=======i-node========

每个文件都有属性,包括大小,文件所有者,最近修改时间等等。这些性质被记录在一个被称为i-node的结构中,所有的i-node的大小相同。所有文件的i-node构成一个i-node表。

表中的每个i-node都通过位置来标识,例如标识为2的i-node位于文件系统的第三个位置。

i-node实际上代表了一个文件,i-node包含了文件的属性和数据块的列表。

下面直观的看看

$ls -1ia example

(注意是-1不是字母l)

可以看到左边是i-node,右边是文件名。就是说文件名x名对应的i-node号是123445

当前目录用“.”表示,i-node号是234345(随便举例的)。这就意味着当前目录的相关信息比如文件大,文件所有者等信息是放在编号为234345的i-node节点中的。然后再通过i-node中所指向的数据块来读取文件的内容。

======编写pwd====

以下的代码仅仅是最大限度的说明pwd的思路,要让程序顺利的编译通过和运行,还要稍加整理和添加一些东西

首先是相关的头文件

#include<stdio.h>#include<sys/stat.h>#include<sys/types.h>#include<dirent.h>

我们的思路:

编写函数get_inode(char *file_name)得到相关文件的i-node

编写函数inode_to_name(ino_t, char *, int)将我们得到的i-node转化为文件的名字

编写函数print_path(ino_t)将路径名字打印出来。

<span style="font-size:18px;">6 ino_t get_inode(char *file_name)    7 {    8     struct stat info;    9     if( ( stat(file_name, &info) ) == -1 )   10     {   11         fprintf(stderr, "cannot stat");x  12         perror("stat");   13         exit(1);   14     }   15     return info.st_ino;   16 }</span>

这个函数返回指向stat的成员变量。

<span style="font-size:18px;">void inode_to_name(ino_t inode_to_find, char *file_name, int buflen)   19 {   20     DIR *dir_ptr;   21     dir_ptr = opendir(".");   22     if( dir_ptr == NULL )   23     {   24         perror( "." );   25         exit(1);   26     }   27     struct dirent *dir_enpt;   28     while( ( dir_enpt = readdir( dir_ptr ) ) != NULL )   29     {   30         if( dir_enpt->d_ino == inode_to_find )   31         {x  32             strncpy(file_name, dir_enpt->d_name, buflen);   33             file_name[buflen-1]='\0';   34             closedir( dir_ptr );   35         }   36     }   37 }</span>

最后一个就是将路径名字打印出来啦

运用的递归,没有使用while循环操作

38 void print_path( ino_t this_inode )   39 {      40     ino_t my_inode;   41     char its_name[BUFSIZ];x  42     if( get_inode( ".." ) != this_inode )   43     {x  44         chdir("..");x  45         inode_to_name(this_inode, its_name, BUFSIZ);   46         my_inode = get_inode(".");   47         print_path( my_inode );   48         printf("/%s", its_name);   49     }   50 }

简单说说这里的业务逻辑吧。

想想在shell中输入pwd命令。。。。。。。。。。。。

开始执行get_inode( "." ),参数是当前的工作目录,返回值是当前目录的i-node号,命名为this_inode.

将当前目录的i-node(即就是this_inode)和上一级目录(父目录)的i-node比较(上一级的i-node同样是用get_inode( ".." )得到,只不过参数变成了"..")如果不相同的话,转入上一级目录,同时通过inode_to_name()函数将当前的this_inode转换为目录的名字。chdir函数是改变进程的工作目录的,到达父目录后,同样的方法得到父目录的i-node,(此时的父目录就是当前目录了),递归调用print_path函数打印出路径名称。当到达根目录的时候,由于根目录的this_inode和它的父目录的i-node是相同的,那么打印结束,整个业务流程结束。

不然你大概会一直好奇和不甘吧——家门前的那条小路,

linux命令自己写

相关文章:

你感兴趣的文章:

标签云: