信号量
信号量(semaphore)與已經介紹過的 IPC 結構不同,它是一個計數器。信号量用于實作程序間的互斥與同步,而不是用于存儲程序間通信資料。
1、特點
信号量用于程序間同步,若要在程序間傳遞資料需要結合共享記憶體。
信号量基于作業系統的 PV 操作,程式對信号量的操作都是原子操作。
每次對信号量的 PV 操作不僅限于對信号量值加 1 或減 1,而且可以加減任意正整數。
支援信号量組
函數原型
1 #include <sys/sem.h>
2 // 建立或擷取一個信号量組:若成功傳回信号量集ID,失敗傳回-1
3 int semget(key_t key, int num_sems, int sem_flags);
4 // 對信号量組進行操作,改變信号量的值:成功傳回0,失敗傳回-1
5 int semop(int semid, struct sembuf semoparray[], size_t numops);
6 // 控制信号量的相關資訊
7 int semctl(int semid, int sem_num, int cmd, ...);
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include<stdlib.h>
//int semop(int semid, struct sembuf *sops, size_t nsops);
//int semget(key_t key, int nse:ms, int semflg);
//int semctl(int semid, int semnum, int cmd, ...);
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
void pGetkey(int id)
{
struct sembuf set;
set.sem_num=0;
set.sem_op=-1;
set.sem_flg=SEM_UNDO;
if(semop(id,&set,1)==-1){
perror("semop");
exit(EXIT_FAILURE);
}
}
void vPutBackkey(int id)
{
struct sembuf set;
set.sem_num=0;
set.sem_op=1;
set.sem_flg=SEM_UNDO;
if(semop(id,&set,1)==-1){
perror("semop");
exit(EXIT_FAILURE);
}
}
int main(int argc,char **argv)
{
key_t key;
key=ftok(".",1);
if(key==-1){
printf("key=%x\n",key);
}
int semid=semget(key,1,IPC_CREAT|0666);
if(semid==-1){
printf("semget failed\n");
}
union semun initsem;
initsem.val=0;
int ret=semctl(semid,0,SETVAL,initsem);
if(ret==-1){
printf("semctl success\n");
}
pid_t pid;
pid=fork();
if(pid>0){
pGetkey(semid);
printf("this is father\n");
vPutBackkey(semid);
semctl(semid,1,IPC_RMID);
}else if(pid==0){
printf("this is child\n");
vPutBackkey(semid);
}else{
printf("failed\n");
}
}