模拟多核,多进程构建pipe ring, 并对多个数进行排序

1. 问题描述:

1.1 pipe ring。

如图,是四个进程形成的一个环结构,“Orig Process”是初始的Master进程,它首先创建了进程"Child 1",然后"Child 1"创建"Child 2", "Child 2" 创建“Child 3”。这个环通过pipe连接起来,如同一个单向循环链表。比如“Child 1”可从其父进程“Orig Process”读取数据,也可发送数据给它的子进程“Child 2”。这个图中的相邻两个进程都指向一个共同的pipe文件,父进程可以只往里面写数据,而子进程只可以从里面读取数据。关于pipe的知识可以参考文档

1.2 pipe sorting。现在我们用这个环结构来实现一个排序算法,用n个进程对m个数进行排序,这里我们称其

为pipe sorting。

pipe sorting定义:这里取n=m。在这个环中,只有除Master进程外的进程参与排序过程,Master进程每次发送一个数a给"Child 1","Child 1"接收到来自Master的值a后,将其与它的当前值curr(初始为为一很小的值,这里取0)进行比较,它将保存较小值并将较大那个值发送给"Child 2"。每个子进程都将进行同样的操作:从"Child i-1"接收数据,保存较小值,然后发送较大值到"Child i+1"。在"Child i"进行了n-i+1次这样的操作后,它边保存着序列中的i-th largest value。最后每个进程将它的最终保存值通过这个环发送给Master进程。Master进程依次搜集这些进程的结果,并以降序打印。

主要有两个目标:

a. 用n个进程和pipe,构建一个虚拟的pipe ring.

b.利用pipe ring,对n个数进行排序,实现pipe sorting.

2. 问题分析:

2.1 构建pipe ring.

用fork这个函数创建子进程,子进程是父进程的克隆,即父子进程拥有相同的内存镜像,打开文件列表等数据,可参考文档。因此如果在父进程打开一个pipe文件,那么子进程也会拥有这个pipe的所有文件描述符信息。

另外还要用到dup2(oldfd,newfd)这个函数,参考文档,有句很关键的话是:if the file descriptor newfd was previously open, it is silently closed before being resued。并且这个操作是"原子的"。

比如: dup2(fd[1],1)做了两件事:

a.检查文件描述符'1'是否之前被打开了,如果是则关闭它。

b.将'1'指向fd[1]指向的文件。

这两步是'atomically',不可在两步之间中断。

//create pipe ring
pid_t pid;
int fd[2];
pipe(fd);
dup2(fd[0],0);
dup2(fd[1],1);
close(fd[0]);
close(fd[1]);
	
int i;
for(i = 0; i < N; i++) {
	pipe(fd);
	pid = fork();
	if(pid > 0) {
	   if(dup2(fd[1],1) == -1)
			perror("error dup2");
	} else {
	   	if(dup2(fd[0],0) == -1)
		    perror("error dup2");
	}
	close(fd[0]);
	close(fd[1]);
	if(pid > 0) break;
}

2.2 pipe sorting.

/* pipe sort 伪代码 */
index = i;
if(index == 0) {
	//in master process
	i = 0;
	/* read data from file and send to child one by one */
	while(i++ < CountOfNumber) {
		1. read data from file and save in data
		2. write(1,&data,sizeof(int));
	}
	3. collect result.
	i = 0;
	while(i++ < CountOfNum) {
		read(0,&sorted[i],sizeof(int));
	}
	4. print out result.
} else {
	//in child i
	local_value = 0;
	count = N - index + 1;
	/* keep smaller one and send bigger one to child i+1 */
	while(count --) {
		1. read(0,&data,sizeof(int));
		2. data = max(local_value,data);
		3. write(1,&data,sizeof(int));
	}
	/* send result to master */
	write_time = index;
	read_time = index - 1;
	coutn - index;
	i = 0,j = 0;
	while(count --) {
		if(i++ < write_time)
			write(1,&data,sizeof(int));
		if(j++ < read_time)
			read(0,&data,sizeof(int));
	}
}
3. 完整源代码下载点这里。代码要求在cygwin或linux环境下编译运行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值