天天看點

信号量 ——什麼是信号量

信号量

信号量(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");	   

	}
}
           

繼續閱讀