多進(jìn)程——System V信號(hào)量

概述

lLinux 操作系統(tǒng)中有兩種信號(hào)量分別為System V和Posix 。其中Posix 信號(hào)量可以用于多線程和多進(jìn)程同步,但是Posix 信號(hào)量一般只有0和1兩個(gè)值。但是system V信號(hào)量可以的數(shù)值范圍可以變化一般默認(rèn)的范圍為0~2^15 - 1,同時(shí)對(duì)于system V信號(hào)量來說其申請(qǐng)的不是以個(gè)來申請(qǐng)而是以組的概念進(jìn)行申請(qǐng)。

使用

創(chuàng)建system V信號(hào)量

system V信號(hào)量使用semget函數(shù)進(jìn)行申請(qǐng)。semget函數(shù)在成功申請(qǐng)到信號(hào)量之后,會(huì)返回一個(gè)信號(hào)量的標(biāo)記值,用于之后對(duì)信號(hào)量的控制和訪問。
該函數(shù)調(diào)用如下:

int semget(key_t key, int nsems, int semflg);

其中key為鍵值需要具有唯一性,如果這個(gè)值相同那么對(duì)應(yīng)的信號(hào)量相同。該值一般由ftok函數(shù)產(chǎn)生,ftok函數(shù)負(fù)責(zé)產(chǎn)生一個(gè)在系統(tǒng)中具有唯一性的值。ftok函數(shù)如下:

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

其中的pathname需要為一個(gè)文件路徑,該路徑必須是具體存在的,因?yàn)閒tok在生成key值時(shí)需要使用到文件的inode值,因?yàn)閕node值在文件系統(tǒng)中具有唯一性。第二個(gè)參數(shù)proj_id為偏移值,這個(gè)值的末尾8位也同時(shí)參與到key的計(jì)算中,防止通過inode值進(jìn)行生成時(shí)由于文件相同出現(xiàn)重復(fù)。
semget的第二個(gè)參數(shù)為nsem,即所需申請(qǐng)的system V信號(hào)量組中信號(hào)量的數(shù)目。
第三個(gè)參數(shù)semflg負(fù)責(zé)指定這個(gè)system V信號(hào)量的的讀寫權(quán)限,該權(quán)限和system V的作用范圍相關(guān),如果希望信號(hào)量的適用范圍盡可能廣,那么可以設(shè)置為0666。

對(duì)system V信號(hào)量賦初值

賦初值需要調(diào)用如下函數(shù)

semctl(data_req_p_id, 0, SETVAL, sem_union);
需要注意的是上面賦初值的使用方式是semctl較為簡(jiǎn)單的使用方式,semctl本質(zhì)上有很多調(diào)用方式。

  • 其中data_rep_p_id是信號(hào)量的標(biāo)記值。
  • 第二個(gè)參數(shù)0指明操作信號(hào)量組中的第幾個(gè)信號(hào)量,(system V信號(hào)量以組的方式進(jìn)行分配)
  • 第三個(gè)參數(shù)SETVAL是對(duì)應(yīng)的命令,該參數(shù)指明semctl函數(shù)應(yīng)該進(jìn)行的操作為賦值操作
  • 第四個(gè)參數(shù)sem_union是一個(gè)聯(lián)合體,負(fù)責(zé)傳遞具體的初值
    定義如下:
union semun {
        int val;                        /* value for SETVAL */
        struct semid_ds *buf;                /* buffer for IPC_STAT, IPC_SET */
        unsigned short int *array;         /* array for GETALL, SETALL */
        struct seminfo *__buf;                /* buffer for IPC_INFO */
};

生成system V信號(hào)量之后,需要對(duì)system V信號(hào)量賦予初值。需要注意的時(shí),對(duì)于system V信號(hào)量來說,其創(chuàng)建和賦初值是分開的,這將導(dǎo)致一個(gè)system V信號(hào)量在賦值時(shí)可能會(huì)出現(xiàn)多個(gè)進(jìn)程同時(shí)賦值導(dǎo)致初值不確定的情況,不過這一點(diǎn)可以通過下面的代碼進(jìn)行避免:

    if (0 <= (data_req_p_id = semget(data_qp_id, 1, oflag)))
    {
        sem_union.val = 0;
        semctl(data_req_p_id, 0, SETVAL, sem_union);
    }
    else if (errno == EEXIST)
    {
        data_req_p_id = semget(data_qp_id, 1, SVSEM_MODE);
    }
    else
    {
        perror("data_req_p_id semget error\n");
    }

不過上面的方式只是簡(jiǎn)單的適用于不對(duì)等的進(jìn)程之間(一個(gè)進(jìn)程為信號(hào)量的中心持有進(jìn)程開始就被創(chuàng)建,其他進(jìn)程在之后被陸續(xù)創(chuàng)建)。另外一個(gè)更好的方法時(shí)通過信號(hào)量中的一個(gè)屬性值sem_otime來進(jìn)行同步。這個(gè)方法的原理在于sem_otime在信號(hào)量創(chuàng)建時(shí)被置為0,只有在調(diào)用sem_op函數(shù)后才會(huì)變?yōu)榉橇阒怠?br> 因此只要在上面的data_req_p_id = semget(data_qp_id, 1, SVSEM_MODE);后面使用IPC_STAT命令調(diào)用semctl函數(shù),等待sem_otime 變?yōu)榉?時(shí)即可。這個(gè)方法可以更加有效地防止出現(xiàn)system V信號(hào)量初值不確定的情況發(fā)生。

sytem信號(hào)量操作

對(duì)信號(hào)量的操作函數(shù)為semop,函數(shù)申明如下所示:

int semop(int semid, struct sembuf *sops, size_t nsops);

  • 第一個(gè)參數(shù)semid為信號(hào)量的標(biāo)記值
  • 第二個(gè)參數(shù)sembuf如下所示:
struct sembuf
{
  unsigned short int sem_num;   /* semaphore number */
  short int sem_op;     /* semaphore operation */
  short int sem_flg;        /* operation flag */
};

其中sem_num指的不是數(shù)目,而是system V信號(hào)量組中序列號(hào)(本質(zhì)上就是幾個(gè)和第幾個(gè)的區(qū)別)。sem_op指的是對(duì)信號(hào)量的操作值。sem_flg指對(duì)信號(hào)量的操作的flag。這個(gè)flag總共有三種情況:

  • 第一種為不指定,默認(rèn)狀態(tài)為阻塞狀態(tài)
  • 第二種IPC_NOWAIT,設(shè)置為不阻塞狀態(tài),
  • 第三種為SEM_UNDO,這一種需要特殊說明,SEM_UNDO并不是指不做任何事情,該值的實(shí)際意義為將每一次的操作值都加入到一個(gè)中間變量semadj中,具體如下所示:

sem_op < 0 : semadj = semadj + sem_op的絕對(duì)值
sem_op > 0 : semadj = semadj - sem_op的絕對(duì)值

當(dāng)某一個(gè)調(diào)用該信號(hào)量的進(jìn)程退出時(shí),semadj的值會(huì)加到當(dāng)前信號(hào)量的值semval上。所以SEM_UNDO的真正意義為“復(fù)舊”。當(dāng)定義了該屬性的進(jìn)程退出時(shí),該進(jìn)程對(duì)信號(hào)量的操作會(huì)變得和原始沒有允許改進(jìn)程時(shí)相同。因此當(dāng)信號(hào)量用來作為同步信號(hào)量即一個(gè)進(jìn)程負(fù)責(zé)P操作,另外一個(gè)進(jìn)程負(fù)責(zé)V操作時(shí),不能指定該屬性,因?yàn)閱为?dú)一個(gè)進(jìn)程對(duì)該信號(hào)量的操作都是獨(dú)立的P或者V,這會(huì)導(dǎo)致單獨(dú)一個(gè)進(jìn)程中的semadj中間變量的值一直+1或者-1,最后出現(xiàn)semadj越界的情況,導(dǎo)致信號(hào)量同步失敗。

  • 第三個(gè)參數(shù)為nsops指明sembuf的數(shù)目(即對(duì)system V信號(hào)量組還總多少個(gè)信號(hào)量進(jìn)行操作)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容