今天主要讲一下信号灯,也是有名信号量,一共分为四个步骤:创建、销毁、申请以及释放
首先是创建:
semget int semget(key_t key, int nsems, int semflg);
功能:创建一组信号量
参数:key:IPC对象名nsems:信号量的个数semflg:IPC_CREAT
返回值:成功返回信号量ID失败返回-1
销毁
semctl
int semctl(int semid, int semnum, int cmd, ...);
功能: 向信号灯发送命令
参数:semid:信号灯ID号semnum:具体操作信号量的编号cmd:IPC_RMID 删除信号灯SETVAL 设置信号量的值
返回值:成功返回0失败返回-1 初始化:
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) */
};
申请、释放信号量
semop int semop(int semid, struct sembuf *sops, size_t nsops);
功能:对信号量完成操作
参数:semid:信号灯的ID号sops:信号量操作的数组首地址nsops:数组元素个数
返回值:成功返回0 失败返回-1 unsigned short sem_num; /* semaphore number */ 操作信号量的下标short sem_op; /* semaphore operation */ 具体对信号量的操作(申请:-1 释放:+1)short sem_flg; /* operation flags */ SEM_UNDO
示例:写个共享内存,一边收,另一边发。
head.h
#ifndef __HEAD_H__
#define __HEAD_H__#include<signal.h>
#include <semaphore.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<pthread.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<dirent.h>
#include<string.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/shm.h>
#include<sys/sem.h>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) */
};extern int init_sem(int semid, int *parray, int len);
extern int sem_p(int semid, int num);
extern int sem_v(int semid, int num);#endif
linux@ub
read.c
#include "head.h"int main(void)
{key_t key;int shmid = 0;int semid = 0;int val[2] = {0,1};char *pshmaddr = NULL;key = ftok(".",'a');if(-1 == key){perror("fail to ftok");return -1;}semid = semget(key,2,IPC_CREAT|0664);if(-1 == semid){perror("fail to semid");return -1;}init_sem(semid,val,2);shmid = shmget(key,4096,IPC_CREAT|0664);if(-1 == shmid){perror("fail to shmget");return -1;}pshmaddr = shmat(shmid,NULL,0);if(NULL == pshmaddr){perror("fail to shmat");return -1;}while(1){sem_p(semid,0);printf("SHMADDR:%s\n",pshmaddr);if(!strcmp(pshmaddr,".quit")){break;}sem_v(semid,1);}shmdt(pshmaddr);shmctl(shmid,IPC_RMID,NULL);return 0;
}
write.c
#include "head.h"int main(void)
{key_t key;int shmid = 0;int semid = 0;int val[2] = {0,1};char *pshmaddr = NULL;key = ftok(".",'a');if(-1 == key){perror("fail to ftok");return -1;}semid = semget(key,2,IPC_CREAT|0664);if(-1 == semid){perror("fail to semid");return -1;}init_sem(semid,val,2);shmid = shmget(key,4096,IPC_CREAT|0664);if(-1 == shmid){perror("fail to shmget");return -1;}pshmaddr = shmat(shmid,NULL,0);if(NULL == pshmaddr){perror("fail to shmat");return -1;}while(1){sem_p(semid,1);gets(pshmaddr);sem_v(semid,0);if(!strcmp(pshmaddr,".quit")){break;}}shmdt(pshmaddr);shmctl(shmid,IPC_RMID,NULL);return 0;
}
sem.c
#include"head.h"int init_sem(int semid,int *parray,int len)
{union semun myun;int i = 0;int ret = 0;for(i = 0;i < len;++i){myun.val = parray[i];ret = semctl(semid,i,SETVAL,myun);if(-1 == ret){perror("fail to semctl");return -1;}}return 0;
}int sem_p(int semid,int num)
{int ret = 0;struct sembuf mybuf;mybuf.sem_num = num;mybuf.sem_op = -1;mybuf.sem_flg = SEM_UNDO;ret = semop(semid,&mybuf,1);if(-1 == ret){perror("fail to semop");return -1;}return 0;
}int sem_v(int semid,int num)
{int ret = 0;struct sembuf mybuf;mybuf.sem_num = num;mybuf.sem_op = +1;mybuf.sem_flg = SEM_UNDO;ret = semop(semid,&mybuf,1);if(-1 == ret){perror("fail to semop");return -1;}return 0;
}
结果: