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