信号灯——进程通信——day16

今天主要讲一下信号灯,也是有名信号量,一共分为四个步骤:创建、销毁、申请以及释放

首先是创建:

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  释放:+1short          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;
}

结果:
在这里插入图片描述

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值