进程创建(fork,vfork),fork与vfork的区别,进程退出(exit)
1.使用fork函数创建一个进程:
fork函数调用成功,返回两次
返回值为0,代表当前进程为子进程
返回值为非负数,代表当前进程为父进程
调用失败,返回 -1 //pid=fork();
#include <unistd.h>
Pid_t fork(void);
2.获取当前的进程ID号:
#include <sys/types.h>
#include <unistd.h>
pid_t pid;
pid=getpid();
printf("my pid :%d\n",pid);
代码演示demo2.c:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid=getpid();
fork();//创建一个进程,两个进程在运行,返回两个pid
if(pid==getpid())
{
printf("fujincheng\n");
}else
{
printf("zijincheng\n");
}
printf("my pid :%d\n当前pid:%d\n",pid,getpid());
return 0;
}
运行结果:
3.创建进程发生了什么事?
fork:拷贝一份,之后执行两个进程
内存也拷贝了一份,写时拷贝,子进程动手脚时候才分配新空间,
不能共享同样的空间:例如:a=10;a=a+10;//出错
可以共享正文段:代码段
4.创建新进程的应用场景及fork总结
Fork创建子进程的一般目的:
A:父进程希望子进程复制自己,使父子进程同时执行不同的代码段。这在网络服务进程中是最常见的:
-----父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求到达.
B:一个进程要执行一个不同的程序。这对shell是常见的情况。在这种情况下,子进程从fork返回后立即调用exec。
演示代码:网络服务进程:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int data;
pid_t pid;
//pid=getpid();
while(1)
{
printf("请输入数据:\n");
scanf("%d",&data);
if(data==1)
{
pid=fork();
if(pid>0)
{
printf("fujincheng\n");
}else
{
printf("zijincheng\n");
data+=100;//子进程也可以使用while(1)进行执行
}
printf("%d\n",data);
}else{
printf("do nothing\n");
}
}
return 0;
}
代码实现:
每输入一次1,就多创建一个子进程去完成任务。
运行结果:
5.vfork创建进程:
vfork函数也可以创建进程,与fork有什么区别?
关键区别1:
Vfork直接使用父进程存储空间,不拷贝
关键区别2:
Vfork保证了子进程先运行,当子进程调用exit推出后,父进程才执行。
代码演示:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int cnt=0;
pid_t pid;
pid=vfork();//创建子进程
if(pid>0)
{
while(1){
printf("fujincheng\n");
sleep(1);
}
}else if(pid==0)
{
while(1){
printf("ZIjincheng\n");
sleep(1);
cnt++;
if(cnt==3)
{
exit(0);
}
}
}
return 0;
}
代码实现:当子进程中cnt==3时,退出,再去执行父进程
运行结果:
6.进程退出:
正常退出:-------exit(0);-------0为返回状态
A,main函数调用return
B,进程调用exit()标准c库
C,进程调用_exit()或者_Exit(),属于系统调用
补充:
A,进程最后一个线程返回
B,最后一个线程调用pthread_exit
异常退出:
A,调用abort
B,当进程收到某些信号时:ctrl+c
C,最后一个线程对取消(cancellation)请求做出响应