news 2026/6/25 22:38:56

深入理解 ftok:从源码手写一个 IPC key 生成函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入理解 ftok:从源码手写一个 IPC key 生成函数

很多人用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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/25 22:37:38

Web测试入门:从手工到自动化,构建你的测试知识体系与实战项目

1. 项目概述&#xff1a;从零到一&#xff0c;构建你的Web测试知识体系最近和几个刚转行或者刚入行的朋友聊天&#xff0c;发现大家对“Web测试如何入门”这个问题普遍感到迷茫。网上的资料铺天盖地&#xff0c;从“三天速成”到“年薪百万”&#xff0c;看得人眼花缭乱&#x…

作者头像 李华
网站建设 2026/6/25 22:35:42

OpenHarmony学习笔记【总篇:从入门到放弃】

本文以鸿蒙开源代码为基础&#xff0c;记录我在学习鸿蒙系统中的一些关键逻辑和重要模块&#xff0c;以及针对想从安卓工程师转到鸿蒙工程师提供一条思路。

作者头像 李华
网站建设 2026/6/25 22:33:23

musl libc 中 exit() 的实现:一行代码背后的并发哲学

摘要&#xff1a;本文逐行解析 musl libc 中 exit() 函数的源码&#xff0c;揭示其如何用极简的原子操作解决并发退出和递归调用两大难题&#xff0c;以及 .fini_array 倒序调用的设计意图。一、为什么要看 exit() 的实现&#xff1f;exit() 是每个 C 程序的终点&#xff0c;但…

作者头像 李华
网站建设 2026/6/25 22:31:07

LLaMA泄露事件:基础大模型治理的临界点与实践启示

1. 项目概述&#xff1a;一场未授权的模型扩散&#xff0c;不是技术事故&#xff0c;而是治理试金石2023年3月初&#xff0c;一个压缩包在4chan论坛悄然出现&#xff0c;文件名带着典型的极客式冷感&#xff1a;llama-7b-16bit.safetensors.torrent。没有公告&#xff0c;没有说…

作者头像 李华
网站建设 2026/6/25 22:29:01

3步掌握文档下载:彻底解决30+平台付费限制难题

3步掌握文档下载&#xff1a;彻底解决30平台付费限制难题 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档&#xff0c;但是相关网站浏览体验不好各种广告&#xff0c;各种登录验证&#xff0c;需要很多步骤才能下载文档&#xff0c;该脚本就是为了解决您的烦…

作者头像 李华