1.编写一个调用fork()的程序。谁调用fork()之前,让主进程访问一个变量(例如x)并将其值设置为某个值(例如 100)。子进程中的变量有什么值?当子进程和父进程都改变x的值,变量会发生什么?

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

int main(void)
{
	int x = 100;

	pid_t pid = fork();
	if (pid < 0) {
		fprintf(stderr, "fork failed\n");
		exit(1);
	} else if (pid == 0) {
		printf("x in child (do nothing): %d\n", x);
		x = 50;
		printf("x in child (change value): %d\n", x);
	} else {
		printf("x in parent (do nothing): %d\n", x);
		x = 90;
		printf("x in parent (change value): %d\n", x);
		wait(NULL);
	}

	return 0;
}

1

2.编写一个打开文件的程序(使用open()系统调用),然后调用fork()创建一个新进程。子进程和父进程都可以访问open()返回的文件描述符吗?当它们并发(即同时)写入文件时,会发生什么?

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

int main(void)
{
	int fd = open("test.txt", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU);
	if (fd < 0) exit(1);

	pid_t pid = fork();
	if (pid < 0) {
		exit(1);
	} else if (pid == 0) {
		write(fd, "hello", 5);
	} else {
		write(fd, "world", 5);
		wait(NULL);
	}

	return 0;
}

2

3.使用fork()编写另一个程序。子进程应打印“hello”,父进程应打印“goodbye”。你应该尝试确保子进程始终先打印。你能否不在父进程调用wait()而做到这一点呢?

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

int main(void)
{
	pid_t pid = fork();
	if (pid < 0) {
		exit(1);
	} else if (pid == 0) {
		printf("hello\n");
	} else {
		sleep(1);
		printf("goodbye\n");
	}

	return 0;
}

3

4.编写一个调用fork()的程序,然后调用某种形式的exec()来运行程序/bin/ls。看看是否可以尝试exec()的所有变体,包括execl()、execle()、execlp()、execv()、execvp()和 execvP()。为什么同样的基本调用会有这谁多变种?

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

int main(void)
{
    if (fork() == 0) {
        execl("/bin/echo", "echo", "This is execl()", NULL);
    }
    wait(NULL);

    if (fork() == 0) {
        char *const env[] = {"MY_HOME=DYLARIS", NULL};
        execle("/bin/echo", "echo", "This is execle()", NULL, env);
    }
    wait(NULL);

    if (fork() == 0) {
        execlp("echo", "echo", "This is execlp()", NULL);
    }
    wait(NULL);

    if (fork() == 0) {
        char *const args[] = {"echo", "This is execv()", NULL};
        execv("/bin/echo", args);
    }
    wait(NULL);

    if (fork() == 0) {
        char *const args[] = {"echo", "This is execvp()", NULL};
        execvp("echo", args);
    }
    wait(NULL);

    if (fork() == 0) {
        char *const args[] = {"echo", "This is execvpe()", NULL};
        char *const env[] = {"MY_HOME=DYLARIS", NULL};
        execvpe("echo", args, env);
    }
    wait(NULL);

    return 0;
}

5.现在编写一个程序,在父进程中使用wait(),等待子进程完成。wait()返回什么?如果你在子进程中使用wait()会发生什么?

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

int main(void)
{
	pid_t pid = fork();
	if (pid < 0) {
		exit(1);
	} else if (pid == 0) {
		printf("child process (pid:%d)\n", (int) getpid());
		int status = (int) wait(NULL);
		printf("Child: wait return value is: %d\n", status);
	} else {
		int status = (int) wait(NULL);
		printf("Parent: wait return value is: %d\n", status);
	}

	return 0;
}

父进程中wait调用返回的是子进程的进程号,子进程中的wait调用返回-1

4

6.对前一个程序稍作修改,这次使用waitpid()而不是wait()。什么时候waitpid()会有用?

waitpid可以指定要等待的子进程,wait等待随便一个子进程

7.编写一个创建子进程的程序,然后在子进程中关闭标准输(STDOUT_FILENO)。如果子进程在关闭描述符后调用printf()打印输出,会发生什么?

什么都不会打印,输出丢失

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

int main(void)
{
	pid_t pid = fork();
	if (pid < 0) {
		exit(1);
	} else if (pid == 0) {
		close(STDOUT_FILENO);
		printf("Child: print after closing stdout\n");
	} else {
		wait(NULL);
	}

	return 0;
}

8.编写一个程序,创建两个子进程,并使用 pipe()系统调用,将一个子进程的标准输出连接到另一个子进程的标准输入。

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

int main(void)
{
	int pipe_fd[2]; 	/* 0 is read, 1 is write */
	if (pipe(pipe_fd) < 0) exit(1);

	pid_t pid = fork();
	if (pid < 0) {
		exit(1);
	} else if (pid == 0) {
		/* First child process (redirect stdout to pipe write end) */
		close(pipe_fd[0]); /* Close pipe read end (don't use) */
		close(STDOUT_FILENO);
		dup(pipe_fd[1]); /* stdout is pipe write end now */
		close(pipe_fd[1]); /* Close original pipe write end */
		write(STDOUT_FILENO, "Hello, I am first child process", 32);
		exit(0);
	} else {
		/* Parent process */
		pid = fork();
		if (pid < 0) {
			exit(1);
		} else if (pid == 0) {
			/* Second child process (redirect stdin to pipe read end) */
			close(pipe_fd[1]); /* Close pipe write end (don't use) */
			close(STDIN_FILENO);
			dup(pipe_fd[0]); /* stdin is pipe read end now */
			close(pipe_fd[0]); /* Close original pipe read end */
			char buf[50];
			read(STDIN_FILENO, buf, 50);
			printf("Hello, I am second child process\nAnd I received message: %s\n", buf);
			exit(0);
		} else {
			/* Parent process */
			close(pipe_fd[0]);	/* Parent don't use pipe fd */
			close(pipe_fd[1]); 	/* Parent don't use pipe fd */
			wait(NULL);
			wait(NULL);
		}
	}

	return 0;
}

8

 posted on 2025-04-12 15:07  Dylaris  阅读(12)  评论(0)    收藏  举报