1.基本了解:
一个进程,包括代码、数据和分配给进程的资源。fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1。
为什么两个进程的fpid不同呢?
这与fork函数的特性有关。fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
2.fork函数的了解:
#include <sys/types.h>
#include <unistd.h>pid_t fork(void);
函数返回类型 pid_t 实质是 int 类型,Linux 内核 2.4.0 版本的定义是:
typedef int _kenrnel_pid_t;
typedef _kenrnel_pid_t pid_t;
fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。
在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1(此时才能更好理解他的返回值)。
获取进程pid:getpid()
简单判断父子进程demo
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid_F;
pid_t pid_fork;
pid_F = getpid();
printf("pid_F=%d\n",pid_F);
pid_fork = fork();
if(pid_fork > 0){
printf("This is father\n");
printf("father pid = %d\n",getpid());
}else if(pid_fork == 0){
printf("\n\nThis is child\n");
printf("child pid = %d\n",getpid());
}
return 0;
}
还有一个类似的vfork函数
原型:
#include <sys/types.h>
#include <unistd.h>pid_t vfork(void);
fork和vfork的区别:
1)fork(): 父子进程的执行次序不确定。
vfork():保证子进程先运行,在它调用 exec(进程替换) 或 exit(退出进程)之后父进程才可能被调度运行。
2)fork(): 子进程拷贝父进程的地址空间,子进程是父进程的一个复制品。
vfork():子进程共享父进程的地址空间(准确来说,在调用 exec(进程替换) 或 exit(退出进程) 之前与父进程数据是共享的
简单的验证demo:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int mark = 0;
pid = vfork();
while(1){
if(pid > 0){
printf("This is father PID:%d\n",getpid());
printf("mark:%d\n",mark);
sleep(2);
}else if(pid == 0){
printf("This is child PID:%d\n",getpid());
mark++;
printf("mark:%d\n",mark);
sleep(2);
if(mark > 2){
printf("child exit!!!\n");
exit(-1);
}
}
}
return 0;
}
进程退出:
1.Main函数调用return
在main函数中执行return可以终止进程,并将控制权交给调用函数。一般原则程序执行正常退出return 0,而执行函数出错退出return -1。2.进程调用exit——标准C库
exit()是一个标准C库函数,执行exit()会进行一些清理工作,最后调用_exit()函数。
函数原型:
void exit(int status);3.进程调用_exit()或者_Exit(),属于系统调用
_Exit()和_exit()等价,都属于系统调用,使用_exit()会清除其使用的内存空间,并销毁其在内核中的数据结构,关闭进程的所有文件描述符,并结束进程、将控制权交给操作系统。
函数原型:
void _exit(int status);
调用函数需要传入status状态标志,0表示正常结束、若为其它值则表示程序执行过程中检测到有错误发生。
父进程等待子进程退出参考下面文章:
(46条消息) 父进程等待子进程退出_杨映春的博客-CSDN博客_父进程不等待子进程结束
什么是孤儿进程? 什么是僵尸进程?
1、孤儿进程
父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程就叫做孤儿进程。
Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程。
Pid==1,init进程(初始化进程)2、僵尸进程
僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。(也就是子进程的退出状态不被收集)。