每个进程都有一个当前工作目录,此目录是搜索所有相对路径名的起点。当用户登录到UNIX系统时,其当前工作目录通常是口令文件(/etc/passwd)中该用户登录项的第六个字段——用户的起始目录。当前工作目录的是进程的一个属性,起始目录则是登录名的一个属性。
进程调用chdir
或fchdir
函数来更改当前工作目录。
#include <unistd.h>
int chdir(const char *pathname);
int fchdir(int fd);
两个函数的返回值:若成功,返回 0;若出错,返回 -1。
两个函数分别以pathname
和fd
为新的工作目录。
测试示例:
#include "../../include/apue.h"
int main(void)
{
if(chdir("/tmp") < 0)
{
err_sys("chdir failed");
}
printf("chdir to /tmp succeeded.\n");
return 0;
}
当执行上面示例的程序时,发现当前工作目录并不会随着程序的调用chdir
而改变。由此可见,为了改变shell进程自己的工作目录,shell应当直接调用chdir
函数,为此,cd
命令直接内建在shell中。
获得当前工作目录的完整的绝对路径名通过getcwd
函数来完成。
#include<unistd.h>
char *getcwd(char *buf, size_t size);
函数返回值:若成功,返回 buf;若出错,返回NULL。
测试示例:
#include "../../include/apue.h"
int main(void)
{
char *ptr;
size_t size;
if(chdir("/home/dunk/APUE/chapter4/exercise/mkdiratfile2") < 0)
err_sys("chdir failed.");
ptr = path_alloc(&size);
if(getcwd(ptr, size) == NULL)
err_sys("getcwd failed");
printf("cwd = %s\n", ptr);
return 0;
}
st_dev
和st_rdev
经常引起混淆,使用两个字段的规则如下:
- 每个文件系统所在的存储设备都由其主、次设备号表示。设备号所用的数据类型是基本数据类型
dev_t
。主设备号标识设备驱动程序,有时编码为与其通信的外设板;次设备号标识特定的子设备。 - 通常可以使用两个宏:
major
和minor
来访问主次设备号。 - 系统中与每个文件名关联的
st_dev
值是文件系统的设备号,该文件系统包含了这一文件名以及与其对应的i结点。 - 只有字符特殊文件和块特殊文件才有
st_rdev
值。此值包含实际设备的设备号。
测试示例:
#include "../../include/apue.h"
#ifdef SOLARIS
#include <sys/mkdev.h>
#endif
#include <sys/sysmacros.h>
int main(int argc, char *argv[])
{
int i;
struct stat buf;
for(i = 1; i < argc; i++){
printf("%s: ", argv[i]);
if(stat(argv[i], &buf) < 0){
err_ret("stat error");
continue;
}
printf("dev = %d/%d", major(buf.st_dev), minor(buf.st_rdev));
if(S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)){
printf(" (%s) rdev = %d/%d", (S_ISCHR(buf.st_mode)) ? "character"
: "block", major(buf.st_dev), minor(buf.st_rdev));
}
printf("\n");
}
return 0;
}