第四章:基于TCP套接字编程(二)
fork函数
1.fork的简单例子
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <sys/wait.h> 4 5 int main() { 6 printf("hello world\n"); 7 int rc = fork(); 8 if (rc < 0) { 9 fprintf(stderr, "fork failed\n"); 10 } else if (rc == 0) { 11 printf("I am child, my pid is %d\n", getpid()); 12 } else { 13 printf("I am parent of (%d), my pid is %d\n", rc, getpid()); 14 } 15 return 0; 16 }
函数结果:
hello world I am parent of (479), my pid is 478 I am child, my pid is 479
调用fork
创建进程的一刹那,对于操作系统来说,此时此刻有两个完全一样的进程:原来的进程被称为父进程、新创建的被称为子进程。子进程不会从main
开始运行,而是直接从fork
系统调用返回。从返回值来看。
- 只打印了一次
hello world
,说明子进程并不是从main
开始运行的,而是从fork
直接返回,就好像自己调用了自己。 - 父进程中的
rc
等于子进程的pid
- 子进程的
rc
等于0
- 子进程与父进程的运行顺序是不一定的
2.fork的循环
1 #include <sys/types.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <stdio.h> 5 6 int main() 7 { 8 pid_t pid, ppid, pppid, ppppid; 9 int idx = -1; 10 11 for (int i = 0; i < 2; i++) { 12 pid = fork(); 13 printf("i == %d, pid== %d\n", i, getpid()); 14 /* 15 ppid = fork(); 16 printf("i == %d, ppid== %d\n", i, getpid()); 17 pppid = fork(); 18 printf("i == %d, pppid== %d\n", i, getpid()); 19 20 ppppid = fork(); 21 printf("i == %d, ppppid== %d\n", i, getpid()); 22 */ 23 } 24 25 26 while (1); 27 exit(0); 28 }
返回结果:
1 root@local:/mnt/d/workspace/vscode# ./fork 2 i == 0, pid== 485 3 i == 0, pid== 486 4 i == 1, pid== 485 5 i == 1, pid== 486 6 i == 1, pid== 487 7 i == 1, pid== 488
如果循环里边有两个fork呢?(16个)。三个fork呢?(64个)。四个fork呢?(256个)。
那如何限定fork的对象个数呢?
3.fork限定子进程的个数
1 #include <sys/types.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <stdio.h> 5 6 int main() 7 { 8 pid_t pid; 9 int idx = -1; 10 11 for (int i = 0; i < 2; i++) { 12 pid = fork(); 13 if (pid < 0) { 14 exit(-1); 15 } else if (pid > 0) { 16 printf("i == %d, ppid== %d\n", i, getpid()); 17 continue; 18 } else { 19 idx = i; 20 while (1) { 21 //printf("idx=%d\n", idx); 22 } 23 } 24 } 25 26 27 while (1); 28 exit(0); 29 } 30 31 32 //返回值 33 /* 34 root@local:/mnt/d/workspace/vscode# ./fork2 35 i == 0, ppid== 506 36 i == 1, ppid== 506 37 */
4.fork的注意点
fork()函数自身不保证子进程和父进程的执行顺序