Skip to content

Latest commit

 

History

History
307 lines (292 loc) · 5.87 KB

Chapter-5-Homework-Answers.md

File metadata and controls

307 lines (292 loc) · 5.87 KB
#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