vfork也可以创建进程,与fork的区别?
- fork()用于创建一个新进程。由fork()创建的子进程是父进程的副本。即子进程获取父进程数据空间,堆和 栈的副本。父子进程之间不共享这些存储空间的部分。而vfork()创建的进程并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec (或exit)于是也就不会存放该地址空间。相反,在子进程调用exec或exit之前,它在父进程的空间进行。
- vfork保证子进程先运行,当子进程调用exit(-1)退出后,父进程才执行
相同:
两者被调用一次,但是返回两次。两次返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程ID。
code:demo10.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t retpid;
pid_t pid;
int cnt=0;
retpid=vfork();
pid=getpid();
if(retpid > 0){
while(1){
printf("father pid each run one,pid:%d\n",pid);
sleep(1);
printf("cnt:%d\n",cnt);
}
}
else if(retpid == 0){
while(1){
printf("child pid each run one,pid:%d\n",pid);
sleep(1);
cnt++;
if(cnt == 3){
exit(-1);
}
}
}
return 0;
}
运行结果:
CLC@Embed_Learn:~/LinuxLearn/PID$ ./one
child pid each run one,pid:44398
child pid each run one,pid:44398
child pid each run one,pid:44398
father pid each run one,pid:44397
cnt:3
father pid each run one,pid:44397
cnt:3
father pid each run one,pid:44397
cnt:3
father pid each run one,pid:44397
cnt:3
father pid each run one,pid:44397
^c
进程的退出
- 正常退出
- 异常退出
正常退出:
- Main函数调用 return
- 进程调用exit(),标准的C库
- 进程调用_exit或者_Exit(),属于系统调用
补充: - 进程最后一个线程返回
- 最后一个线程调用pthread_exit
异常退出:
1、调用abort
2、当进程收到某些信号时,如ctrl + c
3、 最后一个线程对取消(cancellation),请求作出响应
- 不管进程如何终止,最后都会执行内核中的同一段代码。这段代码为相应进程关闭所有打开描述符,释放它所使用的存储器等等。
- 对上述任意一种终止情形,我们都希望终止进程能够通知其父进程它是如何终止的。对于exit和_exit,这是依靠传递给它们的退出状态( exit status)参数来实现的。在异常终止情况,内核(不是进程本身)产生一个指示其异常终止原因的终止状(termination status)。在任意一种情况下,该终止进程的父进程都能用wait或waitpid函数(在下一节说明)取得其终止状态。
code:demo11.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t retpid;
pid_t pid;
int cnt=0;
retpid=vfork();
pid=getpid();
if(retpid > 0){
while(1){
printf("father pid each run one,pid:%d\n",pid);
sleep(1);
printf("cnt:%d\n",cnt);
}
}
else if(retpid == 0){
while(1){
printf("child pid each run one,pid:%d\n",pid);
sleep(1);
cnt++;
if(cnt == 3){
exit(-1);
// _exit(0);
// _Exit(0);
// break; //This exit to cnt appear messy code
}
}
}
return 0;
}