linux/macos下用symlink()和link()创建软硬链接:symlink(目标, 链接名)支持相对/绝对路径且目标可不存在;link(已有文件, 新链接名)要求目标存在、同文件系统、非目录,失败返回-1并设errno。

Linux/macOS 下用 symlink() 和 link() 创建符号链接与硬链接
在 C++ 中创建链接不靠标准库,而是调用系统 API。Linux 和 macOS 都提供 POSIX 接口:symlink() 做符号链接,link() 做硬链接。Windows 不支持原生 link()(硬链接需管理员权限 + CreateHardLink()),所以跨平台代码要条件编译。
关键点:两个函数都操作路径字符串,不涉及 C++ 流或文件对象;成功返回 0,失败返回 -1 并设置 errno(比如 EEXIST 表示目标已存在,EPERM 表示权限不足)。
-
symlink("target.txt", "link_to_target"):第一个参数是目标路径(可相对/绝对),第二个是链接自身路径 -
link("existing.txt", "hard_link_to_existing"):两个参数都必须是已存在的普通文件的绝对或相对路径;不能跨文件系统 - 硬链接不能指向目录(Linux 默认禁止,会报
EPERM),符号链接可以 - 符号链接的目标路径在创建时不校验是否存在;硬链接的目标必须真实存在且是普通文件
Windows 上创建硬链接要用 CreateHardLink(),符号链接需额外权限
Windows 的硬链接和符号链接都是 NTFS 特性,但默认受限。创建硬链接只需调用 CreateHardLink(),但符号链接(CreateSymbolicLink())要求进程启用 SE_CREATE_SYMBOLIC_LINK_PRIVILEGE 权限——普通用户程序默认没有,会失败并返回 ERROR_PRIVILEGE_NOT_HELD。
常见错误现象:CreateSymbolicLink() 返回 0 且 GetLastError() 是 1314,就是权限问题。解决办法要么以管理员身份运行,要么在 manifest 中声明权限(不推荐普通工具这么做)。
- 硬链接只支持文件,不支持目录;符号链接支持文件和目录(需传
SYMBOLIC_LINK_FLAG_DIRECTORY) -
CreateHardLink()第二个参数是新链接路径,第一个是已有文件路径,顺序和 POSIXlink()一致 - 路径字符串建议用宽字符版本(
CreateHardLinkW),避免编码问题;传入路径需为绝对路径或当前驱动器下的有效相对路径 - 所有 Windows 链接 API 都要求目标文件系统为 NTFS;FAT32/exFAT 不支持
判断一个路径是否为符号链接:用 lstat() 而非 stat()
想确认某个路径是不是符号链接,不能用 stat() —— 它会自动解引用,返回目标文件的属性。必须用 lstat()(POSIX)或 GetFileAttributesEx()(Windows)来读取链接自身的元数据。
在 Linux/macOS 上:lstat(path, &sb) == 0 && S_ISLNK(sb.st_mode) 才表示它是符号链接;硬链接无法通过元数据区分,因为所有硬链接共享同一个 inode,st_ino 和 st_nlink 字段反映的是文件本身而非“链接实体”。
-
lstat()对硬链接和普通文件返回结果一致;只有符号链接会被识别出来 - Windows 下用
GetFileAttributesEx(path, GetFileExInfoStandard, &data),然后检查data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT - 注意:符号链接可能损坏(目标被删),
lstat()仍能成功,但readlink()会失败;硬链接只要有一个存在,文件数据就还在
删除链接时的陷阱:硬链接删的是“引用”,符号链接删的是“链接本身”
unlink() 或 std::filesystem::remove() 删除符号链接时,只删链接文件,不影响目标;但删除硬链接,只是减少该文件的链接计数(st_nlink),只有当计数降为 0 且无进程打开它时,系统才真正回收磁盘空间。
这意味着:硬链接不是“副本”,而是同一份数据的多个入口;误删一个硬链接不会丢数据,但误删最后一个硬链接 + 忘记关闭打开句柄,可能导致文件残留(unlinked but open)。
- 用
stat()查看st_nlink可知还有几个硬链接存在(对普通文件有意义,对符号链接恒为 1) - 符号链接可被
readlink()读出目标路径;硬链接无法反查“谁链接了我” - 备份工具、
rsync -a默认保留符号链接(作为链接复制),但通常把硬链接展开成独立文件——除非显式加--hard-links
硬链接的本质是 inode 引用,符号链接是路径字符串;理解这点,才能避开“为什么删了链接文件,目标还占着空间”或“为什么改了符号链接目标,原来的内容就变了”这类困惑。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











