linux/macos下创建链接需用posix系统调用:link()创建硬链接(要求源存在、同文件系统、目标不存在),symlink()创建符号链接(源可悬空、目标不可存在、路径相对链接所在目录解析);windows则须用createhardlinkw()和createsymboliclinkw()等winapi,且权限与跨卷限制更严格。

Linux/macOS 下用 link() 和 symlink() 创建链接
C++ 本身不提供跨平台的链接创建接口,实际依赖系统调用。在 Linux 和 macOS 上,必须用 POSIX 系统函数:link() 创建硬链接,symlink() 创建软链接(符号链接)。这两个函数都在 <unistd.h></unistd.h> 中声明,返回 -1 表示失败,错误码存于 errno。
常见错误现象:调用后无反应但链接没生成——大概率是权限不足、目标路径已存在、源文件不存在,或跨文件系统(硬链接不支持跨文件系统)。
-
link("source.txt", "hardlink.txt"):要求source.txt必须存在且可访问;hardlink.txt不能已存在;两个路径需在同一挂载点 -
symlink("source.txt", "symlink.txt"):源路径可以不存在(符号链接允许悬空);目标路径也不能已存在;路径是相对于链接所在目录解析的(不是当前工作目录) - 失败时检查
errno:比如EEXIST(目标已存在)、EPERM(权限不够)、EXDEV(硬链接跨设备)
Windows 下用 CreateHardLinkW() 和 CreateSymbolicLinkW()
Windows 不支持 POSIX 的 link()/symlink(),得用 WinAPI。硬链接仅限文件(不能对目录),且目标必须在同一个 NTFS 卷上;符号链接则需管理员权限(除非启用了“开发者模式”或使用 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)。
注意:这些函数是宽字符版,路径必须为 wchar_t*,推荐用 std::wstring 或 L"..." 字面量。ANSI 版本已废弃,不要用 CreateHardLinkA()。
-
CreateHardLinkW(L"hardlink.txt", L"source.txt", nullptr):成功返回非零值;失败返回0,用GetLastError()查错 -
CreateSymbolicLinkW(L"symlink.txt", L"source.txt", SYMBOLIC_LINK_FLAG_FILE):第三个参数指定链接类型:SYMBOLIC_LINK_FLAG_FILE或SYMBOLIC_LINK_FLAG_DIRECTORY - 若提示
ERROR_PRIVILEGE_NOT_HELD,说明没管理员权限或未启用免提权创建(Windows 10 1703+ 可通过组策略或fsutil behavior set symlinkevaluation配置)
跨平台封装要注意路径和权限语义差异
硬链接和软链接在不同系统上行为不一致,强行封装成统一接口容易出错。比如:
- 硬链接在 Windows 上不能指向目录;Linux/macOS 也不支持跨文件系统——但错误码不同(
EXDEVvsERROR_NOT_SAME_DEVICE) - 软链接路径解析规则不同:Linux 下
symlink("a/b", "l")在/x目录下读取时,会尝试打开/x/a/b;Windows 默认按绝对路径处理,除非显式加\?前缀或使用相对路径语法(如.) - 权限检查时机不同:Linux 创建软链接不检查源是否存在;Windows 的
CreateSymbolicLinkW()也不检查,但后续访问时才报错
建议按平台条件编译,而不是试图抽象出一个“通用 link 函数”。否则调试时会卡在路径拼接、宽窄字符转换、权限弹窗等边缘问题上。
用 std::filesystem(C++17)能简化但仍有坑
C++17 引入了 std::filesystem::create_hard_link() 和 std::filesystem::create_symlink(),看起来跨平台,但底层仍是调用系统 API,行为差异照旧。而且它默认抛异常,不返回错误码,对错误处理不透明。
- 必须确保编译器开启 C++17(如
-std=c++17),并链接-lstdc++fs(GCC)或等效库 -
std::filesystem::create_hard_link("src", "dst")在跨文件系统时,GCC 实现会抛std::filesystem::filesystem_error,错误码为std::errc::cross_device_link;MSVC 行为类似但错误消息更模糊 - 符号链接的目标路径如果是相对路径,
std::filesystem会按调用时的current_path()解析一次再传给系统——这可能和你预期的“链接内保存的路径”不一致
真正容易被忽略的是:硬链接无法区分“原文件”和“链接”,所有硬链接共享同一 inode(Linux/macOS)或 MFT 记录(Windows),删光所有硬链接后数据才真正释放。这点在资源管理逻辑里一旦漏掉,就会导致静默的数据残留或误删。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











