进程的创建过程,是子进程通过拷贝父进程得到的,新进程的创建直接拷贝父进程的资源,只需改变很少部分的数据即可,保留了父进程的大部分的数据信息(遗传基因),所以这个拷贝过程,系统通过一个函数fork来自动完成
1、进程的创建:fork
bash
pid_t fork(void);
功能:通过拷贝父进程得到一个子进程
参数:无
返回值:成功在父进程中得到子进程的pid,在子进程中的到0,失败返回-1并置位错误码
- 无返回值的案例
bash
int main()
{
printf("ni hao zxp\n");
fork();
printf("hello\n");
while(1);
return 0;
}
运行结果
bash
ni hao zxp
hello
hello
- 多个fork创建进程
如果不关注返回值的话,有n个fork,会产生2^n个进程 - 有返回值
bash
int main(int argc, const char *argv[])
{
pid_t pid = -1;
pid = fork(); //创建一个子进程,父进程会将返回值赋值给父进程中的pid变量
//子进程会将返回值赋值给子进程中的pid变量
printf("pid = %d\n", pid); //对于父进程而言会得到大于0的数字,对于子进程而言会
得到0
//对pid进程判断
if(pid > 0)
{
//父进程要做执行的代码
printf("我是父进程\n");
}else if(pid == 0)
{
//子进程要执行的代码
printf("我是子进程\n");
}else
{
perror("fork error");
return -1;
}
while(1); //防止进程结束
return 0;
}
bash
pid=2121
我是父进程
pid=0
我是子进程
2、父进程号的获取:getpid、getppid
pid_t getpid():获取当前进程的进程号
pid_t getppid():获取当前进程的父进程pid号
3、进程退出:exit/_exit
exit属于库函数,使用该函数退出进程时,会刷新标准IO的缓冲区后退出
_exit属于系统调用(内核提供的函数),使用该函数退出进程时,不会刷新标准IO的缓冲区
4、进程资源的回收:wait、waitpid
wait是阻塞回收任意一个子进程的资源函数
waitpid:可以阻塞,也可以非阻塞完成对指定的进程号进程资源回收
bash
pid_t waitpid(pid_t pid, int *status, int options);
功能:可以阻塞也可以非阻塞回收指定进程的资源
参数1:进程号
>0 :表示回收指定的进程
=0:表示回收当前所在的进程组中的任意一个子进程
=-1:表示回收任意一个子进程
<-1:表示回收指定进程组中的任意一个子进程,进程组id为给定的pid的绝对值
参数2:接收子进程退出时的状态,获取子进程退出时的状态与0377进行位与后的结果,如果不愿意接收,可以填NULL
参数3:是否阻塞
0:表示非阻塞等待
WNOHANG:表示非阻塞
返回值:
>0:返回的是成功回收的子进程pid号
=0:表示本次没有回收的子进程
=-1:出错并置位错误码
5、僵尸进程和孤儿进程
- 孤儿进程:当前进程还正在运行,其父进程已经退出了
- 僵尸进程:当前进程已经退出了,但是其父进程没有为其回收资源