父进程产生10个子进程,并打印出子进程产生的随机数的和

Linux 专栏收录该内容
4 篇文章 0 订阅
/*---------------------------------------------------------------------------------------------------------
功能:
    父进程产生10个子进程,并打印出子进程产生的随机数的和。要求用信号机制、信号量以及共享内存实现。

思路:
    子进程将自己产生的随机数累加到共享内存。当10个子进程都累加完后,用信号机制通知父进程,
父进程就可以从共享内存中读取数据了。为了避免10个子进程向共享内存中写入数据时发生冲突,
应使用信号量进行并发控制。	
---------------------------------------------------------------------------------------------------------*/

#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "sys/ipc.h"
#include "sys/sem.h"
#include "sys/shm.h"
#include "string.h" //NULL 才可以使用 
#include "stdlib.h" 

union semun
{
	int val;
	struct semid_ds *buf;
	ushort *array;
};


int semid;
int shmid;
char *shm_virtualaddr;  //共享内存关联到进程后的虚拟地址

void p(int semid)
{
	struct sembuf buf = {0, -1, 0};
	semop(semid, &buf, 1);
}

void v(int semid)
{
	struct sembuf buf = {0, 1, 0};
	semop(semid, &buf, 1);
}

void sigusr1_handler(int n)
{
	printf("count = %d, total = %d\n", *(int *)shm_virtualaddr, *(int *)(shm_virtualaddr+4));  //__ 输出共享内存里面保存的count 和total值,前4个字节保存count,后4个字节保存total____
	
	if(semctl(semid, IPC_RMID, 0) == -1)  //删除信号量
		printf("remove semaphore fail\n");
	else
		printf("remove semaphore ok\n");
	
	shmdt(shm_virtualaddr);  //解除共享内存的关联
	if(shmctl(shmid, IPC_RMID, 0) == -1)  //删除共享内存
		printf("remove shared-memory fail\n");
	else
		printf("remove shared-memory ok\n");

	exit(0);
}

int main()
{
	signal(SIGUSR1, sigusr1_handler);  //____注册信号处理函数_______

	//创建并初始化信号量
	semid = semget(IPC_PRIVATE, 1, 0666);
	if(semid == -1)
	{
		printf("create semaphore fail\n");
		return 0;
	}
	else
		printf("create semaphore ok\n");
	union semun x;
	x.val = 1;  //_初始化信号量的值为1_  //信号量初值应为多少?
	semctl(semid, 0, SETVAL, x);
	
	//创建并关联到共享内存
	shmid = shmget(IPC_PRIVATE, 8, 0666);  //共享内存一共8字节,前4字节存放count,后4字节存放total
	if(shmid == -1)
	{
		printf("create shared-memory fail\n");
		return 0;
	}
	else
		printf("create shared-memory ok\n");
	//连接共享内存与某个进程的地址空间
	//如果shmat()函数调用成功则返回指向共享内存的指针;否则返回-1.
	//第二个参数 Shmaddr是共享内存连接到进程中的存放地址,一般设置为空指针,表示交由系统完成这个工作
	shm_virtualaddr = shmat(shmid, 0, 0);
	
	*(int *)shm_virtualaddr = 0;  //___将共享内存里面的值设置为0表示count初始值为0_____
	*(int *)(shm_virtualaddr+4) = 0;  //____ 后4个字节的值设置为0,表示total的值____

	char is_child = 0;
	int i;
	for(i=0; i<10; i++)
	{
		pid_t pid = fork();
		if(pid == 0)	
		{
			is_child = 1;  //__创建子进程成功____
			break;  //___退出子进程所在循环__
		}
	}

	if(is_child)
	{
		p(semid);  //___子进程申请访问共享内存,若申请成功即可访问____

		srand(time(NULL) + i);
		int num = rand()%10;
		(*(int *)shm_virtualaddr)++;  //____前面4个字节表示count,每生成一个随机数cont++______
		*(int *)(shm_virtualaddr+4) += num;  //___后面4个字节是表示total,每次将生成的随机数加上去___

		printf("child%d: %d\n", i, num);

		v(semid);  //___释放信号量,代表已经加上了一个随机数了____

		if(*(int *)shm_virtualaddr == 10)  //if(_产生的随机数个数已经有10个了_)
			kill(getppid(), SIGUSR1);  //__那么向父进程发送信号____
	}
	else
	{
		while(1)
			pause(); //一直等待信号,直到信号来临执行信号处理函数 
	}

	return 0;
}
  • 6
    点赞
  • 1
    评论
  • 20
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值