从零开始UNIX环境高级编程(4):文件和目录
1. 函数stat、fstat、fstata和lstat
1.1 函数描述
函数原型 | 描述 |
---|---|
int stat(const char *restrict path, struct stat *restrict buf); | 获得与path有关的文件信息到buf |
int fstat(int fd, struct stat *buf); | 获得与文件描述符fd有关的文件信息到buf |
int fstatat(int fd, const char *path, struct stat *buf, int flag); | 返回fd有关的文件信息到buf,当flag设置为AT_SYMLINK_NOFOLLOW,功能和lstat一样;当path为绝对路径时,功能和stat一样 |
int lstat(const char *restrict path, struct stat *restrict buf); | 和stat作用类似,只是当文件是一个符号链接时,会返回符号链接的有关信息 |
1.2 stat结构体
stat结构体在不同的版本上实现会有所不同,在Mac OSX 10.12.2上根据宏_DARWIN_FEATURE_64_BIT_INODE是否定义,stat对应有两种实现方式。
- _DARWIN_FEATURE_64_BIT_INODE未定义
struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is NOT defined */
dev_t st_dev; /* device inode resides on */
ino_t st_ino; /* inode's number */
mode_t st_mode; /* inode protection mode */
nlink_t st_nlink; /* number of hard links to the file */
uid_t st_uid; /* user-id of owner */
gid_t st_gid; /* group-id of owner */
dev_t st_rdev; /* device type, for special file inode */
struct timespec st_atimespec; /* time of last access */
struct timespec st_mtimespec; /* time of last data modification */
struct timespec st_ctimespec; /* time of last file status change */
off_t st_size; /* file size, in bytes */
quad_t st_blocks; /* blocks allocated for file */
u_long st_blksize;/* optimal file sys I/O ops blocksize */
u_long st_flags; /* user defined flags for file */
u_long st_gen; /* file generation number */
};
- _DARWIN_FEATURE_64_BIT_INODE已定义
struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is defined */
dev_t st_dev; /* ID of device containing file */
mode_t st_mode; /* Mode of file (see below) */
nlink_t st_nlink; /* Number of hard links */
ino_t st_ino; /* File serial number */
uid_t st_uid; /* User ID of the file */
gid_t st_gid; /* Group ID of the file */
dev_t st_rdev; /* Device ID */
struct timespec st_atimespec; /* time of last access */
struct timespec st_mtimespec; /* time of last data modification */
struct timespec st_ctimespec; /* time of last status change */
struct timespec st_birthtimespec; /* time of file creation(birth) */
off_t st_size; /* file size, in bytes */
blkcnt_t st_blocks; /* blocks allocated for file */
blksize_t st_blksize; /* optimal blocksize for I/O */
uint32_t st_flags; /* user defined flags for file */
uint32_t st_gen; /* file generation number */
int32_t st_lspare; /* RESERVED: DO NOT USE! */
int64_t st_qspare[2]; /* RESERVED: DO NOT USE! */
};
- 通过一段代码来验证_DARWIN_FEATURE_64_BIT_INODE是否定义
#include "../inc/apue.h"
int main(int argc, char const *argv[])
{
#if defined(_DARWIN_FEATURE_64_BIT_INODE)
printf("_DARWIN_FEATURE_64_BIT_INODE is defined\n");
#else
printf("_DARWIN_FEATURE_64_BIT_INODE is not defined \n");
#endif
return 0;
}
运行结果
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./stat_test
_DARWIN_FEATURE_64_BIT_INODE is defined
2. 文件类型
2.1 分类
文件分类如下:
文件类型
文件类型可以通过结构体stat中的成员st_mode获取,不同类型对应的值都定义在头文件 /usr/include/sys/stat.h中:
#define S_IFMT 0170000 /* type of file */
#define S_IFIFO 0010000 /* named pipe (fifo) */
#define S_IFCHR 0020000 /* character special */
#define S_IFDIR 0040000 /* directory */
#define S_IFBLK 0060000 /* block special */
#define S_IFREG 0100000 /* regular */
#define S_IFLNK 0120000 /* symbolic link */
#define S_IFSOCK 0140000 /* socket */
#define S_IFWHT 0160000 /* whiteout */
#define S_ISUID 0004000 /* set user id on execution */
#define S_ISGID 0002000 /* set group id on execution */
#define S_ISVTX 0001000 /* save swapped text even after use */
#define S_IRUSR 0000400 /* read permission, owner */
#define S_IWUSR 0000200 /* write permission, owner */
#define S_IXUSR 0000100 /* execute/search permission, owner */
2.2 获取文件类型 - 示例
- code
#include "../inc/apue.h"
int main(int argc, char const *argv[])
{
struct stat buf;
char *ptr;
if (argc != 2)
{
printf("please input a filename\n");
return 0;
}
if (lstat(argv[1], &buf) < 0 )
err_ret("lstat error");
if (S_ISREG(buf.st_mode))
ptr = "regular";
else if (S_ISDIR(buf.st_mode))
ptr = "directory";
else if (S_ISLNK(buf.st_mode))
ptr = "symbolic link";
else
ptr = "unknown mode";
printf("%s\n", ptr);
return 0;
}
早期的unix版本不提供S_ISxxx宏,需要先将st_mode与屏蔽字S_IFMT进行与运算,然后在和S_IFxxx常量进行比较才能得出对应的文件类型。S_ISxxx宏定义如下:
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) /* block special */
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) /* char special */
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) /* directory */
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /* fifo or socket */
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /* regular file */
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) /* symbolic link */
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* socket */
- 运行结果
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc get_file_type.c -o get_file_type
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./get_file_type /dev/zero
unknown mode
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./get_file_type get_file_type.c
regular
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./get_file_type .
directory
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./get_file_type /dev/stdin
symbolic link
使用ls命令查看文件属性,和程序运行结果一致
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -dl get_file_type.c /dev/zero . /dev/stdin
drwxr-xr-x 6 zhanghuamao staff 204 2 11 09:58 .
lr-xr-xr-x 1 root wheel 0 2 11 09:39 /dev/stdin -> fd/0
crw-rw-rw- 1 root wheel 3, 3 2 11 09:39 /dev/zero
-rw-r--r--@ 1 zhanghuamao staff 453 2 11 10:01 get_file_type.c
3. 访问权限
3.1 文件权限
- 可读权限
使用chmod命令去掉文件的r权限,执行cp复制文件时,会报错"cp: file.txt: Permission denied
",说明复制文件需要r权限
zhanghuamaodeMacBook-Pro:test zhanghuamao$ sudo chmod a-r file.txt
zhanghuamaodeMacBook-Pro:test zhanghuamao$ cp file.txt file.txt.bk
cp: file.txt: Permission denied
给文件用户添加可读权限,复制成功
zhanghuamaodeMacBook-Pro:test zhanghuamao$ sudo chmod u+r file.txt
zhanghuamaodeMacBook-Pro:test zhanghuamao$ ls -l file.txt
-rw------- 1 zhanghuamao staff 0 2 11 14:15 file.txt
zhanghuamaodeMacBook-Pro:test zhanghuamao$ cp file.txt file.txt.bk
zhanghuamaodeMacBook-Pro:test zhanghuamao$ ls -l
total 0
-rw------- 1 zhanghuamao staff 0 2 11 14:15 file.txt
-rw------- 1 zhanghuamao staff 0 2 11 14:18 file.txt.bk
3.2 目录权限
- 可读权限
目录要具有可读权限,才能使用ls命令
zhanghuamaodeMacBook-Pro:code zhanghuamao$ sudo chmod a-r test/ ; ls -dl test/;ls -al test/
d-wx--x--x 4 zhanghuamao staff 136 2 11 14:22 test/
ls: : Permission denied
- 可执行权限
目录要具有可执行权限,才能进入
zhanghuamaodeMacBook-Pro:code zhanghuamao$ sudo chmod a-x test/
zhanghuamaodeMacBook-Pro:code zhanghuamao$ ls -dl test/ ; cd test/
drw-r--r-- 2 zhanghuamao staff 68 2 11 11:21 test/
-bash: cd: test/: Permission denied
3.3 用户ID和组ID
-
实际用户ID、实际组ID和有效用户ID、有效组ID
通常,有效用户ID = 实际用户ID,每个文件的所有者有stat中的st_uid指定;
当执行一个程序文件时,进程的有效用户ID通常就是实际用户ID。但是,当设置了特殊标志时,当执行此文件时,进程的有效用户ID = 文件所有者的用户ID
- code
#include "apue.h"
#include <fcntl.h>
int main(int argc, char const *argv[])
{
struct stat buf;
char *ptr;
if (argc != 2)
{
printf("please input a filename\n");
return 0;
}
if (access(argv[1], R_OK) < 0 )
err_ret("access error for %s", argv[1]);
else
printf("read access OK\n");
if (open(argv[1], O_RDONLY) < 0)
err_ret("open error for %s", argv[1]);
else
printf("open for reading OK\n");
return 0;
}
- output
ckt@ubuntu:~/work/unix/code/chapter4$ cc access_test.c -o access_test
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l access_test
-rwxrwxr-x 1 ckt ckt 13419 Feb 12 18:46 access_test
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1129 Sep 19 23:17 /etc/shadow
ckt@ubuntu:~/work/unix/code/chapter4$ ./access_test /etc/shadow
access error for /etc/shadow: Permission denied
open error for /etc/shadow: Permission denied
ckt@ubuntu:~/work/unix/code/chapter4$ sudo chown root access_test
ckt@ubuntu:~/work/unix/code/chapter4$ sudo chmod u+s access_test
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l access_test
-rwsrwxr-x 1 root ckt 13419 Feb 12 18:46 access_test
ckt@ubuntu:~/work/unix/code/chapter4$ ./access_test /etc/shadow
access error for /etc/shadow: Permission denied
open for reading OK
3.4 默认权限:umask
-
查看默认权限
zhanghuamaodeMacBook-Pro:test zhanghuamao$ umask; umask -S
0022
u=rwx,g=rx,o=rx
umask的分数0022指的是“该默认值需要减掉的权限”,umask一共4组数字,第一组是特殊权限用的,后面3组为user、group、other的默认分值
-
文件和目录的默认权限
用户建文件时,默认没有可执行权限,即只有r、w这两个选项,默认权限为-rw-rw-rw
新建文件时默认权限计算方式:(-rwxrw-rw-) - (------w--w) = -rw-r--r--
zhanghuamaodeMacBook-Pro:test zhanghuamao$ touch test ; ls -l
total 0
-rw-r--r-- 1 zhanghuamao staff 0 2 11 15:03 test
用户创建目录时,由于x与是否进入目录有关,因此默认3个权限都开放:-rwxrwxrwx
新建目录时默认权限计算方式:(-rwxrwxrwx) - (------w--w) = -rwxr-xr-x
zhanghuamaodeMacBook-Pro:test zhanghuamao$ mkdir dir; ls -l
total 0
drwxr-xr-x 2 zhanghuamao staff 68 2 11 15:06 dir
-rw-r--r-- 1 zhanghuamao staff 0 2 11 15:03 test
3.5 umask函数
-
函数原型
mode_t umask(mode_t mask); , 其中的参数mask的值定义在/usr/include/sys/stat.h中:
#define S_IRUSR __S_IREAD /* Read by owner. */
#define S_IWUSR __S_IWRITE /* Write by owner. */
#define S_IXUSR __S_IEXEC /* Execute by owner. */
/* Read, write, and execute by owner. */
#define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC)
#define S_IRGRP (S_IRUSR >> 3) /* Read by group. */
#define S_IWGRP (S_IWUSR >> 3) /* Write by group. */
#define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */
/* Read, write, and execute by group. */
#define S_IRWXG (S_IRWXU >> 3)
#define S_IROTH (S_IRGRP >> 3) /* Read by others. */
#define S_IWOTH (S_IWGRP >> 3) /* Write by others. */
#define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */
/* Read, write, and execute by others. */
#define S_IRWXO (S_IRWXG >> 3)
- code
#include "apue.h"
#include <fcntl.h>
#define RWRWRW (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
int main(int argc, char const *argv[])
{
umask(0);
if (creat("test", RWRWRW) < 0 )
err_sys("create error for test");
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (creat("test2", RWRWRW) < 0 )
err_sys("create error for test2");
return 0;
}
- output
ckt@ubuntu:~/work/unix/code/chapter4$ cc umask_test.c -o umask_test
ckt@ubuntu:~/work/unix/code/chapter4$ umask
0002
ckt@ubuntu:~/work/unix/code/chapter4$ ./umask_test
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test*
-rw-rw-rw- 1 ckt ckt 0 Feb 12 21:53 test
-rw------- 1 ckt ckt 0 Feb 12 21:53 test2
ckt@ubuntu:~/work/unix/code/chapter4$ umask
0002
3.6 chmod函数
- code
#include "apue.h"
int main(int argc, char const *argv[])
{
struct stat statbuf;
if (stat("test", &statbuf) < 0 )
err_sys("stat error for test");
if (chmod("test", (statbuf.st_mode & ~S_IWGRP) | S_IXGRP) < 0 )
err_sys("chmod error for test");
if (chmod("test2", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0 )
err_sys("chmod error for test2");
return 0;
}
- output
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test*
-rw-rw-rw- 1 ckt ckt 0 Feb 13 00:17 test
-rw------- 1 ckt ckt 0 Feb 13 00:17 test2
ckt@ubuntu:~/work/unix/code/chapter4$ cc chmod_test.c -o chmod_test
ckt@ubuntu:~/work/unix/code/chapter4$ ./chmod_test
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test*
-rw-r-xrw- 1 ckt ckt 0 Feb 13 00:17 test
-rw-rw---- 1 ckt ckt 0 Feb 13 00:17 test2
3.7 chown函数
- code
#include "apue.h"
int main(int argc, char const *argv[])
{
if (chown("test", getuid(), getgid()) < 0 )
err_sys("chmod error for test");
return 0;
}
- output
ckt@ubuntu:~/work/unix/code/chapter4$ cc chown_test.c -o chown_test
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test
-rw------- 1 ckt ckt 0 Feb 13 00:17 test
ckt@ubuntu:~/work/unix/code/chapter4$ sudo ./chown_test
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l test
-rw------- 1 root root 0 Feb 13 00:17 test
4. 文件系统
4.1 硬链接和软链接对比
在link目录下,使用link命令给test目录下的file文件创建一个硬链接hard_link,file和hard_link的inode相同,都为1000760
zhanghuamaodeMacBook-Pro:link zhanghuamao$ link ../test/file hard_link
zhanghuamaodeMacBook-Pro:link zhanghuamao$ ls -li hard_link ../test/file
1000760 -rw-r--r-- 2 zhanghuamao staff 0 2 12 11:36 ../test/file
1000760 -rw-r--r-- 2 zhanghuamao staff 0 2 12 11:36 hard_link
使用ls -li查看link和test目录的inode号,分别为1000766、100068
zhanghuamaodeMacBook-Pro:code zhanghuamao$ ls -li
1000766 drwxr-xr-x 2 zhanghuamao staff 68 2 12 11:37 link
1000688 drwxr-xr-x 3 zhanghuamao staff 102 2 12 11:36 test
再使用ln -s命令给file文件创建一个软链接soft_link,查看soft_link的inode号为1000805,和file的inode号不一样。
zhanghuamaodeMacBook-Pro:link zhanghuamao$ ln -s ../test/file soft_link
zhanghuamaodeMacBook-Pro:link zhanghuamao$ ls -il ../test/file soft_link
1000760 -rw-r--r-- 2 zhanghuamao staff 0 2 12 11:36 ../test/file
1000805 lrwxr-xr-x 1 zhanghuamao staff 12 2 12 11:40 soft_link -> ../test/
往hard_link文件中添加内容"add by hard link",使用cat命令查看soft_link和file文件,内容都同步更新了。
zhanghuamaodeMacBook-Pro:link zhanghuamao$ cat soft_link ../test/file
add by hard link
add by hard link
删除file文件,再次使用cat命令查看soft_link和hard_link文件,soft_link提示"No such file or directory",而hard_link文件仍然存在。
zhanghuamaodeMacBook-Pro:link zhanghuamao$ rm ../test/file
zhanghuamaodeMacBook-Pro:link zhanghuamao$ cat soft_link hard_link
cat: soft_link: No such file or directory
add by hard link
创建硬链接后,inode和bloack data示意图
硬链接
当删除file文件时,hard_link仍然可以通过编号为1000760的inode访问文件内容
硬链接 - 删除file文件后创建软链接后,inode和bloack data示意图
软链接当删除file文件后,soft_link无法再通过test目录的inode号访问file文件
软链接 - 删除file文件4.2 获取文件的硬链接
- code
#include "../inc/apue.h"
int main(int argc, char const *argv[])
{
struct stat buf;
char *ptr;
if (argc != 2)
{
printf("please input a filename\n");
return 0;
}
if (lstat(argv[1], &buf) < 0 )
err_ret("lstat error");
printf("The hard link count of %s : %d\n", argv[1], buf.st_nlink);
return 0;
}
- output
先ls -il查看hard_link文件的链接数为3
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il ../link/hard_link*
1005313 -rw-r--r-- 3 zhanghuamao staff 0 2 12 16:20 ../link/hard_link
1005313 -rw-r--r-- 3 zhanghuamao staff 0 2 12 16:20 ../link/hard_link1
1005313 -rw-r--r-- 3 zhanghuamao staff 0 2 12 16:20 ../link/hard_link2
运行link_text程序查看hard_link文件的链接数,和ls -il得到的结果一致,都为3
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc link_text.c -o link_text
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./link_text ../link/hard_link
The hard link count of ../link/hard_link : 3
4.3 link函数
- code
#include "../inc/apue.h"
int main(int argc, char const *argv[])
{
struct stat buf;
char *ptr;
if (argc != 3)
{
printf("please input a filename\n");
return 0;
}
link(argv[1], argv[2]);
return 0;
}
- output
运行程序my_link创建my_link.c的硬链接文件my_link_hard_link.txt
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc my_link.c -o my_link
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls
get_file_type link_text my_link stat_test
get_file_type.c link_text.c my_link.c stat_test.c
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./my_link my_link.c my_link_hard_link.txt
运行完成后使用ls -il查看,my_link.c和my_link_hard_link.txt的inode号一样都为1006798
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il my*
1006809 -rwxr-xr-x 1 zhanghuamao staff 13596 2 12 16:56 my_link
1006798 -rw-r--r--@ 2 zhanghuamao staff 275 2 12 16:55 my_link.c
1006798 -rw-r--r--@ 2 zhanghuamao staff 275 2 12 16:55 my_link_hard_link.txt
4.4 unlink函数
- code
#include "../inc/apue.h"
int main(int argc, char const *argv[])
{
struct stat buf;
char *ptr;
if (argc != 2)
{
printf("please input a filename\n");
return 0;
}
unlink(argv[1]);
return 0;
}
- output
运行程序my_unlink取消掉之前创建的my_link_hard_link.txt
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc my_unlink.c -o my_unlink
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./my_unlink my_link_hard_link.txt
已经没有my_link_hard_link.txt 这支文件了
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il my*
1006809 -rwxr-xr-x 1 zhanghuamao staff 13596 2 12 16:56 my_link
1006798 -rw-r--r--@ 1 zhanghuamao staff 210 2 12 17:05 my_link.c
1006904 -rwxr-xr-x 1 zhanghuamao staff 13596 2 12 17:06 my_unlink
1006865 -rw-r--r--@ 1 zhanghuamao staff 203 2 12 17:06 my_unlink.c
4.5 rename函数
- code
#include "../inc/apue.h"
int main(int argc, char const *argv[])
{
struct stat buf;
char *ptr;
if (argc != 3)
{
printf("please input a filename\n");
return 0;
}
rename(argv[1], argv[2]);
return 0;
}
- output
运行程序my_mv创建硬链接前,先查看当前已使用inode个数为793518
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc my_mv.c -o my_mv
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ df .
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1 487686144 65661544 421512600 14% 793518 4294173761 0% /
运行程序my_mv创建my_mv.c的硬链接my_mv_rename.txt,查看它们的inode号都为1007929,并且已使用inode个数和创建硬链接前一样。
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./my_mv my_mv.c my_mv_rename.txt
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ df .
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1 487686144 65663336 421510808 14% 793518 4294173761 0% /
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il my_m*
1007936 -rwxr-xr-x 1 zhanghuamao staff 13596 2 12 17:37 my_mv
1007929 -rwxr-xr-x 1 zhanghuamao staff 212 2 12 17:37 my_mv.c
1007929 -rwxr-xr-x 1 zhanghuamao staff 212 2 12 17:37 my_mv_rename.txt
4.6 symlink函数
- code
#include "../inc/apue.h"
int main(int argc, char const *argv[])
{
struct stat buf;
char *ptr;
if (argc != 3)
{
printf("please input a filename\n");
return 0;
}
symlink(argv[1], argv[2]);
return 0;
}
- output
在运行程序my_ln创建软链接前,先使用df命令查看当前已用inode个数为793532
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc my_ln.c -o my_ln
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ df .
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1 487686144 65664040 421510104 14% 793532 4294173747 0% /
运行程序my_ln创建my_ln.c的软链接my_ln_soft_link.txt,查看它们的inode号分别是1008145和1008163
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./my_ln my_ln.c my_ln_soft_link.txt
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -il my_ln*
1008156 -rwxr-xr-x 1 zhanghuamao staff 13604 2 12 17:50 my_ln
1008145 -rw-r--r--@ 1 zhanghuamao staff 213 2 12 17:49 my_ln.c
1008163 lrwxr-xr-x 1 zhanghuamao staff 7 2 12 17:51 my_ln_soft_link.txt -> my_ln.c
再次使用df命令查看当前已用inode个数为793533,比运行程序my_ln前,少了一个inode号
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ df .
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1 487686144 65663920 421510224 14% 793533 4294173746 0% /
将my_ln.c删除,再去cat my_ln_soft_link.txt,提示错误"cat: my_ln_soft_link.txt: No such file or directory"
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ rm my_ln.c ; cat my_ln_soft_link.txt
cat: my_ln_soft_link.txt: No such file or directory
4.7 时间参数
Unix中一共有3个时间参数,这3个值被记录在stat成员变量中:
struct timespec st_atimespec; /* time of last access */
struct timespec st_mtimespec; /* time of last data modification */
struct timespec st_ctimespec; /* time of last file status change */
-
modification time(mtime)
当修改文件内容时,mtime会更新,使用ls -l命令查看的时间就是mtime
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l ../chapter2/limits_test.c
-rwxr--r-- 1 ckt ckt 179 Jan 15 22:10 ../chapter2/limits_test.c
-
acess time(atime)
当文件内容被取用时,就会更新atime。例如,使用cat去读取文件时。
使用命令ls -l --time=atime可以查看atime
ckt@ubuntu:~/work/unix/code/chapter4$ cat ../chapter2/limits_test.c
cat内容省略
ckt@ubuntu:~/work/unix/code/chapter4$ls -l ../chapter2/limits_test.c
-rwxr--r-- 1 ckt ckt 179 Jan 15 22:10 ../chapter2/limits_test.c
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l --time=atime ../chapter2/limits_test.c
-rwxr--r-- 1 ckt ckt 179 Feb 13 01:00 ../chapter2/limits_test.c
ckt@ubuntu:~/work/unix/code/chapter4$ date
Mon Feb 13 01:01:12 PST 2017
-
status time(ctime)
当文件的状态改变时,就会更新这个时间,例如:权限与属性被更改了
使用命令ls -l --time=ctime可以查看ctime
ckt@ubuntu:~/work/unix/code/chapter4$ chmod 644 ../chapter2/limits_test.c
ckt@ubuntu:~/work/unix/code/chapter4$ ls -l --time=ctime ../chapter2/limits_test.c
-rw-r--r-- 1 ckt ckt 179 Feb 13 01:03 ../chapter2/limits_test.c
4.8 打印设备ID
- code
#include "apue.h"
#include <sys/sysmacros.h>
int main(int argc, char const *argv[])
{
struct stat buf;
if (argc != 2)
{
printf("please input a filename\n");
return 0;
}
if (lstat(argv[1], &buf) < 0 )
err_ret("lstat error");
printf("dev = %d / %d ", major(buf.st_dev), minor(buf.st_dev));
if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode))
{
printf(", rdev = %d / %d ", major(buf.st_rdev), minor(buf.st_rdev));
}
printf("\n");
return 0;
}
- output
ckt@ubuntu:~/work/unix/code/chapter4$ cc dev_test.c -o dev_test
ckt@ubuntu:~/work/unix/code/chapter4$ ./dev_test /dev/tty1
dev = 0 / 5 , rdev = 4 / 1
ckt@ubuntu:~/work/unix/code/chapter4$ ./dev_test dev_test
dev = 8 / 17
5. 目录操作
5.1 mkdir函数
- code
#include "apue.h"
#define RWXRXRX (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
int main(int argc, char const *argv[])
{
if (argc != 2)
{
printf("please input a filename\n");
return 0;
}
if (mkdir(argv[1], RWXRXRX) < 0 )
err_ret("mkdir error");
return 0;
}
- output
ckt@ubuntu:~/work/unix/code/chapter4$ cc mkdir_test.c -o mkdir_test
ckt@ubuntu:~/work/unix/code/chapter4$ ./mkdir_test 222
ckt@ubuntu:~/work/unix/code/chapter4$ ls -dl 222
drwxr-xr-x 2 ckt ckt 4096 Feb 15 01:14 222
5.2 rmdir函数
- code
#include "apue.h"
int main(int argc, char const *argv[])
{
if (argc != 2)
{
printf("please input a filename\n");
return 0;
}
if (rmdir(argv[1]) < 0 )
err_ret("rmdir error");
return 0;
}
- output
ckt@ubuntu:~/work/unix/code/chapter4$ cc rmdir_test.c -o rmdir_test
ckt@ubuntu:~/work/unix/code/chapter4$ ./rmdir_test 222/
ckt@ubuntu:~/work/unix/code/chapter4$ ls -dl 222
ls: cannot access 222: No such file or directory
5.3 chdir函数
- code
#include "apue.h"
int main(int argc, char const *argv[])
{
if (chdir("/home") < 0 )
err_ret("chdir error");
printf("chdir to /home succeeded\n");
printf("current path = %s\n", get_current_dir_name());
return 0;
}
-
output
运行程序chdir_test后,shell显示的当前目录并没有改变,这是因为每个程序运行在独立的进程中,shell的当前工作目录并不会随着程序调用chdir而改变。但是,chdir_test程序通过调用get_current_dir_name函数,可以将当前目录名称打印出来,由此可以证明chdir已经生效
ckt@ubuntu:~/work/unix/code/chapter4$ cc chdir_test.c -o chdir_test
ckt@ubuntu:~/work/unix/code/chapter4$ ./chdir_test
chdir to /home succeeded
current path = /home
5.4 读目录
- code
#include "../inc/apue.h"
#include <dirent.h>
int main(int argc, char const *argv[])
{
DIR *dirp;
struct dirent *dp;
dirp = opendir("../");
if (dirp == NULL)
return 0;
while ((dp = readdir(dirp)) != NULL)
{
printf("%s\n", dp->d_name);
}
return 0;
}
- output
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ cc readdir_test.c -o readdir_test
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ./readdir_test
.
..
chapter3
chapter4
file1
file2
inc
link
test
zhanghuamaodeMacBook-Pro:chapter4 zhanghuamao$ ls -l ../
total 0
drwxr-xr-x 17 zhanghuamao staff 578 1 22 21:55 chapter3
drwxr-xr-x 21 zhanghuamao staff 714 2 15 23:18 chapter4
-rw-r--r-- 1 zhanghuamao staff 0 2 15 23:01 file1
-rw-r--r-- 1 zhanghuamao staff 0 2 15 23:01 file2
drwxr-xr-x 4 zhanghuamao staff 136 1 21 10:06 inc
drwxr-xr-x 8 zhanghuamao staff 272 2 12 16:25 link
drwxr-xr-x 2 zhanghuamao staff 68 2 12 11:43 test
参考
- UNIX 环境高级编程 第3版
- undefined reference to `major'