每個進程都有一個當前工作目錄,此目錄是搜索所有相對路徑名的起點(不以斜杠開始的路徑名為相對路徑名)。當用戶登錄到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"intmain(void){ if(chdir("/tmp") < 0) err_sys("chdir failed"); printf("chdir to /tmp succeeded/n"); exit(0);}
運行結果:
[root@localhost apue]# pwd/home/zhu/apue[root@localhost apue]# ./prog4-8chdir 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_MAXstatic int pathmax = PATH_MAX;#elsestatic int pathmax = 0;#endif#define SUSV3 200112Lstatic long posix_version = 0;/* If PATH_MAX is indeterminate, no guarantee this is adequate */#define PATH_MAX_GUESS 1024char *path_alloc(int *sizep);intmain(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/n", 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/。
新聞熱點
疑難解答