Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 環境程式設計:ftok() 函數深度解析與共享記憶體實戰應用

編輯:Linux 教學

ftok() 核心作用

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。

測試程式:觀察 proj_id 變化對 key 影響

#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;
}

實戰:以 ftok() 鍵值建立共享記憶體

單一進程建立/掛載/移除

#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;
}

父子進程透過 ftok() 共享記憶體

#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,專案內協調避免衝突。
Copyright © Windows教程網 All Rights Reserved