fork系统调用用于创建一个新进程,称为子进程,它与进程(称为系统调用fork的进程)同时运行,此进程称为父进程。创建新的子进程后,两个进程将执行fork()系统调用之后的下一条指令。
通过man
命令简单查看一下:man fork
基本概念
每个进程都由进程号来标识,其类型为 pid_t(整型),进程号的范围:0~32767。进程号总是唯一的,但可以重用。当一个进程终止后,其进程号就可以再次使用。
任何进程(除 init 进程)都是由另一个进程创建,该进程称为被创建进程的父进程,对应的进程号称为父进程号(PPID)。
进程组是一个或多个进程的集合。他们之间相互关联,进程组可以接收同一终端的各种信号,关联的进程有一个进程组号(PGID)。默认情况下,当前的进程号会当做当前的进程组号
进程号和进程组相关函数
fork()
函数用法
pid_t fork(void);函数的作用:用于创建子进程。包含头文件:#include #include 返回值:fork()的返回值会返回两次。一次是在父进程中,一次是在子进程中。在父进程中返回创建的子进程的ID,在子进程中返回0在父进程中返回-1,表示创建子进程失败,并且设置errno
先来看一个最简单的例子
#include
#include
#include
int main()
{// 创建子进程pid_t pid = fork();// 判断是父进程还是子进程if(pid > 0) {printf("pid : %d\n", pid);// 如果大于0,返回的是创建的子进程的进程号,当前是父进程printf("i am parent process, pid : %d, ppid : %d\n", getpid(), getppid());} else if(pid == 0) {// 当前是子进程printf("i am child process, pid : %d, ppid : %d\n", getpid(),getppid());}for(int i = 0; i < 3; i++) {printf("i : %d , pid : %d\n", i , getpid());sleep(1);}return 0;
}
输出结果
(base) user@ubuntu:~/Desktop/OS/NiuKe$ gcc -o test test.c -std=c99
(base) user@ubuntu:~/Desktop/OS/NiuKe$ ./test
pid : 3274
i am parent process, pid : 3273, ppid : 2077
i : 0 , pid : 3273
i am child process, pid : 3274, ppid : 3273
i : 0 , pid : 3274
i : 1 , pid : 3273
i : 1 , pid : 3274
i : 2 , pid : 3273
i : 2 , pid : 3274
这个程序比较简单,唯一值得注意的是输出结果的这个语句i : 0 , pid : 3273
。
原因是fork之后父进程先执行还是子进程先执行不确定,取决于内核所使用的调度算法。
program
#include
#include
#include int main()
{int n=2;for(int i=0;ifork();printf("A\n");}return 0;
}
输出结果
(base) user@ubuntu:~/Desktop/OS/NiuKe$ gcc -o fork fork.c -std=c99
(base) user@ubuntu:~/Desktop/OS/NiuKe$ ./fork
A
A
A
A
A
A
代码共打印6个A,创建3个子进程。
【注意】:‘\n’:会自动刷新缓冲区。即遇到\n会自动刷新缓冲区。
program
我们把上面程序的\n删除掉在试一下。
#include
#include
#include int main()
{int n=2;for(int i=0;ifork();printf("A");}return 0;
}
输出结果
(base) user@ubuntu:~/Desktop/OS/NiuKe$ gcc -o fork fork.c -std=c99
(base) user@ubuntu:~/Desktop/OS/NiuKe$ ./fork
AAAA(base) user@ubuntu:~/Desktop/OS/NiuKe$ AAAA
代码共打印8个A。
使用 GDB 调试的时候,GDB 默认只能跟踪一个进程,可以在 fork 函数调用之前,通过指令设置 GDB 调试工具跟踪父进程或者是跟踪子进程,默认跟踪父进程。
设置调试父进程或者子进程:set follow-fork-mode [parent(默认)| child]
。
设置调试模式:set detach-on-fork [on | off]
默认为 on
,表示调试当前进程的时候,其它的进程继续运行,如果为 off
,调试当前进程的时候,其它进程被 GDB
挂起。
查看调试的进程:info inferiors
。
切换当前调试的进程:inferior Num
。
使进程脱离 GDB 调试:detach inferiors Num
。
参考资料:89-多进程开发:GDB多进程调试