选做 实现mypwd
实验内容:
-
1.学习pwd命令。
-
2.研究pwd实现需要的系统调用(man -k; grep),写出伪代码。
-
3.实现mypwd。
-
4.测试mypwd。
实验步骤:
学习pwd命令
man pwd
查看pwd
功能
-
该命令用来显示目前所在的工作目录。指令英文原义:print work directory。
-
显示当前目录所在路径 pwd
-
显示当前的路径,有连接文件时,不使用连接路径,直接显示连接文件所指向的文件;当包含多层连接文件时,显示连接文件最终指向的文件: pwd –P
-
显示当前的路径,有连接文件时,直接显示连接文件的路径,(不加参数时默认此方式):pwd -L
-
显示帮助信息:pwd -help
-
显示版本信息:pwd -version
-
研究pwd实现需要的系统调用(man -k; grep)
- (1)查看相关系统调用函数信息:
man -k dir | grep 2
- (2)可以得知
getcwd
命令可以获得当前目录路径。man getcwd
查看getcwd
命令功能。
找到所需要的头文件以及函数
#include <unistd.h>
char *getcwd(char *buf, size_t size);
图中getcwd():getcwd(char *buf,size_t size)
是将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数size为buf的空间大小。
- (3)由刚才
man -k directory | grep 2
获得的相关命令中我们也可以发现chdir
命令会被用到。man chdir
查看chdir命令功能。
找到所需要的头文件以及函数
#include <unistd.h>
int chdir(const char *path);
图中chdir():int chdir(const char *path )
用于改变当前工作目录,调用参数是指向目录的指针,调用进程需要有搜索整个目录的权限。
- (4)由刚才
man -k directory | grep 2
获得的相关命令中我们也可以发现readdi
r命令会被用到。man readdir
查看readdir命令功能
找到所需要的头文件以及函数
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
图中readdir():readdir(DIR* dir)
返回参数dir 目录流的下个目录进入点。
需要搭配opendir()
使用:opendir (const char * path )
获取path子目录下的所由文件和目录的列表,如果path是个文件则返回值为NULL。
对于它的实现,我们首先要知道,目录在Linux中其实也是一种文件,所以它也是由inode+
数据块构成的,每一个列表记录inode-number+filename
。
- (5)伪代码
-
通过上面我们可以发现可以通过两种函数来实现
pwd
命令 -
对
getcwd()
:
定义一个缓冲区数组buf[MAXPATH]; 调用getcwd(buf, MAXPATH); 输出返回值即为路经; -
对
readdir()
:-
通过特殊的文件名"."获取当前目录的inode-number(假设当前目录为a)
-
通过特殊的文件名".."获取当前目录的父级目录的inode-number
-
判断当前目录和上级目录的inode-number是否一样
-
如果两个inode-number一样说明达到根目录,输出完整路径,退出程序
-
如果两个inode-number不一样,切换至父级目录,根据步骤1获取的inode-number,在父级目录中搜索对应的文件名并记录下来,然后重新回到步骤1
-
-
实现mypwd
代码如下:
#include<stdio.h>
#include<sys/stat.h>
#include<dirent.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include <unistd.h>
void printpath();
char *inode_to_name(int);
int getinode(char *);
//功能:打印当前目录路径
void printpath()
{
int inode,up_inode;
char *str;
inode = getinode(".");
up_inode = getinode("..");
chdir("..");
str = inode_to_name(inode);
//当当前目录的i-node与父级目录的i-node相同时,到达根目录
if(inode == up_inode) {
return;
}
//打印路径
printpath();
printf("/%s",str);
}
//功能:获取当前目录的i-node
int getinode(char *str)
{
struct stat st;
if(stat(str,&st) == -1){
perror(str);
exit(-1);
}
return st.st_ino;
}
//功能:获取当前路径
char *inode_to_name(int inode)
{
char *str;
DIR *dirp;
struct dirent *dirt;
if((dirp = opendir(".")) == NULL){
perror(".");
exit(-1);
}
while((dirt = readdir(dirp)) != NULL)
{
if(dirt->d_ino == inode){
str = (char *)malloc(strlen(dirt->d_name)*sizeof(char));
strcpy(str,dirt->d_name);
return str;
}
}
perror(".");
exit(-1);
}
//主函数
int main()
{
printpath();
putchar('\n');
return 0;
}