ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

多线程排序-v33-多进程-管道通信

2022-07-13 15:05:39  阅读:168  来源: 互联网

标签:v33 int 排序 array 多线程 data forks bins size


makefile

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

v33.c

// 多线程排序-多进程-管道通信-V33
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/resource.h>
#include <stdlib.h>
#include <unistd.h>

#define SIZE 16

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

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

// 注意多进程结构体的内容
struct fork_info
{
    struct data_size array;
    struct data_info *bins;
    int status;
    pid_t npid;
    int pipefd[2];  // pipe管道创建的两个文件描述符,读和写
};

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

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

// 打印数据
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 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 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;
            }
        }
    }
}

// 转移数据
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];
        }
    }
}

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);
    for (int i = 0; i < 4; i++)
    {
        bins[i].size = 0;
        bins[i].data = allocate(array.size);
    }

    // 初始数据
    produce_data(array);

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

    // 分配数据到缓存数据区
    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];   // 注意使用取地址符
        if (pipe(forks[i].pipefd) < 0)   // 创建管道文件描述符,读和写
        {
            perror("Error pipe");
            exit(EXIT_FAILURE);
        }

        forks[i].npid = fork();   // 创建子进程

        if (forks[i].npid < 0)      // 创建子进程失败
        {
            perror("Error fork");
            exit(EXIT_FAILURE);
        }   
        else if (forks[i].npid == 0)    // 子进程
        {
            insertion(*forks[i].bins);  // 多进程的排序,使用的是带星号

            close(forks[i].pipefd[0]);
            write(forks[i].pipefd[1], &forks[i].bins->data[0], sizeof(int) * forks[i].bins->size);
            close(forks[i].pipefd[1]);

            _exit(EXIT_SUCCESS);
        }
        else                        // 父进程
        {
            close(forks[i].pipefd[1]);

            int pos = 0;
            int size = 0;

            while ((size = read(forks[i].pipefd[0], forks[i].bins->data + pos / sizeof(int), sizeof(int) * forks[i].bins->size)) > 0)
            {
                printf("child[%d] pipe pos=%d size=%d\n", i, pos, size);
                pos += size;
            };
            close(forks[i].pipefd[0]);
        }
    }

    // 进程同步
    for (int i = 0; i < 4; i++)
    {
        waitpid(forks[i].npid, &forks[i].status, 0);
    }

    // 转移数据从缓存区到原始数据区
    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++)
    {
        free(bins[i].data);
    }
    exit(EXIT_SUCCESS);
}

标签:v33,int,排序,array,多线程,data,forks,bins,size
来源: https://www.cnblogs.com/starc/p/16473861.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有