Simulate multi-core, multi-process build pipe ring, and sort multiple numbers

1. Problem description:

1.1 pipe ring。

As shown in the figure, it is a ring structure formed by four processes . "Orig Process" is the initial Master process. It first creates the process "Child 1", then "Child 1" creates "Child 2", "Child 2" creates " Child 3". This ring is connected by pipes, like a one-way circular linked list. For example, "Child 1" can read data from its parent process "Orig Process" and can also send data to its child process "Child 2". The two adjacent processes in this figure point to a common pipe file. The parent process can only write data to it, while the child process can only read data from it. You can refer to the documentation for knowledge of pipe .

1.2 pipe sorting. Now we use this ring structure to implement a sorting algorithm, using n processes to sort m numbers, here we call it

为pipe sorting。

Definition of pipe sorting : n=m here. In this ring, only processes other than the Master process participate in the sorting process. The Master process sends a number a to "Child 1" each time. After "Child 1" receives the value a from the Master, it compares it with its current value. curr (initially a small value, here is 0) for comparison, it will save the smaller value and send the larger value to "Child 2". Each child process will do the same: receive data from "Child i-1", save the smaller value, and then send the larger value to "Child i+1". After "Child i" has performed such operations n-i+1 times, it holds thei-th largest valuein the sequence. Finally, each process sends its final saved value to the Master process through this ring. The Master process collects the results of these processes in turn, and prints them in descending order.

There are two main goals:

a. Use n processes and pipes to build a virtual pipe ring.

b. Use pipe ring to sort n numbers to realize pipe sorting.

2. Problem analysis:

2.1 Build pipe ring.

Use the fork function to create a child process, the child process is a clone of the parent process, that is, the parent and child processes have the same memory mirror, open file list and other data, please refer to the document . Therefore, if a pipe file is opened in the parent process, the child process will also have all the file descriptor information of the pipe.

In addition, the function dup2 (oldfd, newfd) is also used. Refer to the documentation . There is a very key sentence: if the file descriptor newfd was previously open, it is silently closed before being resued. And this operation is "atomic".

For example: dup2(fd[1],1) does two things:

a. Check whether the file descriptor '1' has been opened before, and close it if it is.

b. Point '1' to the file pointed to by fd[1].

These two steps are'atomically' and cannot be interrupted between the two steps.

//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. To download the complete source code , click here . The code must be compiled and run in cygwin or linux environment.

Guess you like

Origin blog.csdn.net/lx1848/article/details/52199061