定義
semctl()系統調用:semctl();
原型:int semctl(int semid,int semnum,int cmd, /*union semun arg*/);
參數說明
返回值:如果成功,則為一個正數。
如果失敗,則為-1:errno=EACCES(許可權不夠)
EFAULT(arg指向的地址無效)
EIDRM(信號量集已經刪除)
EINVAL(信號量集不存在,或者semid無效)
EPERM(EUID沒有cmd的權利)
ERANGE(信號量值超出範圍)
因為信號量一般是作為一個信號量集使用的,而不是一個單獨的信號量。所以在信號量集的操作中,不但要知道IPC關鍵字值,也要知道信號量集中的具體的信號量。這兩個系統調用都使用了參數cmd,它用來指出要操作的具體命令。兩個系統調用中的最後一個參數也不一樣。在系統調用msgctl中,最後一個參數是指向核心中使用的數據結構的指針。我們使用此數據結構來取得有關訊息佇列的一些信息,以及設定或者改變佇列的存取許可權和使用者。但在信號量中支持額外的可選的命令,這樣就要求有一個更為複雜的數據結構。
系統調用semctl()的第一個參數是信號量集IPC標識符。第二個參數是操作信號在信號集中的編號,第一個信號的編號是0。
參數cmd中可以使用的命令如下:
·IPC_STAT讀取一個信號量集的數據結構semid_ds,並將其存儲在semun中的buf參數中。
·IPC_SET設定信號量集的數據結構semid_ds中的元素ipc_perm,其值取自semun中的buf參數。
·IPC_RMID將信號量集從記憶體中刪除。
·GETALL用於讀取信號量集中的所有信號量的值。
· GETNCNT返回正在等待資源的進程數目。
·GETPID返回最後一個執行semop操作的進程的PID。
·GETVAL返回信號量集中的一個單個的信號量的值。
·GETZCNT返回正在等待完全空閒的資源的進程數目。
·SETALL設定信號量集中的所有的信號量的值。
·SETVAL設定信號量集中的一個單獨的信號量的值。
參數arg代表一個semun的實例。semun是在linux/sem.h中定義的:
/*arg for semctl systemcalls.*/
union semun{
int val;/*value for SETVAL*/
struct semid_ds *buf;/*buffer for IPC_STAT&IPC_SET*/
ushort *array;/*array for GETALL&SETALL*/
struct seminfo *__buf;/*buffer for IPC_INFO*/
void *__pad;
val當執行SETVAL命令時使用。buf在IPC_STAT/IPC_SET命令中使用。代表了核心中使用的信號量的數據結構。array在使用GETALL/SETALL命令時使用的指針。
下面的程式返回信號量的值。當使用GETVAL命令時,調用中的最後一個參數被忽略:
intget_sem_val(intsid,intsemnum)
{
return(semctl(sid,semnum,GETVAL,0));
}
下面是一個實際套用的例子:
#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));
}
下面的程式可以用來初始化一個新的信號量值:
void init_semaphore(int sid,int semnum,int initval)
{
union semun semopts;
semopts.val=initval;
semctl(sid,semnum,SETVAL,semopts);
}
注意系統調用semctl中的最後一個參數是一個聯合類型的副本,而不是一個指向聯合類型的指針。
需要注意的是,對於semun聯合體,最好自己定義,否則GCC編譯器可能會報“semun大小未知”。