操作系统导论OSTEP 第五章作业答案 插叙:进程API

操作系统导论OSTEP 专栏收录该内容
21 篇文章 0 订阅

答案Github库

https://github.com/jzplp/OSTEP-Answers

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main()
{
	int x = 100;
	printf("x = %d, (pid:%d)\n", x, (int)getpid());
	int rc = fork();
	if (rc < 0) {
		fprintf(stderr, "fork failed");
		exit(1);
	} else if (rc == 0) {
		printf("child x = %d (pid:%d)\n", x, (int)getpid());
		x = 200;
		printf("child after changed x = %d (pid:%d)\n", x, (int)getpid());
	} else {
		printf("parent x = %d (pid:%d)\n", x, (int)getpid());
		x = 300;
		printf("parent after changed x = %d (pid:%d)\n", x, (int)getpid());
	}
	return 0;
}

执行结果

[testjz@localhost OS_test]$ ./5.1
x = 100, (pid:6368)
parent x = 100 (pid:6368)
parent after changed x = 300 (pid:6368)
child x = 100 (pid:6369)
child after changed x = 200 (pid:6369)

子进程的变量子一开始与父进程相同。但是实际上父子进程中的同名变量已经不在同一内存区域,实际上是两个变量,因此父子进程的变量值改变不会影响另外一个进程。

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<string.h>
#include<sys/wait.h>

int main()
{
	int fd = open("./5.2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
	int rc = fork();
	if (rc < 0) {
		close(fd);
		fprintf(stderr, "fork failed");
		exit(1);
	} else if (rc == 0) {
		char * s = "child write something!\n";
		write(fd, s, strlen(s));
	} else {
		char * s = "parent write something\n";
		write(fd, s, strlen(s));
		wait(NULL);
		close(fd);
	}
	return 0;
}

执行结果

[testjz@localhost OS_test]$ ./5.2
[testjz@localhost OS_test]$ cat 5.2.txt
parent write something
child write something!

看起来都可以访问文件描述符并正常写入文件。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
	int rc = vfork();
	if (rc < 0) {
		fprintf(stderr, "fork failed");
		exit(1);
	} else if (rc == 0) {
		printf("hello\n");
		exit(1);
	} else {
		printf("goodbye\n");
	}
	return 0;
}

使用vfork,可以在子进程执行结束后再执行父进程。

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int flag = 0;
const int MAX = 6;
int main()
{
	char * s = "/bin/ls";
	char * ss = "ls";
	char * s2 = "/";
	char * sv[] = { ss, s2, NULL };
	for(flag = 0;flag < MAX; ++flag) {
		int rc = fork();
		if (rc < 0) {
			fprintf(stderr, "fork failed");
			exit(1);
		} else if (rc == 0) {
			switch(flag) {
			case 0:
				execl(s, ss, s2, NULL);
				break;
			case 1:
				execle(s, ss, s2, NULL);
				break;
			case 2:
				execlp(s, s, s2, NULL);
				break;
			case 3:
				execv(s, sv);
				break;
			case 4:
				execvp(ss, sv);
				break;
			case 5:
				execvpe(ss, sv);
				break;
			default: break;
			}
		} else {
			wait(NULL);
		}
	}
	return 0;
}

执行结果

[testjz@localhost OS_test]$ ./5.4
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr

有多种变体是为了要适应不同的调用形式和环境要求。

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>

int main()
{
	int rc = fork();
	int wc = wait(NULL);
	if(rc < 0) {
		fprintf(stderr, "fork failed");
		exit(1);
	} else if (rc == 0) {
		printf("child");
	} else {
		printf("parent");
	}
	printf("pid:%d wc:%d rc:%d\n", (int)getpid(), wc, rc);
	return 0;
}

执行结果

[testjz@localhost OS_test]$ ./5.5
childpid:14495 wc:-1 rc:0
parentpid:14494 wc:14495 rc:14495

父进程使用wait()返回子进程id,子进程由于本身没有子进程,所以返回-1。

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>

int main()
{
	int rc = fork();
	int wc = waitpid(rc, NULL, 0);
	if(rc < 0) {
		fprintf(stderr, "fork failed");
		exit(1);
	} else if (rc == 0) {
		printf("child");
	} else {
		printf("parent");
	}
	printf("pid:%d wc:%d rc:%d\n", (int)getpid(), wc, rc);
	return 0;
}

执行结果

[testjz@localhost OS_test]$ ./5.6
childpid:14607 wc:-1 rc:0
parentpid:14606 wc:14607 rc:14607

waitpid在进程本身有子进程的时候有用。

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main()
{
	int rc = fork();
	if (rc < 0) {
		fprintf(stderr, "fork failed");
		exit(1);
	} else if (rc == 0) {
		close(STDOUT_FILENO);
		printf("output child\n");
	}
	wait(NULL);
	return 0;
}

执行结果

[testjz@localhost OS_test]$ ./5.7
[testjz@localhost OS_test]$ 

无任何输出。

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main() {
	int pi[2];
	int p = pipe(pi);
	if(p < 0) {
		fprintf(stderr, "pipe failed");
		exit(1);
	}
	int i = 0;
	int rc[2];
	char buf[256];
	for(i=0;i<2;++i) {
		rc[i] = fork();
		if (rc[i] < 0) {
			fprintf(stderr, "fork failed");
			exit(1);
		} else if (rc[i] == 0) {
			switch(i) {
			case 0:
				dup2(pi[1], STDOUT_FILENO);
				puts("child input");
				break;
			case 1:
				dup2(pi[0], STDIN_FILENO);
				gets(buf);
				printf("child0 out (%s) in the child1\n", buf);
				return 2;
			}
			break;
		}
	}
	waitpid(rc[0], NULL, 0);
	waitpid(rc[1], NULL, 0);
	return 0;
}

执行结果

[testjz@localhost OS_test]$ ./5.8
child0 out (child input) in the child1
  • 4
    点赞
  • 6
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值