16、符号链接
硬链接的局限是:
- 硬链接和文件必须在同一个文件系统之下。
b. 只有超级用户才能够创建目录的硬链接。
一个目录的软链接(也就是符号链接)就没有这些限制,它可以由任何人创建,可以创建目录或者文件的软链接,以及在不同文件系统上创建某个文件或者目录的软链接。软链接是不能用 rmdir
来删除的,因为软链接是一个文件,不是目录。用 rm -r
也是只删除了这个软链接本身。
当使用以名字引用一个处理文件的函数时,应当知道该函数是否能够处理符号连接。也就是这个函数是否跟随符号连接到达它所连接的文件,然后对被连接的文件进行正确地操作,而不是指向文件的链接本身。如若该函数可以处理符号连接,则传递给该函数的符号链接的路径名参数,会最终引用到由符号连接指向的文件;否则,只是引用到路径参数引用的链接本身,而不是由该链接指向的文件。这里列出了如果传递的路径是一个符号链接的时候,哪些函数会沿着符号链接跟踪到相应的文件(即对符号链接进行处理),或者不跟踪(即不处理符号链接)。
各种函数对符号链接的处理
+-------------------------------------------------------------------+
| Function | Does not follow symbolic link | Follows symbolic link |
|----------+--------------------------------+-----------------------|
| access | | • |
|----------+--------------------------------+-----------------------|
| chdir | | • |
|----------+--------------------------------+-----------------------|
| chmod | | • |
|----------+--------------------------------+-----------------------|
| chown | • | • |
|----------+--------------------------------+-----------------------|
| creat | | • |
|----------+--------------------------------+-----------------------|
| exec | | • |
|----------+--------------------------------+-----------------------|
| lchown | • | |
|----------+--------------------------------+-----------------------|
| link | | • |
|----------+--------------------------------+-----------------------|
| lstat | • | |
|----------+--------------------------------+-----------------------|
| open | | • |
|----------+--------------------------------+-----------------------|
| opendir | | • |
|----------+--------------------------------+-----------------------|
| pathconf | | • |
|----------+--------------------------------+-----------------------|
| readlink | • | |
|----------+--------------------------------+-----------------------|
| remove | • | |
|----------+--------------------------------+-----------------------|
| rename | • | |
|----------+--------------------------------+-----------------------|
| stat | | • |
|----------+--------------------------------+-----------------------|
| truncate | | • |
|----------+--------------------------------+-----------------------|
| unlink | • | |
+-------------------------------------------------------------------+
例如 open
会 follow
一个 symbolic link.
如果一个 symbolic
指向一个不存在的文件,那么 open
的时候会提示没有这样的文件,如果大家不清楚 symbolic link
的工作原理,可能会被这种现象所困惑,举例如下:
$ ln -s /no/such/file myfile create a symbolic link
$ ls myfile
myfile ls says it's there
$ cat myfile so we try to look at it
cat: myfile: No such file or directory
$ ls -l myfile try -l option
lrwxrwxrwx 1 sar 13 Jan 22 00:26 myfile -> /no/such/file
我们好像看到了一个 myfile
的文件,但是 ls
的时候却提示没有这个文件。实际上, myfile
是一个符号链接,这个符号链接所指向的文件 /no/such/file
根本就不存在。
译者注
原文参考
17、symlink和readlink函数
symlink
函数创建一个符号连接。声明如下:
#include <unistd.h>
int symlink(const char *actualpath, const char *sympath);
返回:如果成功返回0,如果错误返回1(实际值一般为-1)。
该函数创建了一个指向 actualpath
的新目录项 sympath
,在创建此符号连接时,并不要求 actualpath
已经存在。并且, actualpath
和 sympath
不必位于同一文件系统中。
因为 open
函数跟随符号连接,所以需要有一种方法打开该连接本身,并读取该连接中的名字。 readlink
函数提供了这种功能。声明如下:
#include <unistd.h>
ssize_t readlink(const char* restrict pathname, char *restrict buf, size_t bufsize);
返回:如果成功返回读取的字节数目;错误返回1(实际值一般为-1)。
此函数组合了 open
, read
和 close
的所有操作。如果成功,则返回读入 buf
的字节数。在 buf
中返回的符号连接的内容不以 null
字符终止。
译者注
原文参考
18、文件的三种时间
文件有三种和时间相关的属性:
-
atime
:访问时间。记录最后一次,例如执行exec
,或者read
,或者创建文件(非截断创建)的时候的时间。 -
mtime
:内容改变时间。记录最后一次文件内容改变的时间。 -
ctime
:状态改变时间。记录最后一次文件索引信息改变的时间,例如:文件名称,大小,链接数目,等一般在stat
中的信息的改变。
这里,内容改变时间( st_mtime
)和状态改变时间( st_ctime
)是不同的:内容改变时间是文件内容最后一次被修改的时间;状态改变时间是该文件的 i 节点最后一次被修改的时间。
因为有很多操作,它们只影响到i节点,但并没有更改文件的实际内容:文件的存取许可权、用户 ID
、连接数等等。而i节点中的所有信息都是与文件的实际内容分开存放的,所以,除了文件数据改变时间以外,还需要状态改变时间。
另外,注意,系统并不保存对一个 i节点的最后一次存取时间,所以 access
和 stat
函数并不更改这三个时间中的任一个。下表给出之前讲过的各种函数对这三个时间的作用。
各种函数对access,modification,以及changed-status时间的影响
+--------------------------------------------------------------------------------------------------------------------------------------+
| | Referenced file or | | | |
| Function | directory | Parent directory of referenced file or directory| Section| Note |
| |---------------------------+-------------------------------------------------| | |
| | a | m | c | a | m | c | | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| chmod, fchmod | | | • | | | | 4.9 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| chown, fchown | | | • | | | | 4.11 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| creat | • | • | • | | • | • | 3.4 | O_CREAT new file |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| creat | | • | • | | | | 3.4 | O_TRUNC existing file |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| exec | • | | | | | | 8.10 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| lchown | | | • | | | | 4.11 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| link | | | • | | • | • | 4.15 | parent of second argument|
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| mkdir | • | • | • | | • | • | 4.20 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| mkfifo | • | • | • | | • | • | 15.5 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| open | • | • | • | | • | • | 3.3 | O_CREAT new file |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| open | | • | • | | | | 3.3 | O_TRUNC existing file |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| pipe | • | • | • | | | | 15.2 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| read | • | | | | | | 3.7 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| remove | | | • | | • | • | 4.15 | remove file = unlink |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| remove | | | | | • | • | 4.15 | remove directory = rmdir |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| rename | | | • | | • | • | 4.15 | for both arguments |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| rmdir | | | | | • | • | 4.20 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| truncate, ftruncate| | • | • | | | | 4.13 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| unlink | | | • | | • | • | 4.15 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| utime | • | • | • | | | | 4.19 | |
|--------------------+---------+---------+-------+----------------+----------------+---------------+--------+--------------------------|
| write | | • | • | | | | 3.8 | |
+--------------------------------------------------------------------------------------------------------------------------------------+
译者注
原文参考
19、 utime
函数
我们可以使用 utime
函数来修改文件的访问时间和内容修改时间。其声明如下:
#include <utime.h>
int utime(const char *pathname, const struct utimbuf *times);
返回:如果成功返回0,如果错误返回1(其值一般为-1)。
这里, utimbuf
结构定义如下:
struct utimbuf {
time_t actime; /*access time*/
time_t modtime; /*modification time*/
};
此结构中的两个时间值是日历时间(即1970年1月1日,00:00:00至今的秒数)。此函数的操作以及执行它所要求的优先权取决于参数 times
是否为 NULL
。
- 如果
times
是空指针,则存取时间和修改时间两者都设置为当前时间。此操作必须满足下列两条件之一:进程的有效用户ID
必须等于该文件的所有者ID
;进程对该文件必须具有写许可权。 - 如果
times
非空,则存取时间和修改时间被设置为times
所指向的结构中的值。此时,进程的有效用户ID
必须等于该文件的所有者ID
,或者进程必须是一个超级用户进程。对文件只具有写许可权是不够的。
注意,我们不能对更改状态时间 st_ctime
指定一个值,当调用 utime
函数时,此字段被自动更新。
译者注
原文参考
20、 mkdir
和 rmdir
函数
mkdir
函数可以创建一个目录,其声明如下:
#include <sys/stat.h>
int mkdir(const char *pathname, mode_t mode);
返回:如果成功返回0,如果错误返回1(其值一般为-1)。
空目录通过函数 rmdir
被删除。这里空目录表示目录里面只有 .
和 ..
目录项。这个函数声明如下:
#include <unistd.h>
int rmdir(const char *pathname);
返回:如果成功返回0,如果错误返回1(其值一般为-1)。
如果此调用使目录的连接计数变成0,并且也没有其他进程打开此目录,则释放此目录所占空间。如果在连接计数达到0时,有一个或几个进程打开了此目录,则在此函数返回前删除最后一个连接及 .
和 ..
项,另外,在此目录中不能再创建新文件。在最后一个进程关闭它之前并不释放此目录(即使某些进程打开该目录,这些进程在此目录下也不能执行其他操作,因为为使rmdir函数成功执行,该目录必须为空)。