进程创建
创建进程:
pid_t fork(void);
返回值:
失败 -1, 成功返回两次,在父进程中返回值为子进程ID,在子进程中返回父进程ID
注:
子进程的代码和父进程的代码是一致的,但是子进程启动之后是从fork之后开始执行的
获得pid,进程id,获得当前进程:
pid_t fork(void);
获得当前进程父进程的id
pid_t getppid(void);
进程创建示例代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("Begin ....\n");
pid_t pid = fork();
if(pid < 0){
perror("fork err");
exit(1);
}
if(pid == 0){
//子进程
printf("I am a child,pid = %d,ppid=%d\n",getpid(),getppid());
while(1){
printf("I am a child\n");
sleep(1);
}
}
else if(pid > 0){
//父进程的逻辑
printf("childpid=%d,self=%d,ppid=%d\n",pid,getpid(),getppid());
while(1){
sleep(1);
}
}
printf("End ....\n");
return 0;
}
代码示例 用父进程创建N个子进程:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int n = 5;
int i =0;
pid_t pid = 0;
for(i = 0; i < 5 ; i ++){//父进程循环结束
pid = fork();
if(pid == 0){
//son
printf("I am child ,pid=%d,ppid=%d\n",getpid(),getppid());
break;//子进程退出循环的接口 , 否则子进程也会创建自己的子进程,因为fork是在一个循环中的
}else if(pid > 0){
//father
printf("I am father,pid=%d,ppid=%d\n",getpid(),getppid());
}
}
sleep(i);
if(i < 5){
printf("I am child ,will exit,pid=%d,ppid=%d\n",getpid(),getppid());
}
else{
//father
printf("I am parent,will out pid=%d,ppid=%d\n",getpid(),getppid());
}
return 0;
}
进程共享
父子进程之间在fork后。有哪些相同,哪些相异之处呢?
fork之后:
父子进程相同之处:全局变量、.data(数据块)、.text(代码块)、栈、堆、环境变量、用户ID、宿主目录、进程工作目录,信号处理方...
父子进程不同之处:进程ID、fork返回值、父进程ID、进程运行时间、闹钟、未解决信号集
那么子进程复制了父进程的用户空间内容,已经父进程的PCB,但pid不同。子进程每fork一次都要将父进程的地址空间完全拷贝一份,然后映射至物理内存吗?
答案是不是的。父子进程间遵循读时共享写时复制的原则,这样设计,无论子进程执行父进程的逻辑还是执行自己的逻辑都能节省内存开销。
关于全局变量,子进程虽然是也拥有同样的全局变量,但是父子进程的内存是独立的,所以不会有竞争问题
代码示例 父子进程不共享全局变量:
#include <stdio.h>
#include <unistd.h>
int var = 100;
int main()
{
pid_t pid = fork();
if(pid == 0){
//son
var = 1001;
printf("address = %d var = %d,child,pid=%d,ppid=%d\n",&var,var,getpid(),getppid());
sleep(3);
printf("address = %d var = %d,child,pid=%d,ppid=%d\n",&var,var,getpid(),getppid());
}
else if(pid > 0){
//parent
sleep(1);//保障子进程能够修改var的值成功
printf("address = %d var = %d,parent,pid=%d,ppid=%d\n",&var,var,getpid(),getppid());
var=2000;
printf("address = %d var = %d,parent,pid=%d,ppid=%d\n",&var,var,getpid(),getppid());
}
return 0;
}