(Linux-OS实验-求100000个浮点数之和)信号量与共享内存

信号量与共享内存

求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;
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值