semget()
可以使用系統(tǒng)調(diào)用semget()創(chuàng)建一個(gè)新的信號量集,或者存取一個(gè)已經(jīng)存在的信號量集:
系統(tǒng)調(diào)用:semget();
原型:intsemget(key_t key,int nsems,int semflg);
返回值:如果成功,則返回信號量集的IPC標(biāo)識(shí)符。如果失敗,則返回-1:errno=EACCESS(沒有權(quán)限)
EEXIST(信號量集已經(jīng)存在,無法創(chuàng)建)
EIDRM(信號量集已經(jīng)刪除)
ENOENT(信號量集不存在,同時(shí)沒有使用IPC_CREAT)
ENOMEM(沒有足夠的內(nèi)存創(chuàng)建新的信號量集)
ENOSPC(超出限制)
系統(tǒng)調(diào)用semget()的第一個(gè)參數(shù)是關(guān)鍵字值(一般是由系統(tǒng)調(diào)用ftok()返回的)。系統(tǒng)內(nèi)核將此值和系統(tǒng)中存在的其他的信號量集的關(guān)鍵字值進(jìn)行比
較。打開和存取操作與參數(shù)semflg中的內(nèi)容相關(guān)。IPC_CREAT如果信號量集在系統(tǒng)內(nèi)核中不存在,則創(chuàng)建信號量集。IPC_EXCL當(dāng)和
IPC_CREAT一同使用時(shí),如果信號量集已經(jīng)存在,則調(diào)用失敗。如果單獨(dú)使用IPC_CREAT,則semget()要么返回新創(chuàng)建的信號量集的標(biāo)識(shí)
符,要么返回系統(tǒng)中已經(jīng)存在的同樣的關(guān)鍵字值的信號量的標(biāo)識(shí)符。如果IPC_EXCL和IPC_CREAT一同使用,則要么返回新創(chuàng)建的信號量集的標(biāo)識(shí)
符,要么返回-1。IPC_EXCL單獨(dú)使用沒有意義。參數(shù)nsems指出了一個(gè)新的信號量集中應(yīng)該創(chuàng)建的信號量的個(gè)數(shù)。信號量集中最多的信號量的個(gè)數(shù)是
在linux/sem.h中定義的:
#defineSEMMSL32/*<=512maxnumofsemaphoresperid*/
下面是一個(gè)打開和創(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ù)進(jìn)行)
EFAULT(sops指向的地址無效)
EIDRM(信號量集已經(jīng)刪除)
EINTR(當(dāng)睡眠時(shí)接收到其他信號)
EINVAL(信號量集不存在,或者semid無效)
ENOMEM(使用了SEM_UNDO,但無足夠的內(nèi)存創(chuàng)建所需的數(shù)據(jù)結(jié)構(gòu))
ERANGE(信號量值超出范圍)
第一個(gè)參數(shù)是關(guān)鍵字值。第二個(gè)參數(shù)是指向?qū)⒁僮鞯臄?shù)組的指針。第三個(gè)參數(shù)是數(shù)組中的操作的個(gè)數(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將要處理的信號量的個(gè)數(shù)。
sem_op要執(zhí)行的操作。
sem_flg操作標(biāo)志。
如果sem_op是負(fù)數(shù),那么信號量將減去它的值。這和信號量控制的資源有關(guān)。如果沒有使用IPC_NOWAIT,那么調(diào)用進(jìn)程將進(jìn)入睡眠狀態(tài),直到信號
量控制的資源可以使用為止。如果sem_op是正數(shù),則信號量加上它的值。這也就是進(jìn)程釋放信號量控制的資源。最后,如果sem_op是0,那么調(diào)用進(jìn)程
將調(diào)用sleep(),直到信號量的值為0。這在一個(gè)進(jìn)程等待完全空閑的資源時(shí)使用。
===============================================================
semctl()
系統(tǒng)調(diào)用:semctl();
原型:int semctl(int semid,int semnum,int cmd,union semunarg);
返回值:如果成功,則為一個(gè)正數(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í)行在信號量集上的控制操作。這和在消息隊(duì)列中的系統(tǒng)調(diào)用msgctl是十分相似的。但這兩個(gè)系統(tǒng)調(diào)用的參數(shù)略有不同。因?yàn)樾盘?
量一般是作為一個(gè)信號量集使用的,而不是一個(gè)單獨(dú)的信號量。所以在信號量集的操作中,不但要知道IPC關(guān)鍵字值,也要知道信號量集中的具體的信號量。這兩
個(gè)系統(tǒng)調(diào)用都使用了參數(shù)cmd,它用來指出要操作的具體命令。兩個(gè)系統(tǒng)調(diào)用中的最后一個(gè)參數(shù)也不一樣。在系統(tǒng)調(diào)用msgctl中,最后一個(gè)參數(shù)是指向內(nèi)核
中使用的數(shù)據(jù)結(jié)構(gòu)的指針。我們使用此數(shù)據(jù)結(jié)構(gòu)來取得有關(guān)消息隊(duì)列的一些信息,以及設(shè)置或者改變隊(duì)列的存取權(quán)限和使用者。但在信號量中支持額外的可選的命
令,這樣就要求有一個(gè)更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
系統(tǒng)調(diào)用semctl()的第一個(gè)參數(shù)是關(guān)鍵字值。第二個(gè)參數(shù)是信號量數(shù)目。
參數(shù)cmd中可以使用的命令如下:
·IPC_STAT讀取一個(gè)信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds,并將其存儲(chǔ)在semun中的buf參數(shù)中。
·IPC_SET設(shè)置信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds中的元素ipc_perm,其值取自semun中的buf參數(shù)。
·IPC_RMID將信號量集從內(nèi)存中刪除。
·GETALL用于讀取信號量集中的所有信號量的值。
·GETNCNT返回正在等待資源的進(jìn)程數(shù)目。
·GETPID返回最后一個(gè)執(zhí)行semop操作的進(jìn)程的PID。
·GETVAL返回信號量集中的一個(gè)單個(gè)的信號量的值。
·GETZCNT返回這在等待完全空閑的資源的進(jìn)程數(shù)目。
·SETALL設(shè)置信號量集中的所有的信號量的值。
·SETVAL設(shè)置信號量集中的一個(gè)單獨(dú)的信號量的值。
參數(shù)arg代表一個(gè)semun的實(shí)例。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命令時(shí)使用。buf在IPC_STAT/IPC_SET命令中使用。代表了內(nèi)核中使用的信號量的數(shù)據(jù)結(jié)構(gòu)。array在使用GETALL/SETALL命令時(shí)使用的指針。
下面的程序返回信號量的值。當(dāng)使用GETVAL命令時(shí),調(diào)用中的最后一個(gè)參數(shù)被忽略:
intget_sem_val(intsid,intsemnum)
{
return(semctl(sid,semnum,GETVAL,0));
}
下面是一個(gè)實(shí)際應(yīng)用的例子:
#defineMAX_PRINTERS5
printer_usage()
{
int x;
for(x=0;x<MAX_PRINTERS;x++)
printf("Printer%d:%d\n\r",x,get_sem_val(sid,x));
}
下面的程序可以用來初始化一個(gè)新的信號量值:
void init_semaphore(int sid,int semnum,int initval)
{
union semunsemopts;
semopts.val=initval;
semctl(sid,semnum,SETVAL,semopts);
}
注意系統(tǒng)調(diào)用semctl中的最后一個(gè)參數(shù)是一個(gè)聯(lián)合類型的副本,而不是一個(gè)指向聯(lián)合類型的指針。