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;
}

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;
}

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;
}

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

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;
}

posted on
浙公网安备 33010602011771号