15_进程间通信5-信号量数组

在这里插入图片描述
信号量数组:

在这里插入图片描述

信号量:

在这里插入图片描述
创建一个新的信号量或获取一个已经存在的信号量的ID

在这里插入图片描述

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

/*创建一个新的信号量数组 或获取一个已经存在的信号量数组 的ID
key:
如果没有亲缘关系的进程中 创建和获取 和之前 消息队列是一样的
如果在有亲缘关系的进程中,fork()之后,每一个子进程都可以拿到父进程创建的 key值,此时不再关心key值,此时可以设置为 IPC_PRIVATE,表示该IPC 为 匿名IPC 不需要ftok

nsems: 指定当前信号量数组中有多少个元素
semflg:其他特殊要求,当key 为IPC_PRIVATE时, semflg设置为IPC_CREAT

*/
int semget(key_t key, int nsems, int semflg);

对目标信号量执行各类操作,不过最常用的是删除它。

/*
semid : IPC ID
semnum :目标信号量 在数组中的下标值
cmd :命令
...
IPC_RMID:从系统中删除目标信号量集合
......
SETVAL:设置数组中下标为semnum的成员值,即设置某个信号量的资源量
......

最后参数:初始值,即资源总量

如:
//设置ID为semid的信号量集合数组中 第1个信号量的资源总量为1
semctl(semid,0,SETVAL,1):
*/

在这里插入图片描述
在这里插入图片描述

semop() 操作信号量数组 ,P + V

       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>

/*
semid:目标IPC ID
sops :结构体数组起始位置
nsops:结构体数组中有多少个元素,即有多少个该结构体
*/
       int semop(int semid, struct sembuf *sops, size_t nsops);

The elements of this structure are of type struct sembuf, containing the following members:
//信号量编号,当使用单个信号量时候,为0
       unsigned short sem_num; 
        //信号量操作,取值为-1,表示P操作。归还为+1,为释放操作
       short          sem_op;  
       short          sem_flg;  /* operation flags */

ERRORS
On failure, errno is set to one of the following:

   E2BIG  The argument nsops is greater than SEMOPM, the maximum number of operations allowed per system call.

   EACCES The calling process does not have the permissions required to perform the specified semaphore operations, and does not have the CAP_IPC_OWNER capability.

   EAGAIN 假错

   EFAULT An address specified in either the sops or the timeout argument isn't accessible.

   EFBIG  For some operation the value of sem_num is less than 0 or greater than or equal to the number of semaphores in the set.

   EIDRM  The semaphore set was removed.

   EINTR  While blocked in this system call, the thread caught a signal; see signal(7).

   EINVAL The semaphore set doesn't exist, or semid is less than zero, or nsops has a nonpositive value.

   ENOMEM The sem_flg of some operation specified SEM_UNDO and the system does not have enough memory to allocate the undo structure.

   ERANGE For some operation sem_op+semval is greater than SEMVMX, the implementation dependent maximum value for semval.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验:信号量使用,20个进程写同一个文件,该例程中 信号量集合中只有一个信号量,功能和互斥锁差不多。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define PROCNUM 20
#define FNAME "/home/mhr/Desktop/xitongbiancheng/super_io/out"
#define LINESIZE 1024
static 	int semid;

//取资源量
static void P(void)
{
	struct sembuf op;
	
	op.sem_num = 0;
	op.sem_op = -1;
	op.sem_flg = 0;

	while(semop(semid,&op,1) < 0)
	{
		if(errno != EINTR || error != EAGAIN)
		{
			perror("semop()");
			exit(1);
		}
	}
}

//归还资源量
static void V(void)
{
	struct sembuf op;
	
	op.sem_num = 0;
	op.sem_op = 1;
	op.sem_flg = 0;

	if(semop(semid,&op,1) < 0)
	{
		perror("semop()");
		exit(1);

	}
}

static void func_add(void)
{
	FILE *fp;
	int fd;
	char linebuf[LINESIZE];

	fp = fopen(FNAME,"r+");
	if(fp == NULL)
	{
		perror("fopen()");
		exit(1);
	}



P();//取资源量
	fgets(linebuf,LINESIZE,fp);
	fseek(fp,0,SEEK_SET);

	//sleep(1);	
	
	fprintf(fp,"%d\n",atoi(linebuf)+1);
	fflush(fp);
V();//归还资源量
	
	fclose(fp);
return;

} 

int main()
{
	int i,err;
	pid_t pid;

//创建信号量数组 IPC 返回值为id
	semid = semget(IPC_PRIVATE,1,IPC_CREAT);
	if(semid < 0)
	{
		perror("semget");
		exir(0);
	}

// 设置信号量集合中 第一个信号量的资源总量为1
	if(semctl(semid,0,SETVAL,1) < 0)
	{
		perror("semctl");
		exir(0);	
	}

	for(i = 0; i < PROCNUM; i++)
	{
		pid = fork();
		if(pid < 0)
		{
			perror("fork()");
			exit(1);
		}
		
		if(pid == 0)//Child 
		{
			func_add();
			exit(0);
		}

	}


	for(i = 0;i < PROCNUM; i++)
	{
		wait(NULL);
	}
	
	//从当前系统 删除该 信号量集合
	semctl(semid,0,IPC_RMID);

	exit(0);
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值