ftok()函數深度解析


【轉載】 原文鏈接:https://blog.csdn.net/u013485792/article/details/50764224 

     關於ftok函數,先不去了解它的作用來先說說為什么要用它,共享內存,消息隊列,信號量它們三個都是找一個中間介質,來進行通信的,這種介質多的是。就是怎么區分出來,就像唯一一個身份證來區分人一樣。你隨便來一個就行,就是因為這。只要唯一就行,就想起來了文件的設備編號和節點,它是唯一的,但是直接用它來作識別好像不太好,不過可以用它來產生一個號。ftok()就出場了。ftok函數具體形式如下:

    key_t ftok(const char *pathname, int proj_id);

    其中參數fname是指定的文件名,這個文件必須是存在的而且可以訪問的。id是子序號,它是一個8bit的整數。即范圍是0~255。當函數執行成功,則會返回key_t鍵值,否則返回-1。在一般的UNIX中,通常是將文件的索引節點取出,然后在前面加上子序號就得到key_t的值。

 

有關該函數的三個常見問題:

1.pathname是目錄還是文件的具體路徑,是否可以隨便設置

2.pathname指定的目錄或文件的權限是否有要求

3.proj_id是否可以隨便設定,有什么限制條件

 

解答:

   1、ftok根據路徑名,提取文件信息,再根據這些文件信息及project ID合成key,該路徑可以隨便設置。

    2、該路徑是必須存在的,ftok只是根據文件inode在系統內的唯一性來取一個數值,和文件的權限無關。

    3、proj_id是可以根據自己的約定,隨意設置。這個數字,有的稱之為project ID; 在UNIX系統上,它的取值是1到255;

 

簡單驗證:

                   

用到的代碼,文件wxyuan.c:

    #include <stdio.h>  
    #include <sys/sem.h>  
    #include <stdlib.h>  
    int main()  
    {  
        key_t semkey;  
        if((semkey = ftok("./test", 1))<0)  
        {  
            printf("ftok failed\n");  
            exit(EXIT_FAILURE);  
        }     
        printf("ftok ok ,semkey = %d\n", semkey);  
        return 0;  
    }

 


關於ftok()函數的一個陷阱

     在使用ftok()函數時,里面有兩個參數,即fname和id,fname為指定的文件名,而id為子序列號,這個函數的返回值就是key,它與指定的文件的索引節點號和子序列號id有關,這樣就會給我們一個誤解,即只要文件的路徑,名稱和子序列號不變,那么得到的key值永遠就不會變。

     事實上,這種認識是錯誤的,想想一下,假如存在這樣一種情況:在訪問同一共享內存的多個進程先后調用ftok()時間段中,如果fname指向的文件或者目錄被刪除而且又重新創建,那么文件系統會賦予這個同名文件新的i節點信息,於是這些進程調用的ftok()都能正常返回,但鍵值key卻不一定相同了。由此可能造成的后果是,原本這些進程意圖訪問一個相同的共享內存對象,然而由於它們各自得到的鍵值不同,實際上進程指向的共享內存不再一致;如果這些共享內存都得到創建,則在整個應用運行的過程中表面上不會報出任何錯誤,然而通過一個共享內存對象進行數據傳輸的目 的將無法實現。

      這是一個很重要的問題,希望能謹記!!!

     所以要確保key值不變,要么確保ftok()的文件不被刪除,要么不用ftok(),指定一個固定的key值。

 

Ubuntu下,ftok()產生鍵值的原理:

執行該源碼:

 

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
 
int main()
{
    char filename[50];
    struct stat buf; 
    int ret; 
    strcpy( filename, "/home/satellite/" ); 
    ret = stat( filename, &buf ); 
    if( ret ) 
    { 
        printf( "stat error\n" ); 
        return -1; 
    } 
    printf( "the file info: ftok( filename, 0x27 ) = %x, st_ino = %x, st_dev= %x\n", ftok( filename, 0x27 ), buf.st_ino, buf.st_dev );
    return 0;
}

 

satellite@ubuntu:~/test$ ./wxyuan
the file info: ftok( filename, 0x27 ) = 27012eef, st_ino = e2eef, st_dev= 801


通過執行結果可看出,ftok獲取的鍵值是由ftok()函數的第二個參數的后8個bit,st_dev的后兩位,st_ino的后四位構成的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM