Linux IPC之信號(hào)量

創(chuàng)建一個(gè)信號(hào)量

//創(chuàng)建之后一直存在,除非主動(dòng)刪除
int sem_id;
//semget第二個(gè)參數(shù)為信號(hào)量集(數(shù)組)中信號(hào)量的個(gè)數(shù)
sem_id = semget(1000,1,IPC_CREAT|0600);
ERROR_CHECK(sem_id,-1,"semget");

將信號(hào)量初始化|設(shè)置信號(hào)量的值

//semctl函數(shù)
//第二個(gè)參數(shù)為信號(hào)量在信號(hào)量集(數(shù)組)中的下標(biāo)
//初始化時(shí),第三個(gè)參數(shù)為 SETVAL
//第四個(gè)參數(shù)為初始化的值
int ret = semctl(sem_id,0,SETVAL,1);
//成功返回0
ERROR_CHECK(ret,-1,"semctl");

獲取信號(hào)量的值

ret = semctl(sem_id,0,GETVAL);
ERROR_CHECK(ret,-1,"semctl");

實(shí)現(xiàn)PV操作

//P定義一個(gè)結(jié)構(gòu)體
//V定義一個(gè)結(jié)構(gòu)體
struct sembuf sopp,sopv;
//P操作
sopp.sem_num = 0;
sopp.sem_op = -1;
sopp.sem_flag = SEM_UNDO;
//V操作
sopv.sem_num = 0;
sopv.sem_op = 1;
sopv.sem_flag = SEM_UNDO;

if(!fork())
{
    for(int i=0;i<100000000;i++)
    {
        //加鎖
        semop(sem_id,&sopp,1);
        p_start[0] = p_start[0]+1;
        //解鎖
        semop(sem_id,&sopv,1);
    }
}

參數(shù)cmd為執(zhí)行的操作

  • IPC_RMID 立即刪除信號(hào)量,喚醒所有被阻塞的進(jìn)程
  • GETVAL 返回信號(hào)量的值,從0開(kāi)始,第一個(gè)信號(hào)量編號(hào)為0
  • SETVAL 設(shè)定信號(hào)量的值,從0開(kāi)始,第一個(gè)信號(hào)量編號(hào)為0

刪除信號(hào)量集合

//刪除信號(hào)量集合
ret = semctl(sem_id,0,IPC_RMID);
ERROR_CHECK(ret,-1,"semctl");

批量設(shè)置多個(gè)信號(hào)量的值

unsigned short arrays[2]={0,10};
int ret = semctl(sem_id,0,SETALL,arrays);

生產(chǎn)者消費(fèi)者

#include <func.h>

int main(int argc,char*argv[])
{
    int sem_id;
    //兩個(gè)信號(hào)量
    sem_id = semget(1000,2,IPC_CREAT|0600);
    ERROR_CHECK(sem_id,-1,"semctl");
    //生產(chǎn)者消費(fèi)者 計(jì)數(shù)信號(hào)量
    //0號(hào)信號(hào)量代表產(chǎn)品數(shù)目
    //1號(hào)信號(hào)量代表倉(cāng)庫(kù)數(shù)目
    unsigned short arrays[2]={0,10};
    int ret;
    //對(duì)兩個(gè)信號(hào)量同時(shí)進(jìn)行初始化
    ret = semctl(sem_id,0,SETALL,arrays);
    ERROR_CHECK(ret,-1,"semctl");
    //將arrays都設(shè)置為0
    //memset(arrays,0,sizeof(arrays));
    //子進(jìn)程是出庫(kù)進(jìn)程,消費(fèi)者
    //父進(jìn)程是入庫(kù)進(jìn)程,生產(chǎn)者
    if(!fork()){
        //出庫(kù),產(chǎn)品-,倉(cāng)庫(kù)空間+,故0號(hào)信號(hào)量p操作,1號(hào)信號(hào)量v操作
        struct sembuf sopp0,sopv1;
        sopp0.sem_num=0;
        sopp0.sem_op=-1;
        sopp0.sem_flg=SEM_UNDO;
        sopv1.sem_num=1;
        sopv1.sem_op=1;
        sopv1.sem_flg=SEM_UNDO;
        while(1){
        //子進(jìn)程出庫(kù)
        printf("I am Customer,product num = %d space num = %d \n",semctl(sem_id,0,GETVAL),semctl(sem_id,1,GETVAL));
        //對(duì)產(chǎn)品-1 P操作
        semop(sem_id,&sopp0,1);
        printf("start out...\n");
        //對(duì)倉(cāng)庫(kù)個(gè)數(shù)+1
        semop(sem_id,&sopv1,1);
        printf("I am Customer,product num = %d space num = %d \n",semctl(sem_id,0,GETVAL),semctl(sem_id,1,GETVAL));
        sleep(2);
        } 
    }else{
        //入庫(kù)
        //產(chǎn)品+,倉(cāng)庫(kù)空間-, 0號(hào)信號(hào)量+1,1號(hào)信號(hào)量-1
        struct sembuf sopp1,sopv0;
        sopv0.sem_num=0;//在信號(hào)量集合中的編號(hào)
        sopv0.sem_op=1;//V操作 +1
        sopv0.sem_flg=SEM_UNDO;
        sopp1.sem_num=1;
        sopp1.sem_op=-1;
        sopp1.sem_flg=SEM_UNDO;
        while(1)
        {
            printf("I am Productor,product num = %d space num = %d\n",semctl(sem_id,0,GETVAL),semctl(sem_id,1,GETVAL));
            //對(duì)倉(cāng)庫(kù)數(shù)-1,先要有位置了才能放入
            semop(sem_id,&sopp1,1);
            printf("start in...\n");
            //產(chǎn)品數(shù)+1
            semop(sem_id,&sopv0,1);
            printf("I am Productor,product num = %d space num = %d\n",semctl(sem_id,0,GETVAL),semctl(sem_id,1,GETVAL));
            sleep(1);
        }
    } 
    return 0;
}

SEM_UNDO

設(shè)置為SEM_UNDO,當(dāng)殺掉一個(gè)進(jìn)程的時(shí)候,這個(gè)進(jìn)程對(duì)該某信號(hào)的操作會(huì)較初始值全部反向操作回去.(若P操作減了三十次,則較初始值加回三十)

若要減三十多次,不能減為負(fù)值,那就為0

PV的非計(jì)數(shù)信號(hào)量,需要用SEM_UNDO.

?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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