这类程序更多是为了说明你理解分叉是如何工作的,我希望你永远不要在多个嵌套循环中编写一个分叉程序,并带有中断。
他们跟踪这一点的方法是在纸上模拟机器,但每次模拟分叉时,你都会复制模拟,将一个副本的 fork() 的返回码设置为零,另一个的返回码复制到其他进程的pid。
让我重新格式化你的程序,让它更容易
int pid;
int i;
int j;
pid_t t;
将保存我们的进程的“当前值”。我们还将用“IP ==>”表示指令指针位置
int pid;
int i;
int j;
pid_t t;
IP ===>
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
下一步(对于 PID 1)
=== PROCESS 1 ====
int pid;
int i; (set to 0)
int j;
pid_t t;
for (i = 0; i < 2; i++) {
IP ===>
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
下一步(对于 PID 1)
=== PROCESS 1 ====
int pid (set to 1 // fake pid, but easy to count)
int i; (set to 0)
int j;
pid_t t;
for (i = 0; i < 2; i++) {
pid = getpid();
IP ===>
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
下一步(用于流程 1)
=== PROCESS 1 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t;
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
IP ===>
t = fork();
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
下一步(对于 PID 1)
=== PROCESS 1 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 2, parent process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 2 ===
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 2, parent process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
IP ===>
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 2 ===
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
下一步(对于 PID 1)
=== PROCESS 1 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 2, parent process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 2 ===
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 2, parent process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) {
IP ===>
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 2 ===
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 3, parent process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) {
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 2 ===
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 3 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child of PID 1)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) {
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 3, parent process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) {
t = fork();
break;
}
}
IP ===>
if (pid != getpid())
break;
}
=== PROCESS 2 ===
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 3 ====
int pid (set to 1)
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child of PID 1)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) {
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int pid = 1;
int i; (set to 0)
int j; (set to 1, due to j++)
pid_t t; (set to 3, parent process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
break;
}
}
if (pid != getpid()) // pid == 1, getpid == 1. so skip break
break;
IP ===>
}
=== PROCESS 2 ===
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 3 ====
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child of PID 1)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int pid = 1;
int i; (set to 1)
int j; (set to 1, due to j++)
pid_t t; (set to 3, parent process)
for (i = 0; i < 2; IP ===> i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
break;
}
}
if (pid != getpid()) // pid == 1, getpid == 1. so skip break
break;
}
=== PROCESS 2 ===
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 3 ====
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child of PID 1)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int pid = 1;
int i; (set to 1)
int j; (set to 1, due to j++)
pid_t t; (set to 3, parent process)
for (i = 0; IP ===> i < 2; i++) { // 1 is less than 2 so enter loop block
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
break;
}
}
if (pid != getpid()) // pid == 1, getpid == 1. so skip break
break;
}
=== PROCESS 2 ===
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 3 ====
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child of PID 1)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int pid = 1;
int i; (set to 1)
int j; (set to 1)
pid_t t; (set to 3, parent process)
for (i = 0; i < 2; i++) {
IP ===>
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
break;
}
}
if (pid != getpid()) // pid == 1, getpid == 1. so skip break
break;
}
=== PROCESS 2 ===
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 3 ====
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child of PID 1)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1, again)
int pid = 1;
int i; (set to 1)
int j; (set to 1)
pid_t t; (set to 3)
for (i = 0; i < 2; i++) {
pid = getpid();
IP ===>
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
break;
}
}
if (pid != getpid()) // pid == 1, getpid == 1. so skip break
break;
}
=== PROCESS 2 ===
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 3 ====
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child of PID 1)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
下一步(针对过程 1)
=== PROCESS 1 ====
int pid (set to 1)
int pid = 1;
int i; (set to 1)
int j; (set to 0)
pid_t t; (set to 3)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
IP ===>
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
break;
}
}
if (pid != getpid()) // pid == 1, getpid == 1. so skip break
break;
}
=== PROCESS 2 ===
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child process)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
IP ===>
if (t != 0) {
t = fork();
break;
}
}
if (pid != getpid())
break;
}
=== PROCESS 3 ====
int i; (set to 0)
int j; (set to 0)
pid_t t; (set to 0, child of PID 1)
for (i = 0; i < 2; i++) {
pid = getpid();
for (j = 0 ; j < i+2; j++){
t = fork();
if (t != 0) { // t == 2 in this process, so enter the block
t = fork();
IP ===>
break;
}
}
if (pid != getpid())
break;
}
等等。一旦您将进程 1 从其循环中取出(并等待其子进程完成),您对进程 2 执行相同的过程,直到它脱离循环并等待其子进程完成。
本练习的重点是您是否可以模拟一些令人困惑的流程代码。很明显,由于顶级进程将循环两次,并且它永远不会跳出循环,因此您将在其下获得 4 个进程。当您练习逐步完成其他流程时,您将开始看到它们实现的模式。
就个人而言,这类问题需要大量工作,而不是让你成为更好的程序员的工作;但是,它将证明您是否了解程序是以其当前状态分叉的(请注意,许多孩子的 pid 是错误的,因为它在分叉后没有更新),如果您完全理解,您可以模拟程序最终完成。
当然,我们使用计算机来自动处理无聊的事情(像这样),所以你可能想想出一个像这样的新日志行:
void printState(int me, int pid, int i, int j, int t) {
printf("PID %d: pid = %d, i = %d, j = %d, t = %d\n");
}
然后运行
printState(getpid(), pid, i, j, t);
for (i = 0; i < 2; i++) {
printState(getpid(), pid, i, j, t);
pid = getpid();
printState(getpid(), pid, i, j, t);
for (j = 0 ; j < i+2; j++){
printState(getpid(), pid, i, j, t);
t = fork();
printState(getpid(), pid, i, j, t);
if (t != 0) {
printState(getpid(), pid, i, j, t);
t = fork();
printState(getpid(), pid, i, j, t);
break;
}
}
if (pid != getpid())
printState(getpid(), pid, i, j, t);
break;
}
并收集输出,按照他们自己报告的 pid 编号(getpid(),而不是 pid 变量)对它们进行排序