System V IPC(訊息佇列、共享記憶體、訊號量)建立時需指定 key_t 鍵值,ftok() 是產生該鍵值的標準方式。
key_t ftok(const char *pathname, int proj_id);
pathname:既存且可存取的檔案路徑。proj_id:子序號,**僅低 8 bits 有效 (0~255)**。key_t,失敗回傳 -1。傳統 UNIX 實作:key = (proj_id & 0xFF) << 24 | (inode & 0xFFFFFF)。
範例:inode = 65538 (0x010002),proj_id = 38 (0x26) → key = 0x26010002。
查詢 inode:ls -i filename。
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#define IPCKEY 0x11
int main(void) {
for (int i = 1; i < 256; ++i)
printf("key = %x\n", ftok("/tmp", i));
return 0;
}
#include <sys/shm.h>
#include <stdio.h>, <errno.h>, <string.h>, <stdlib.h>
#define SIZE 1024
extern int errno;
int main() {
int shmid;
char *shmptr;
// 建立私有共享記憶體(IPC_PRIVATE 忽略 key)
if ((shmid = shmget(IPC_PRIVATE, SIZE, 0600)) < 0) {
perror("shmget"); return -1;
}
// 掛載
if ((shmptr = shmat(shmid, 0, 0)) == (void*)-1) {
perror("shmat"); return -1;
}
memcpy(shmptr, "hello world", sizeof("hello world"));
printf("share memory %lx~%lx: %s\n", (long)shmptr, (long)(shmptr+SIZE), shmptr);
// 移除(最後一個進程 detach 後才真正刪除)
shmctl(shmid, IPC_RMID, 0);
return 0;
}
#include <sys/shm.h>, <unistd.h>, <sys/wait.h> ...
#define SIZE 1024
int main() {
pid_t pid = fork();
key_t key;
int shmid; char *shmptr;
if (pid == 0) { // 子進程
sleep(2);
key = ftok("/dev/null", 1);
shmid = shmget(key, SIZE, 0600); // 開啟既有
shmptr = shmat(shmid, 0, 0);
printf("child: %s\n", shmptr);
sleep(2);
shmctl(shmid, IPC_RMID, 0);
exit(0);
} else { // 父進程
key = ftok("/dev/null", 1);
shmid = shmget(key, SIZE, 0600|IPC_CREAT|IPC_EXCL); // 建立新
shmptr = shmat(shmid, 0, 0);
memcpy(shmptr, "hello world", sizeof("hello world"));
printf("parent: %s\n", shmptr);
sleep(2);
shmctl(shmid, IPC_RMID, 0);
waitpid(pid, NULL, 0);
}
return 0;
}
輸出:父子進程皆印出 hello world,驗證共享記憶體跨進程可見。
shmctl(shmid, IPC_RMID, 0) 標記刪除,實際釋放需等 shm_nattch == 0。ftok() 路徑必須存在,建議用 /dev/null 或固定專案檔案。proj_id 限 0~255,專案內協調避免衝突。