多线程排序-v44-多进程-共享内存

makefile

v44:v44.o
	gcc -o v44 v44.o -lm -lpthread 
v44.o:v44.c
	gcc -c v44.c 
.PHONY:clean
clean:
	-rm v44
	-rm *.o
	-rm *.txt

v44.c

// 多线程排序-v44-多进程-共享内存
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/resource.h>
#include <stdbool.h>
#include <sys/times.h>
#include <time.h>
#include <pthread.h>
#include <math.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>

#define SIZE 16

struct data_size
{
    int size;
    int *data;
};

struct data_info
{
    int size;
    int *data;
};

// 注意fork结构体的内容
struct fork_info
{
    struct data_size array;
    struct data_info *bins;
    int status;
    pid_t npid;
    int fd;
};

// 申请内存空间
int *allocate(int size)
{
    int *space;
    space = (int *)calloc(size, sizeof(int));
    if (space == NULL)
    {
        perror("Error allocate\n");
        exit(EXIT_FAILURE);
    }
    return space;
}

// 打印数据
void print_data(struct data_size array, char *txt)
{
    FILE *fp;
    char num_str[4] = {""};
 
    fp = fopen(txt, "w");
    if (fp == NULL)
    {
        perror("Error print data.");
        exit(EXIT_FAILURE);
    }
 
    for (int i = 0; i < array.size; i++)
    {
        sprintf(num_str, "%d", array.data[i]);
        fwrite(num_str, sizeof(num_str), 1, fp);
        fputc('\n', fp);
    }
    fclose(fp);
}

// 生成随机数据
void produce_data(struct data_size array)
{
    srand(1);
    for (int i = 0; i < array.size; i++)
    {
        array.data[i] = rand() % 1000;
    }
}

// 划分数据到缓存区
void split_data(struct data_size array, struct data_info bins[])
{
    for (int i = 0; i < array.size; i++)
    {
        int number = array.data[i];
        if (number < 250)
        {
            bins[0].data[bins[0].size++] = number;
        }
        else if (number < 500){
            bins[1].data[bins[1].size++] = number;
        }
        else if (number < 750)
        {
            bins[2].data[bins[2].size++] = number;
        }
        else
        {
            bins[3].data[bins[3].size++] = number;
        }
    }
}

// 转移数据
void move_back(struct data_size array, struct data_info bins[])
{
    for (int bin = 0; bin < 4; bin++)
    {
        for (int i = 0; i < bins[bin].size; i++)
        {
            *array.data++ = bins[bin].data[i];
        }
    }
}

// 排序
void insertion(struct data_info bin)
{
    for (int i = 1; i < bin.size; i++)
    {
        for (int j = i; j > 0; j--)
        {
            if (bin.data[j - 1] > bin.data[j])
            {
                int temp;
                temp = bin.data[j];
                bin.data[j] = bin.data[j - 1];
                bin.data[j - 1] = temp;
            }
            else
            {
                break;
            }
        }
    }
}

// 判断排序
bool is_sorted(struct data_size array)
{
    bool sorted = true;
    for (int i = 0; i < array.size - 1; i++)
    {
        if (array.data[i] > array.data[i + 1])
            sorted = false;
    }
    return sorted;
}


// 主函数
int main(int argc, char *argv[])
{
    // 初始化参数
    struct data_size array;
    struct data_info bins[4];
    struct fork_info forks[4];

    // 设置参数量
    if (argc < 2)
    {
        array.size = SIZE;
    }
    else
    {
        array.size = pow(2, atoi(argv[1]));
    }

    // 申请内存空间
    array.data = allocate(array.size);

    // 打印数据
    print_data(array, "original.txt");

    // 多进程-共享内存
    for (int i = 0; i < 4; i++)
    {
        bins[i].size = 0;

        forks[i].fd = open("/dev/zero", O_RDWR);

        if (-1 == forks[i].fd)
        {
            perror("Error open\n");
            exit(EXIT_FAILURE);
        }

        bins[i].data = mmap(NULL, array.size * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, forks[i].fd, 0);

        if (MAP_FAILED == bins[i].data)
        {
            perror("Problem allocate space.\n");
            exit(EXIT_FAILURE);
        }
    }

    // 生成随机数据
    produce_data(array);

    // 划分数据
    split_data(array, bins);
    // 计算总数据量
    int sum = 0;
    for (int i = 0; i < 4; i++)
    {
        sum += bins[i].size;
    }
    printf("Size=%d.\n", sum);

    // 多进程-共享内存
    for (int i = 0; i < 4; i++)
    {
        forks[i].bins = &bins[i];   // 多进程结构体去缓存区数据的首地址
        forks[i].npid = fork();     // 创建子进程

        if (forks[i].npid < 0)
        {
            perror("Error fork\n");
            exit(EXIT_FAILURE);
        }
        else if (forks[i].npid == 0)
        {
            insertion(*forks[i].bins);
            _exit(EXIT_SUCCESS);
        }
        else
        {

        }
    }

    for (int i = 0; i < 4; i++)
    {
        wait(&forks[i].status);     // 多线程同步
    }
    // 转移数据从缓存区到原始数据区
    move_back(array, bins);
    // 打印排序后的数据 
    print_data(array, "insertion.txt");

    // 判断是否排序正确
    printf(is_sorted(array) ? "sorted\n" : "not sorted\n");
 
    // 释放内存
    free(array.data);
    for (int i = 0; i < 4; i++)
    {
        munmap(bins[i].data, array.size * sizeof(int));
        close(forks[i].fd);
    }

    exit(EXIT_SUCCESS);
}



posted @ 2022-07-13 16:45  starc的miao  阅读(228)  评论(0)    收藏  举报