linux 信号量semget,51CTO博客-专业IT技术博客创作平台-技术成就梦想
semget()
可以使用系統(tǒng)調(diào)用semget()創(chuàng)建一個新的信號量集,或者存取一個已經(jīng)存在的信號量集:
系統(tǒng)調(diào)用:semget();
原型:intsemget(key_t key,int nsems,int semflg);
返回值:如果成功,則返回信號量集的IPC標(biāo)識符。如果失敗,則返回-1:errno=EACCESS(沒有權(quán)限)
EEXIST(信號量集已經(jīng)存在,無法創(chuàng)建)
EIDRM(信號量集已經(jīng)刪除)
ENOENT(信號量集不存在,同時沒有使用IPC_CREAT)
ENOMEM(沒有足夠的內(nèi)存創(chuàng)建新的信號量集)
ENOSPC(超出限制)
系統(tǒng)調(diào)用semget()的第一個參數(shù)是關(guān)鍵字值(一般是由系統(tǒng)調(diào)用ftok()返回的)。系統(tǒng)內(nèi)核將此值和系統(tǒng)中存在的其他的信號量集的關(guān)鍵字值進行比
較。打開和存取操作與參數(shù)semflg中的內(nèi)容相關(guān)。IPC_CREAT如果信號量集在系統(tǒng)內(nèi)核中不存在,則創(chuàng)建信號量集。IPC_EXCL當(dāng)和
IPC_CREAT一同使用時,如果信號量集已經(jīng)存在,則調(diào)用失敗。如果單獨使用IPC_CREAT,則semget()要么返回新創(chuàng)建的信號量集的標(biāo)識
符,要么返回系統(tǒng)中已經(jīng)存在的同樣的關(guān)鍵字值的信號量的標(biāo)識符。如果IPC_EXCL和IPC_CREAT一同使用,則要么返回新創(chuàng)建的信號量集的標(biāo)識
符,要么返回-1。IPC_EXCL單獨使用沒有意義。參數(shù)nsems指出了一個新的信號量集中應(yīng)該創(chuàng)建的信號量的個數(shù)。信號量集中最多的信號量的個數(shù)是
在linux/sem.h中定義的:
#defineSEMMSL32/*<=512maxnumofsemaphoresperid*/
下面是一個打開和創(chuàng)建信號量集的程序:
intopen_semaphore_set(key_t keyval,int numsems)
{
intsid;
if(!numsems)
return(-1);
if((sid=semget(mykey,numsems,IPC_CREAT|0660))==-1)
{
return(-1);
}
return(sid);
}
};
==============================================================semop()
系統(tǒng)調(diào)用:semop();
調(diào)用原型:int semop(int semid,struct sembuf*sops,unsign ednsops);
返回值:0,如果成功。-1,如果失敗:errno=E2BIG(nsops大于最大的ops數(shù)目)
EACCESS(權(quán)限不夠)
EAGAIN(使用了IPC_NOWAIT,但操作不能繼續(xù)進行)
EFAULT(sops指向的地址無效)
EIDRM(信號量集已經(jīng)刪除)
EINTR(當(dāng)睡眠時接收到其他信號)
EINVAL(信號量集不存在,或者semid無效)
ENOMEM(使用了SEM_UNDO,但無足夠的內(nèi)存創(chuàng)建所需的數(shù)據(jù)結(jié)構(gòu))
ERANGE(信號量值超出范圍)
第一個參數(shù)是關(guān)鍵字值。第二個參數(shù)是指向?qū)⒁僮鞯臄?shù)組的指針。第三個參數(shù)是數(shù)組中的操作的個數(shù)。參數(shù)sops指向由sembuf組成的數(shù)組。此數(shù)組是在linux/sem.h中定義的:
/*semop systemcall takes an array of these*/
structsembuf{
ushortsem_num;/*semaphore index in array*/
shortsem_op;/*semaphore operation*/
shortsem_flg;/*operation flags*/
sem_num將要處理的信號量的個數(shù)。
sem_op要執(zhí)行的操作。
sem_flg操作標(biāo)志。
如果sem_op是負(fù)數(shù),那么信號量將減去它的值。這和信號量控制的資源有關(guān)。如果沒有使用IPC_NOWAIT,那么調(diào)用進程將進入睡眠狀態(tài),直到信號
量控制的資源可以使用為止。如果sem_op是正數(shù),則信號量加上它的值。這也就是進程釋放信號量控制的資源。最后,如果sem_op是0,那么調(diào)用進程
將調(diào)用sleep(),直到信號量的值為0。這在一個進程等待完全空閑的資源時使用。
===============================================================semctl()
系統(tǒng)調(diào)用:semctl();
原型:int semctl(int semid,int semnum,int cmd,union semunarg);
返回值:如果成功,則為一個正數(shù)。
如果失敗,則為-1:errno=EACCESS(權(quán)限不夠)
EFAULT(arg指向的地址無效)
EIDRM(信號量集已經(jīng)刪除)
EINVAL(信號量集不存在,或者semid無效)
EPERM(EUID沒有cmd的權(quán)利)
ERANGE(信號量值超出范圍)
系統(tǒng)調(diào)用semctl用來執(zhí)行在信號量集上的控制操作。這和在消息隊列中的系統(tǒng)調(diào)用msgctl是十分相似的。但這兩個系統(tǒng)調(diào)用的參數(shù)略有不同。因為信號
量一般是作為一個信號量集使用的,而不是一個單獨的信號量。所以在信號量集的操作中,不但要知道IPC關(guān)鍵字值,也要知道信號量集中的具體的信號量。這兩
個系統(tǒng)調(diào)用都使用了參數(shù)cmd,它用來指出要操作的具體命令。兩個系統(tǒng)調(diào)用中的最后一個參數(shù)也不一樣。在系統(tǒng)調(diào)用msgctl中,最后一個參數(shù)是指向內(nèi)核
中使用的數(shù)據(jù)結(jié)構(gòu)的指針。我們使用此數(shù)據(jù)結(jié)構(gòu)來取得有關(guān)消息隊列的一些信息,以及設(shè)置或者改變隊列的存取權(quán)限和使用者。但在信號量中支持額外的可選的命
令,這樣就要求有一個更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
系統(tǒng)調(diào)用semctl()的第一個參數(shù)是關(guān)鍵字值。第二個參數(shù)是信號量數(shù)目。
參數(shù)cmd中可以使用的命令如下:
·IPC_STAT讀取一個信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds,并將其存儲在semun中的buf參數(shù)中。
·IPC_SET設(shè)置信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds中的元素ipc_perm,其值取自semun中的buf參數(shù)。
·IPC_RMID將信號量集從內(nèi)存中刪除。
·GETALL用于讀取信號量集中的所有信號量的值。
·GETNCNT返回正在等待資源的進程數(shù)目。
·GETPID返回最后一個執(zhí)行semop操作的進程的PID。
·GETVAL返回信號量集中的一個單個的信號量的值。
·GETZCNT返回這在等待完全空閑的資源的進程數(shù)目。
·SETALL設(shè)置信號量集中的所有的信號量的值。
·SETVAL設(shè)置信號量集中的一個單獨的信號量的值。
參數(shù)arg代表一個semun的實例。semun是在linux/sem.h中定義的:
/*arg for semctl systemcalls.*/
unionsemun{
intval;/*value for SETVAL*/
structsemid_ds*buf;/*buffer for IPC_STAT&IPC_SET*/
ushort*array;/*array for GETALL&SETALL*/
structseminfo*__buf;/*buffer for IPC_INFO*/
void*__pad;
val當(dāng)執(zhí)行SETVAL命令時使用。buf在IPC_STAT/IPC_SET命令中使用。代表了內(nèi)核中使用的信號量的數(shù)據(jù)結(jié)構(gòu)。array在使用GETALL/SETALL命令時使用的指針。
下面的程序返回信號量的值。當(dāng)使用GETVAL命令時,調(diào)用中的最后一個參數(shù)被忽略:
intget_sem_val(intsid,intsemnum)
{
return(semctl(sid,semnum,GETVAL,0));
}
下面是一個實際應(yīng)用的例子:
#defineMAX_PRINTERS5
printer_usage()
{
int x;
for(x=0;x
printf("Printer%d:%d\n\r",x,get_sem_val(sid,x));
}
下面的程序可以用來初始化一個新的信號量值:
void init_semaphore(int sid,int semnum,int initval)
{
union semunsemopts;
semopts.val=initval;
semctl(sid,semnum,SETVAL,semopts);
}
注意系統(tǒng)調(diào)用semctl中的最后一個參數(shù)是一個聯(lián)合類型的副本,而不是一個指向聯(lián)合類型的指針。
總結(jié)
以上是生活随笔為你收集整理的linux 信号量semget,51CTO博客-专业IT技术博客创作平台-技术成就梦想的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微博上的微博ID在哪里查看
- 下一篇: 写作猫怎么用?写作猫安装使用详细图文教程