今天主要讲一下信号灯,也是有名信号量,一共分为四个步骤:创建、销毁、申请以及释放
首先是创建:
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;
}
结果: