
很多人用ftok生成 System V IPC 的 key但很少有人真正去看它的实现。今天我们从零手写一个彻底搞懂它的原理。一、ftok 是干什么的在 System V IPC消息队列、共享内存、信号量中所有操作都需要一个key_t类型的 key 来标识资源。ftok的作用就是根据一个已存在的文件路径 一个项目ID生成一个唯一的 key_t。key_t key ftok(/tmp/myfile, 65);这样不同进程只要用相同的路径和ID就能拿到同一个 key从而访问同一个 IPC 资源。二、标准库的 ftok 原型#include sys/ipc.h key_t ftok(const char *pathname, int proj_id);pathname必须是一个已存在的文件路径proj_id项目标识符通常取 0~255返回成功返回 key_t失败返回 -1三、手写实现核心源码下面这个实现和 glibc 的逻辑基本一致非常适合理解原理#include sys/ipc.h #include sys/stat.h key_t ftok(const char *path, int id) { struct stat st; if (stat(path, st) 0) return -1; return ((st.st_ino 0xffff) | ((st.st_dev 0xff) 16) | ((id 0xffu) 24)); }四、逐行拆解步骤代码含义1stat(path, st)获取文件的 inode 和设备号2st.st_ino 0xffff取 inode 的低 16 位文件唯一标识3(st.st_dev 0xff) 16取设备号低 8 位放到第 17~24 位4(id 0xffu) 24取项目ID低 8 位放到最高 8 位5三者按位或组合成一个 32 位的 key_t最终 key 的 bit 布局| 高8位(proj_id) | 8位(dev) | 16位(ino) | | bit 31~24 | bit 23~16 | bit 15~0 |五、为什么这样设计1. 用 inode 保证唯一性同一个文件系统中inode 是唯一的。所以只要路径相同st_ino就相同。2. 用 st_dev 区分不同文件系统不同挂载点可能有相同的 inode 号加上设备号就能区分。3. 用 proj_id 扩展空间同一个文件可以生成多个不同的 key靠的就是proj_id。比如key_t key1 ftok(/tmp/ipcfile, 1); // key for 消息队列 key_t key2 ftok(/tmp/ipcfile, 2); // key for 共享内存同一个文件不同 ID不同 key互不干扰。六、完整使用示例#include stdio.h #include sys/ipc.h #include sys/shm.h #include sys/stat.h key_t ftok(const char *path, int id) { struct stat st; if (stat(path, st) 0) return -1; return ((st.st_ino 0xffff) | ((st.st_dev 0xff) 16) | ((id 0xffu) 24)); } int main() { // 先创建一个文件ftok 要求文件必须存在 system(touch /tmp/my_ipc_file); key_t key ftok(/tmp/my_ipc_file, 65); if (key -1) { perror(ftok); return 1; } printf(Generated key: 0x%x (%d)\n, key, key); // 用这个 key 创建共享内存 int shmid shmget(key, 4096, IPC_CREAT | 0666); if (shmid 0) { perror(shmget); return 1; } printf(Shared memory id: %d\n, shmid); return 0; }编译运行gcc -o ftok_demo ftok_demo.c ./ftok_demo # Generated key: 0x4101d1a2 (1090636194) # Shared memory id: 65536七、踩坑清单坑说明❌ 文件不存在stat失败直接返回 -1一定要先创建文件❌ 路径被删除后重建inode 变了key 也变了旧的 IPC 资源将无法访问❌ 多个文件系统 inode 相同所以实现里加了st_dev来区分⚠️ key 不是全局唯一它只是大概率唯一真正的唯一性靠IPC_EXCL标志保证八、一句话总结ftok 的本质 inode(16bit) 设备号(8bit) 项目ID(8bit)用一个已存在文件的身份信息生成一个 IPC key。理解了这个System V IPC 的 key 机制就再也没有秘密了。觉得有用的话点个赞有问题评论区见参考glibc sysdeps/posix/ftok.c