如果要实现pwd命令,必需对linux的文件系统非常了解。下面我们先从文件系统说起,然后过度到编写pwd的知识。
1、linux的文件系统
从用户的角度来看,linux的文件系统就是一个目录树,从系统的角度看,是对磁盘划分的抽象。磁盘的第一级抽象:从磁盘到分区;第二级:从磁盘到块序
列,盘片被划分为磁道,磁道被划分为扇区;第三级:从块序列到三个区域的划分。在linux下,磁盘被划分为三个区域:超级块,i-结点和书局区。超级块
是文件系统的第一个块,存放文件系统本身的信息,i-结点存放每个文件的属性『大小,文件所有者,权限等』。数据区存放文件的内容。
2、创建一个文件的过程
四个步骤:
— 存储属性,分配i-结点;
— 存储数据,维护一个存放文件的块列表;
— 记录分配情况,在i-结点的磁盘分布区记录了存放文件的块序列;
— 添加文件名到目录,在目录文件中增加一条记录。
3、目录的工作过程
目录是包含了文件名子列表的特殊文件,可以使用命令ls -1ia
director来查看对应的i-node号。理解目录和目录的工作过程是理解文件系统的关键。在每个目录文件的列表中有两个特殊的项:.代表本级目
录,..代表上级目录,并且都有对应的i-node号,所以我们可以通过这两个i-node号逐级向上就可以找到当前工作目录的绝对路径。但是什么时间算
到了根目录呢?先执行ls -i /看看结果,可以发现,根目录下的.和..对应的i-node号相同,这可以作为搜索结束的条件。
4、pwd命令的实现
代码如下:
1 /*
2 * starts in current directory and recursively climbs up to root
3 * of filesystem, prints top part then prints current part
4 * use readdir() to get info about each thing
5 */
6
7 #include <stdio.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <dirent.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14
15 ino_t get_inode(char *);
16 void printpathto(ino_t);
17 void inum_to_name(ino_t, char *, int);
18
19 int main()
20 {
21 printpathto(get_inode("."));
22 printf("\n");
23 return 0;
24 }
25
26 void printpathto(ino_t this_inode)
27 /*
28 * prints path leading down to an object with this inode
29 * kind of recursive
30 */
31 {
32 ino_t my_inode;
33 char its_name[BUFSIZ];
34 if(get_inode("..") != this_inode) //not lead to root
35 {
36 chdir(".."); //up one dir
37 inum_to_name(this_inode, its_name, BUFSIZ); //get its name
38 my_inode = get_inode(".");
39 printpathto(my_inode);
40 printf("/%s", its_name);
41 }
42 }
43
44 void inum_to_name(ino_t inode_to_find, char *namebuf, int buflen)
45 /*
46 *looks through current directory for a file with this node
47 *number and copies its name into namebuf
48 */
49 {
50 DIR *dir_ptr;
51 struct dirent *direntp;
52 dir_ptr = opendir(".");
53 if(dir_ptr == NULL)
54 {
55 perror(".");
56 exit(1);
57 }
58 while((direntp = readdir(dir_ptr)) != NULL)
59 {
60 if (direntp->d_ino == inode_to_find)
61 {
62 strncpy(namebuf, direntp->d_name, buflen);
63 namebuf[buflen - 1] = '\0';
64 closedir(dir_ptr);
65 return ;
66 }
67 }
68 fprintf(stderr, "error looking for inum %d\n", inode_to_find);
69 exit(1);
70 }
71
72
73 ino_t get_inode(char *fname)
74 {
75 /*
76 * return inode number of the file
77 */
78 struct stat info;
79 if((stat(fname, &info)) == -1)
80 {
81 fprintf(stderr, "Cannot stat");
82 perror(fname);
83 exit(1);
84 }
85
86 return info.st_ino;
87 }
88
89
结论:
对于理解系统编程,理解操作系统,学习相关的命令,并探究命令的实现过程,最后自给编写一个同样功能的命令,不失为一种很好的学习方法。