【Linux】进程通信(信号量 练习巩固)

题目:三个进程 a、b、c 分别输入“A”、“B”、“C”,要求输出结果必须是“ABCABCABC”

(一)分析

按照ABC的顺序打印的话,可以看到总共3个A、3个B、3个C,所以未同步之前的进程大致是这样:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
	for(int i = 0; i < 3; i++)
	{
		write(1, "A", 1);	
		/*
		*	a进程输出A
		*	b进程输出B
		*	c进程输出C
		*/
		int num = rand() % 3;
		sleep(num);
	}
}
  • 未同步试试运行结果:
    在这里插入图片描述
(二)信号量同步思路

规定顺序的话,先A后B再C,后续循环也是如此,所以给定三个信号量如下图流程进行p v操作即可
在这里插入图片描述

(三)使用信号量同步后
  • sem.h
#include <stdio.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
//信号量的个数
#define INDEXSIZE 3
union semun
{
	int val;	//信号量的值
};

//创建(获得)信号量集,并初始化信号量的值
void sem_init();

//对下标为index的信号量的p操作
void sem_p(int index);

//对下标为index的信号量的v操作
void sem_v(int index);

//销毁信号量集
void sem_destroy();
  • sem.c
#include "sem.h"

//信号量集的ID 默认是-1
static int semid = -1;

//创建(获得)信号量集,并初始化信号量的值
void sem_init()
{
	semid = semget((key_t)8888, 3, IPC_CREAT | IPC_EXCL | 0600);
	//已经存在,创建失败
	if(semid == -1)
	{
		//获取信号量集的ID
		semid = semget((key_t)8888, 3, IPC_CREAT);
		if(semid == -1)
		{
			perror("semget err");
			return;
		}
	}
	//初始化信号量
	else
	{
		union semun arr[INDEXSIZE];
		arr[0].val = 1;
		arr[1].val = 0;
		arr[2].val = 0;
		for(int index = 0; index < INDEXSIZE; index++)
		{
			int ret = semctl(semid, index, SETVAL, arr[index]);
			if(ret == -1)
			{
				perror("semctl setval err");
				return;
			}
		}
	}
}

//对下标为index的信号量的p操作
void sem_p(int index)
{
	if(index < 0 || index > INDEXSIZE)
	{
		perror("index out of line");
		return;
	}
	struct sembuf buf;
	buf.sem_num = index;
	buf.sem_op = -1;
	buf.sem_flg = SEM_UNDO;

	//对index对应的信号量进行p操作
	if(semop(semid, &buf, 1) == -1)
	{
		perror("semop p err");
		return;
	}
}

//对下标为index的信号量的v操作
void sem_v(int index)
{
	if(index < 0 || index > INDEXSIZE)
	{
		perror("index out of line");
		return;
	}
	struct sembuf buf;
	buf.sem_num = index;
	buf.sem_op = 1;
	buf.sem_flg = SEM_UNDO;

	//对index对应的信号量进行v操作
	if(semop(semid, &buf, 1) == -1)
	{
		perror("semop v err");
		return;
	}
}

//销毁信号量集
void sem_destroy()
{
	if(semctl(semid, 0, IPC_RMID) == -1)
	{
		perror("sem_destroy err");
		return;
	}
}
  • a.c
#include "sem.h"

int main()
{
	sem_init();
	for(int i = 0; i < 3; i++)
	{
		sem_p(0);
		write(1, "A", 1);
		sem_v(1);

		int num = rand() % 3;
		sleep(num);
	}

	return 0;
}
  • b.c
#include "sem.h"
int main()
{
	sem_init();
	for(int i = 0; i < 3; i++)
	{
		sem_p(1);
		write(1, "B", 1);
		sem_v(2);

		int num = rand() % 3;
		sleep(num);
	}
	return 0;
}

  • c.c
#include "sem.h"
int main()
{
	sem_init();
	for(int i = 0; i < 3; i++)
	{
		sem_p(2);
		write(1, "C", 1);
		sem_v(0);

		int num = rand() % 3;
		sleep(num);
	}

	sleep(1);
	sem_destroy();
	return 0;
}

  • 结果:
    在这里插入图片描述
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值