在上一篇博文中,建立和擷取 ipc 核心對象的方式所使用的鍵值都是需要事先約定好的。通常在編寫程式的時候,這個鍵值可以放在公共頭檔案中,這樣不同程序間如果需要擷取相同的 ipc 核心對象,就使用公共頭檔案中約定好的 key 值。當然你也可以通過指令行傳參數的方式來指定 key 值。
本文介紹一個函數 ftok,它可以根據路徑和一個整數生成 key 值。如此你就可以約定好一個路徑以及一個整數來取得相同的 key 了。
1. ftok 函數
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
參數 pathname 可以是目錄路徑,也可以是檔案路徑(随便什麼類型的檔案都可以)。
參數 proj_id 可以取任意整數,通常用項目的編号。實際上,ftok 在生成 key 的時候,隻用了 proj_id 的低 8 位。
2. 執行個體
下面這個程式使用 ftok 生成 key 并将其列印到螢幕。
- 代碼
// ftok.c
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
if (argc < ) {
printf("usage: %s <path> <id>\n", argv[]);
return -;
}
int id = atoi(argv[]);
key_t key = ftok(argv[], id);
if (key == -) {
perror("ftok");
return -;
}
printf("key = 0x%08x\n", key);
return ;
}
- 編譯和運作
$ gcc ftok.c -o ftok
$ touch tmp // 生成一個檔案
$ ./ftok tmp
圖1 使用 ftok 生成 key
3. ftok 的算法
ftok 算法非常簡單,它通過 stat 函數讀取 pathname 的裝置号和 inode 号,取裝置号的低8位,inode 号的 低 16 位,以及 proj_id 的低 8 位組合成 key. key 具有下面的結構:
在圖1 中,tmp 檔案的資訊如下:
圖2 tmp 檔案的資訊
可以看到 tmp 的裝置号為 2049(十六進制為 0x801),inode 号為 1002871(十六進制為 0xf4d77),再根據 proj_id,圖1 中使用的是 10,(十進制 0xa),分别取:
proj_id 的低 8 位—— 0x0a
裝置号低 8 位 —— 0x01
inode 号低 16 位—— 0x4d77
最後組合成成 key——0x0a014d77。
4. 總結
需要注意的是,ftok 并不保證 key 一定是唯一的,通常來說,隻要不同的 ftok 使用不同的 pathname 和 proj_id,傳回的 key 值都不相同(除非你的運氣極佳:)。另外 man 手冊中說明 proj_id 必須為非 0 值,否則其行為是未定義的。
- ipc 核心對象的 key 值約定
- 知道 ftok 函數的使用方法
- 了解 ftok 函數的算法
練習:嘗試編寫一個 ftok 函數,功能和系統提供的一樣。