zoukankan      html  css  js  c++  java
  • 文件和目录之chdir、fchdir和getcwd函数

    每个进程都有一个当前工作目录,此目录是搜索所有相对路径名的起点(不以斜杠开始的路径名为相对路径名)。当用户登录到UNIX系统时,其当前工作目录通常是口令文件(/etc/passwd)中该用户登录项的第6个字段——用户的起始目录(home directory)。当前工作目录是进程的一个属性,起始目录则是登录名的一个属性

    进程通过调用chdir或fchdir函数可以更改当前工作目录。

    #include <unistd.h>
    int chdir( const char *pathname );
    int fchdir( int filedes );
    两个函数的返回值:若成功则返回0,若出错则返回-1

    在这两个函数中,分别用pathname或打开文件描述符来指定新的当前工作目录。

    实例

    因为当前工作目录是进程的一个属性,所以它只影响调用chdir的进程本身,而不影响其他进程。

    程序清单4-8 chdir函数实例

    [root@localhost apue]# cat prog4-8.c
    #include "apue.h"
    
    int
    main(void)
    {
            if(chdir("/tmp") < 0)
                    err_sys("chdir failed");
            printf("chdir to /tmp succeeded
    ");
            exit(0);
    }

    运行结果:

    [root@localhost apue]# pwd
    /home/zhu/apue
    [root@localhost apue]# ./prog4-8
    chdir to /tmp succeeded
    [root@localhost apue]# pwd
    /home/zhu/apue

    从中可以看出,执行上面程序的shell的当前工作目录并没有改变,其原因是shell创建了一个子进程,由该子进程具体执行该程序。

    因为内核保存有当前工作目录的信息,所以我们应能取其当前值。不幸的是,内核为每个进程只保存指向该目录v节点的指针等目录本身的信息,并不保存该目录的完整路径名。

    我们需要一个函数,它从当前工作目录(.目录项),用..目录项找到其上一级的目录,然后读其目录项(上一级目录中肯定有一个目录项是当前工作目录),直到该目录项中的i节点编号与工作目录i节点编号相同,这样就找到了其对应的文件名。按照这种方法,逐层上移,直到遇到根,这样就得到了当前工作目录完整的绝对路径名。很幸运,函数getcwd就提供了这种功能。

    #include <unistd.h>
    char *getcwd( char *buf, szie_t size );
    返回值:若成功则返回buf,若出错则返回NULL

    向此函数传递两个参数,一个是缓冲地址buf,另一个是缓冲的长度size(单位:字节)。该缓冲必须有足够的长度以容纳绝对路径名再加上一个null终止字符,否则返回出错。

    程序清单4-9 getcwd函数实例

    [root@localhost apue]# cat prog4-9.c
    #include "apue.h"
    #include <errno.h>
    #include <limits.h>
    
    #ifdef PATH_MAX
    static int pathmax = PATH_MAX;
    #else
    static int pathmax = 0;
    #endif
    
    #define SUSV3 200112L
    
    static long posix_version = 0;
    
    /* If PATH_MAX is indeterminate, no guarantee  this is adequate */
    #define PATH_MAX_GUESS 1024
    
    char *path_alloc(int *sizep);
    
    int
    main(void)
    {
            char *ptr;
            int size;
    
            if(chdir("/home/zhu/test") < 0)
                    err_sys("chdir failed");
    
            ptr = path_alloc(&size);        /* our own function */
            if(getcwd(ptr, size) == NULL)
                    err_sys("getcwd failed");
    
            printf("cwd = %s
    ", ptr);
            exit(0);
    }
    
    char *
    path_alloc(int *sizep) /* also return allocated size, if nonull */
    {
            char *ptr;
            int size;
    
            if(posix_version == 0)
                    posix_version = sysconf(_SC_VERSION);
    
            if(pathmax == 0) {   /* first time trough */
                    errno = 0;
                    if((pathmax = pathconf("/", _PC_PATH_MAX)) < 0) {
                            if(errno == 0)
                                    pathmax = PATH_MAX_GUESS;  /* it's indeterminate */
                            else
                                    err_sys("pathconf error for _PC_PATH_MAX");
                    } else {
                            pathmax++;    /* add one since it's relative to root */
                    }
            }
            if(posix_version < SUSV3)
                    size = pathmax + 1;
            else
                    size = pathmax;
    
            if((ptr = malloc(size)) == NULL)
                    err_sys("malloc error for pathname");
    
            if(sizep != NULL)
                    *sizep = size;
            return(ptr);
    }

    当一个应用程序需要在文件系统中返回到其工作的起点时,getcwd函数是有用的。在更换工作目录之前,我们可以调用getcwd函数先将其保存起来。在完成了处理后,就可以将从getcwd获得的路径名作为调用参数传送给chdir,这样就返回到了文件系统中的起点。

    fchdir函数向我们提供了一种完成此任务的便捷方法。在更换到文件系统中的不同位置前,无需调用getcwd函数,而是使用open打开当前工作目录(用open可以打开目录吗???我尝试用open打开一个目录,运行时出现错误:open: Is a directory),然后保存文件描述符。当希望回到原工作目录时,只需简单地将该文件描述符传递给fchdir。

    本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

  • 相关阅读:
    【面试题】M
    【转】C/S,B/S区别
    【转】指针和引用的区别
    内联函数
    实习-随记
    【面试】http协议知识
    wenbenfenlei
    【面试】链表反转
    测试面试题2
    测试面试题
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3505023.html
Copyright © 2011-2022 走看看