「Linux 系统编程」link 与 unlink

link() 系统调用用于 创建一个已存在文件的硬链接(hard link)。其函数原型如下:

1
2
3
#include <unistd.h>

int link(const char *oldpath, const char *newpath);
  • oldpath:已存在的文件路径。
  • newpath:要创建的硬链接路径。

硬链接实际上是为同一个 inode 创建了另一个目录项(dentry)。这意味着无论通过哪个链接访问,操作的都是同一个文件数据。硬链接数(可通过 ls -l 查看)就是指指向该 inode 的目录项数量。


unlink() 用于 删除一个文件的目录项(dentry),其函数原型为:

1
2
3
#include <unistd.h>

int unlink(const char *pathname);
  • 调用 unlink 后,文件的 硬链接数减 1
  • 只有当硬链接数变为 0,且没有进程打开该文件时,文件所占用的磁盘空间才会被释放。
  • 即使硬链接数为 0,只要还有进程在使用该文件,文件内容就不会被立即删除,直到所有进程关闭该文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char* argv[]){
if(argc != 3){
printf("ERROR: format must be file_1 file_2\n");
return 1;
}

// 给 file_1 创建一个硬链接 file_2
link(argv[1], argv[2]);

// 删除 file_1 的目录项
unlink(argv[1]);

return 0;
}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

int main(){
char* str = "test of unlink\n";

// 创建临时文件
int fd = open("marisa.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if(fd < 0){
perror("open temp error");
return 1;
}

// 立即 unlink 使临时文件具备被释放条件,文件不会被立刻删除
if(unlink("marisa.txt") == -1){
perror("unlink error");
return 1;
}

// 写入操作
if(write(fd, str, strlen(str)) == -1){
perror("write error");
return 1;
}

// 加入使得程序崩溃的操作
// str[1] = 'T';

printf("file has been written\n");
getchar(); // 阻塞

close(fd);

return 0;
}

即使程序在写入过程中崩溃,系统也会在进程结束时自动清理该临时文件。



2. 隐式回收机制

Linux 系统会在进程结束时自动进行 隐式回收(Implicit Reclaim),包括:

  • 关闭所有该进程打开的文件描述符
  • 释放进程所占用的内存空间
  • 释放其他内核资源(如信号量、消息队列等)

这个机制确保了 即使程序员忘记在代码中释放资源,系统也不会永久泄露资源。例如,如果没有显式关闭文件描述符,隐式回收会在进程结束时自动关闭它们,避免文件描述符耗尽的问题。

但是在开发过程中,还是尽量不要依赖隐式回收机制,推荐使用 close(fd) 关闭文件描述符的更加保险的方式。



除了硬链接,Linux 还支持 符号链接(symbolic link,或称软链接)。符号链接是一个特殊的文件,其内容是指向另一个文件或目录的路径。

创建符号链接的函数是 symlink()

1
2
3
#include <unistd.h>

int symlink(const char *target, const char *linkpath);
  • target:源文件路径。
  • linkpath:要创建的符号链接路径。

使用 unlink() 删除符号链接时,删除的是这个符号链接文件本身,不会删除符号链接所指向的目标文件或目录。

特性 硬链接 符号链接
inode 与源文件相同 不同
跨文件系统 不支持 支持
链接目录 不允许(除.和…) 允许
删除源文件 不影响链接(数据仍在) 链接会失效(悬空链接)

「Linux 系统编程」link 与 unlink
https://marisamagic.github.io/2025/08/27/20250827/
作者
MarisaMagic
发布于
2025年8月27日
许可协议