- 介绍
fork()系统调用用于创建一个新进程,称为子进程,他与进程(成为系统调用fork的进程)同时运行,此进程称为父进程。创建新的子进程后,两个进程将执行fork()系统调用之后的下一条指令。子进程使用相同得pc(程序计数器),相同的CPU寄存器,在父进程中使用的相同打开文件。其返回值如下:
1. 负值:创建子进程失败。
2. 零:返回到新创建的子进程。
3. 正值:返回父进程,该值包含新创建的子进程的进乘ID。
- 包含其头文件
#include<unistd.h>
#include<sys/types.h>
Linux下有两个系统调用的创建子进程的函数分别是fork()
和vfork()
,后面会介绍两个函数的区别和用法。fork()
函数被称为分叉函数,一般的函数一次调用只会有一次返回,fork()
函数会有两次返回,上面提到返回给父进程的是子进程的PID(进程号),返回给子进程的是0,返回负值则说明创建失败,可能有如下两个原因:
1. 系统中有太多进程。
2. 当前用户ID的进程数超过系统限制。
通常我们也通过返回值判定是哪个进程在运行。
在Linux内核启动过程中最后会创建一个init进程(初始化进程),执行程序/sbin/init,该进程是Linux系统运行的第一个进程因此其进程号为1,它不会被“杀死”,接下来他会创建其他子进程启动相应的系统服务,每个服务可以创建不同子进程执行不同程序,通过ps aux
命令可查看此时系统维护正在运行的进程的进程表:
panghu@Ubuntu-14:~/socket$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 33920 4468 ? Ss 2月16 0:04 /sbin/init //1号进程 init进程
root 2 0.0 0.0 0 0 ? S 2月16 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 2月16 0:01 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< 2月16 0:00 [kworker/0:0H]
root 7 0.0 0.0 0 0 ? S 2月16 1:24 [rcu_sched]
root 8 0.0 0.0 0 0 ? S 2月16 0:00 [rcu_bh]
root 9 0.0 0.0 0 0 ? S 2月16 0:00 [migration/0]
root 10 0.0 0.0 0 0 ? S 2月16 0:05 [watchdog/0]
root 11 0.0 0.0 0 0 ? S 2月16 0:00 [kdevtmpfs]
root 12 0.0 0.0 0 0 ? S< 2月16 0:00 [netns]
root 13 0.0 0.0 0 0 ? S< 2月16 0:00 [perf]
··········
通过对相应进程的PID(进程号)操作,可对其进行开启、关闭等管理。
通过其名字可知,每个父进程都有无数个子进程,一个子进程只能有一个父进程,进程通过getpid()
函数可获取自己的PID(进程号),通过getppid()
获取其父进程的PID(进程号),通过下列了解下fork()创建进程的过程:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main