Assignment3 总结

任务:1. 用C语言写一个rgen.c,是一个random generator,产生的东西是assignment1(python script)的input。(assignment1的input是这样的:

a "Weber Street" (2,-1) (2,2) (5,5) (5,6) (3,8)
a "King Street S" (4,2) (4,8)
a "Davenport Road" (1,4) (5,8)
g


用户输入了以后就会generate一个ouput如下:

            2. assignment1的output是这样的:

V = {
1: (2,2)
2: (4,2)
3: (4,4)
4: (5,5)
5: (1,4)
6: (4,7)
7: (5,6)
8: (5,8)
9: (3,8)
10: (4,8)
}

E = {
<1,3>,
<2,3>,
<3,4>,
<3,6>,
<7,6>,
<6,5>,
<9,6>,
<6,8>,
<6,10>
}

修改这个output,使其格式为assignment2的input的格式(assignment2的input格式为:

V 15
E {<2,6>,<2,8>,<2,5>,<6,5>,<5,8>,<6,10>,<10,8>}

3. 用C语言写一个driver程序。将rgen的ouput送给assignment1,将assignment1的output送给assignment2,然后用户可以输入两个点然后程序返回最短路径。

sample running screenshot:


“V =” 和 “E = ” 后面的东西是经rgen随机产生assignment1可以接受的input之后,经过assignment1处理然后打印出assignment2可以接受的input之后assignment2打印出来的 。 


注意事项:1. assignment3是要接受commandline arguments(其实是rgen所需要的参数,全都optional,optional的话就用预设值)的,然后传给rgen。这里不多说参数都干什么的了。

2. 如果rgen随机产生数据,连续25次都没成功,就报错退出,如sample running screenshot所示。


别的不多说!开始总结知识点:

1. rgen.c中。我们需要随机产生一些数据。此次assignment要求必须使用/dev/urandom下的数据。 还有一个文件与urandom类似的叫random。区别见这里:http://blog.csdn.net/wind19/article/details/8085164

一个对这次assignment有用的区别是urandom可以一次读完,而random只能一次读一个byte。好像是这样。本次assignment用法:

int gen_random(int lower, int upper){
	unsigned int random;
	int random_fd = -1;
	if((random_fd = open("/dev/urandom", O_RDONLY)) < 0){
		fprintf(stderr, "Error: open /dev/urandom error\n");
		exit(1);
	}
	read(random_fd, &random, sizeof(unsigned int));
	random %= (upper - lower + 1); random += lower;
	close(random_fd);
	return random;
}
后面的求余数操作是因为我们想要得到[a,b] 范围内的一个随机整数。


2.rgen中需要对产生的随机的数据进行查验。 防止产生的两条line segment重叠。 我们检查两条线段是否重叠的方法是:

假设第一条线段的两个端点a,b。第二条线段的两个端点为c,d。

先看abc共不共线,若不共线,则不重叠。若共线,

再看abd共不共线,若不共线,则不重叠。若共线,

再看哪条线长,如果ab长,看c在不在ab中(不包含a,b),若在,则重叠,若不在,如果d在ab中(不包含a,b),则也一定重叠。

如果cd长,方法同上。

如果一样长,如果a,b和c,d分别相同,则点重叠,线段重叠。不相同,方法同上。

看哪条线长 的原因是因为有可能cd包在ab之中,也有可能ab包在cd之中,这样就不知道该用那个点去检测在不在另一条线段中间了。


3. driver中。用管道(重定向输入输出)+ (fork+exec)的方法将各个进程的输入输出串起来。

注意:由于重定向输入输出,可能有内容没能及时到管道中,而是在缓冲区中,这时需要用fflush(stdout)。而我选择的是关掉stdout的缓冲区:

setvbuf(stdout, NULL, _IONBF, 0);


在driver中,子进程1执行assignment1,子进程2执行rgen,子进程3执行assignment2。父进程用来循环获取用户输入,然后传给a2去算最短路径。


在子进程结束后,会发SIGCHLD信号给父进程,父进程可以在任何地方写一个:

signal(SIGCHLD, sig_handler);

sig_handler是个函数名,随便起名,用来处理这个信号。我写的函数为:

void sig_handler(int sig){
	if(sig == SIGCHLD){
		kill(pid1, SIGTERM);
		kill(pid3, SIGTERM);
		exit(0);
	}

}

如果有子进程结束,则父进程要结束其他子进程,并且自己退出。


管道重定向+fork+exec核心代码为:

<span style="white-space:pre">	</span>if(pipe(pipe_fd1) < 0){
		fprintf(stderr, "Error: pipe failed\n");
		exit(-1);
	}

	if(pipe(pipe_fd2) < 0){
		fprintf(stderr, "Error: pipe failed\n");
		exit(-1);
	}

	pid1 = fork();
	

	if(pid1 < 0){
		fprintf(stderr, "Error: fork() failed\n");
		exit(-1);
	}

	// first child process handles python
	if(pid1 == 0){
			
		close(pipe_fd1[1]);//close write port of pipe1
		close(0);//close stdin, prepare for redirection
		dup(pipe_fd1[0]);//redirect stdin to read port of pipe1
		close(pipe_fd1[0]);// after redirection, close write port of pipe1

		close(pipe_fd2[0]);
		close(1);
		dup(pipe_fd2[1]);
		close(pipe_fd2[1]);
	
		// parent of the second child process, execute python script
		execvp(comArgv2[0], comArgv2);
		fprintf(stderr, "Error: %s: program not found\n", comArgv2[0]);
		exit(-1);

	}

	pid2 = fork();
	if(pid2 < 0){
		fprintf(stderr, "Error: fork() failed\n");
		exit(-1);
	}

	// second child process handles rgen
	if(pid2 == 0){
			
		close(pipe_fd1[0]);
		close(1);
		dup(pipe_fd1[1]);
		close(pipe_fd1[1]);//newly added
		
		execvp(comArgv1[0], comArgv1);
		fprintf(stderr, "Error: %s: program not found\n", comArgv1[0]);
		exit(-1);
	
	}

	
	if((pid3 = fork()) > 0){

		close(pipe_fd2[0]);
		close(1);
		dup(pipe_fd2[1]);
		close(pipe_fd2[1]);

		while((fgets(readStr, SIZE, stdin)) != NULL){
			printf("%s\n", readStr);
		}
		
		
		kill(pid2, SIGTERM);
		kill(pid1, SIGTERM);
		kill(pid3, SIGTERM);
			
	}
	

	if(pid3 == 0){

		close(pipe_fd2[1]);
		close(0);
		dup(pipe_fd2[0]);
		close(pipe_fd2[0]);
	
		execvp(comArgv3[0], comArgv3);
		fprintf(stderr, "Error: %s: program not found\n", comArgv3[0]);
		exit(-1);

	}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值