• 20155212——man指令的使用及mypwd的实现


    man指令的使用及mypwd的实现

    man指令的使用

    一、man -k的k参数以及代表的意思

    代号 代表內容
    1 使用者在shell中可以操作的指令或可执行档
    2 系統核心可呼叫的函数与工具等
    3 一些常用的函数(function)与函数库(library),大部分是C的函数库(libc)
    4 装置档案的说明,通常在/dev下的档案
    5 设定档或者是某些档案的格式
    6 游戏(games)
    7 惯例与协定等,例如Linux档案系统、网络协定、ASCII code等等的說明
    8 系統管理員可用的管理指令
    9 跟kernel有关的文件

    二、如何将man指令检索到的帮助文档中文显示

    ubuntu源里面已经包含了中文的man包,所以不用从其他地方down了,直接
    sudo apt-get install manpages-zh
    但是这样man默认显示的还不是中文,还需要以下两步:

    1. 把中文man包转换成utf8格式的
      新建一个脚本文件
      vim t.sh
      把下面内容添加进去
      #!/bin/bashcd /usr/share/man/zh_CN/for k in *docd $kfor i in *.gzdo j=`echo ${i%.gz}` gunzip $i iconv -f gb18030 -t utf8 $j >tmp mv tmp $j gzip $jdonecd ..done
      然后
      sudo ./t

    2. 修改man默认的语言
      sudo gedit /etc/manpath.config 把里面的所有的 /usr/share/man 改成 /usr/share/man/zh_CN
      保存后退出,然后你再试一下man ls

    mypwd的实现

    一、查找与文件路径相关的系统调用与C库函数

    1. 使用man -k directory | grep 3查找与路径有关的库函数,可以发现readdir和opendir以及getcwd函数:

    2. 通过man 3 readdir得到如下结构体

      struct dirent {
                 ino_t          d_ino;       /* inode number */
                 off_t          d_off;       /* not an offset; see NOTES */
                 unsigned short d_reclen;    /* length of this record */
                 unsigned char  d_type;      /* type of file; not supported
                                                by all filesystem types */
                 char           d_name[256]; /* filename */
             };
      

      从这个结构体以及相关帮助文档中可以看出,需要找到文件的i-node才可以找到与之对应的文件名。

    3. 通过man -k inode发现有stat函数可以使用

    4. 在stat的帮助文档中可以找到readlink(2)的信息,下面是readlink的帮助文档。

    二、综上可以设计出如下三种mypwd

    1)my_getcwd:

    • 使用getcwd函数:
        定义字符数组用来存储路径;
    
    使用getcwd函数;
    判断成功找到路径;
    成功则输出路径,不成功则输出错误信息并退出;
    • 产品代码:
    #include <stdio.h>
    #include <unistd.h>
    int main(void)
    {
        char buff[256];
        if(getcwd(buff,sizeof(buff)))
        perror("getcwd");
        else
        printf("当前路径为:%s
    ",buff);
        return 0;
    }
    
    • 测试结果:

    2)my_readlink:

    • 使用readlink函数:
        调用readlink函数;
    根据readlink的返回值去除后面的文件名,从而获得当前路径;
    • 产品代码:
    #include <stdio.h>
    #include <unistd.h>
    char * get_exe_path( char * buf, int count)
    {
        int i;
        int rslt = readlink("/proc/self/exe", buf, count - 1);
        if (rslt < 0 || (rslt >= count - 1))
        {
            return NULL;
        }
        buf[rslt] = '';
        for (i = rslt; i >= 0; i--)
        {
            if (buf[i] == '/')
            {
                buf[i + 1] = '';
                break;
            }
        }
        return buf;
    }
    
    int main(int argc, char ** argv)
    {
        char path[256];
        printf("当前路径:%s
    ", get_exe_path(path, 256));
        return 0;
    }
    
    • 运行结果:

    3)my_pwd:

    • 综合使用stat函数,readdir函数和opendir函数:
        Step1:调用stat函数获得当前目录文件的iNode值,以及父辈目录的iNode;
    Step2:判断当前目录iNode值与父目录iNode值是否相等,如果相等则跳到Step6;
    Step3:判断此时的iNode是否使用chdir进入上一层父目录;
    Step4:调用opendir打开当前目录文件,并使用readdir读取所有文件的iNode值并与之前iNode值对比,如果一致,则将文件名存入字符数组中;
    Step5:返回Step1;
    Step6:打印出存有路径的字符串;
    • 产品代码:
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <string.h>
    #include <unistd.h>
    /*根据文件名获取文件inode-number*/
    ino_t get_ino_byname(char *filename)
    {
        struct stat file_stat;
        if (0 != stat(filename, &file_stat)) {
            perror("stat");
            exit(-1);
        }
        return file_stat.st_ino;
    }
    
    /*根据inode-number ,在当前目录中查找对应的文件名*/
    char* find_name_byino(ino_t ino)
    {
        DIR *dp = NULL;
        struct dirent *dptr = NULL;
        char *filename = NULL;
        if (NULL == (dp = opendir("."))) {
            fprintf(stderr, "Can not open Current Directory
    ");
            exit(-1);
        } else {
            while (NULL != (dptr = readdir(dp))) {
                if (dptr->d_ino == ino) {
                    filename = strdup(dptr->d_name);
                    break;
                }
            }
            closedir(dp);
        }
        return filename;
    }
    
    /*限制最大的目录深度*/
    #define MAX_DIR_DEPTH (256)
    
    int main(int argc, char *argv[])
    {
        /*记录目录名的栈*/
        char *dir_stack[MAX_DIR_DEPTH];
        unsigned current_depth = 0;
    
        for(;;) {
            /*1.通过特殊的文件名“.”获取当前目录的inode-number*/
            ino_t current_ino = get_ino_byname(".");
            /*2.通过特殊的文件名“..”获取当前目录的父级目录的inode-number*/
            ino_t parent_ino = get_ino_byname("..");
    
            /*3.判断当前目录和上级目录的inode-number是否一样*/
            if (current_ino == parent_ino)
                break; /*4.如果两个inode-number一样说明到达根目录*/
    
            /*5.如果两个inode-number不一样*/
            /*切换至父级目录,根据步骤1获取的inode-number,在父级目录中搜索对应的文件名并记录下来, 重新回到步骤1*/
            chdir("..");
            dir_stack[current_depth++] = find_name_byino(current_ino);
            if (current_depth>=MAX_DIR_DEPTH) { /*路径名太深*/
                 fprintf(stderr, "Directory tree is too deep.
    ");
                 exit(-1);
            }
        }
    
        /*输出完整路径名*/
        int i = current_depth-1;
        for (i = current_depth-1; i>=0; i--) {
           fprintf(stdout, "/%s", dir_stack[i]);
        }
        fprintf(stdout, "%s
    ", current_depth==0?"/":"");
    
        return 0;
    }
    
    • 运行结果:
  • 相关阅读:
    SpringBoot和SpringCould的关系
    MyBatis全局配置文件头
    MyBatis的SQL映射文件头
    MyBatis 驼峰式配置 yml配置
    频率组件
    序列化和反序列化
    生成器面试题
    序列化组件
    进程间通信IPC机制
    信号量、event事件和线程queue
  • 原文地址:https://www.cnblogs.com/elevator/p/7859394.html
Copyright © 2020-2023  润新知