信号量与共享内存
求100000个浮点数的和。要求:
(1)随机生成100000个浮点数(父进程);
(2)然后创建4个后代进程,分别求25000个浮点数的和;
(3)父进程对4个后代进程的结果求和;
(4)进程间用共享内存进行通信,用信号量实现同步和互斥。要求在创建子进程之后,由父进程创建共享缓冲区和信号量。
#include <stdio.h>
#include <sys/mman.h> //共享内存
#include <semaphore.h> //信号量
#include <fcntl.h> //O_* 宏定义
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
double num[5][25000];//放随机数
double sum_calculate(int i)
{
int k;
double totalsum=0;
for(k=1; k<=25000; k++)
totalsum += num[i][k];
return totalsum;
}
int main()
{
//数组从1开始
double sum[5] = {0.0};//放四个进程的计算和
srand((unsigned int)time(0));//初始化种子为随机值
//随机生成100000浮点数
int i,j,k;
for(i=1; i<=4; i++)
for(j=1; j<=25000; j++)
num[i][j] = (double)rand()/(double)RAND_MAX;//随机数转换为double类型
//父进程
//创建共享内存,调整大小后,并将其映射到进程的地址空间
int shmem_fd = shm_open("data_buffer", O_RDWR|O_CREAT, 0666);
ftruncate(shmem_fd, sizeof(double)*4+sizeof(int)*2);
double *ptr = mmap(NULL, sizeof(double)*4+sizeof(int)*2, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
//利用信号量实现父进程与子进程的同步/互斥
sem_t *w = sem_open("lock", O_CREAT, 0666, 1);
sem_t *s = sem_open("lock",O_CREAT,0666,0);
pid_t pid;
int ret;
for(i=1; i<=4; i++)
{
pid = fork();
if(pid < 0)
{
printf("fork error");
exit(1);
}
else if(pid == 0)//子进程
{
//实现同步
sem_wait(s);
int shmem_fd = shm_open("data_buffer", O_RDWR | O_CREAT, 0666);
ftruncate(shmem_fd, sizeof(double)*4+sizeof(int)*2);
double *ptr = mmap(NULL, sizeof(double)*4+sizeof(int)*2, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
sum[i] = sum_calculate(i);
printf("(%d)Child_%d sum:%.3f\n",getpid(),i,sum[i]);
//利用信号量实现互斥,将数据写入
sem_wait(w);
*(ptr+i) = sum[i];
sem_post(w);
//解除地址映射
ret = munmap(ptr, sizeof(double)+sizeof(int)*2);
if(ret<0){
perror("munmap");
}
exit(1);
}else{
sem_post(s);
}
}
double totalsum_1=0,totalsum_2=0;
for(j=1; j<=4; j++)
{
for(k=1; k<=25000; k++)
totalsum_1 += num[j][k];
}
sem_wait(w);
for(int j = 1; j <= 4; j++)
{
totalsum_2 += ptr[j];
}
sem_post(w);
printf("(%d)Parent direct sum:%.3f,sum from chilren:%.3f\n",getpid(),totalsum_1,totalsum_2);
//释放
ret = shm_unlink("data_buffer");
if(ret < 0)
{
perror("shm_unlink");
exit(-1);
}
ret = munmap(ptr, sizeof(double)*4+sizeof(int)*2);
if(ret < 0)
{
perror("munmap");
}
ret = sem_unlink("lock");
if(ret < 0)
{
perror("sem_unlink");
exit(-1);
}
return 0;
}
运行结果: