前言:
今天我们对“c语言fork”大约比较珍视,咱们都想要了解一些“c语言fork”的相关知识。那么小编在网摘上收集了一些对于“c语言fork””的相关文章,希望大家能喜欢,朋友们快快来了解一下吧!接上文 Linux系列5_你知道什么是进程以及如何查进程吗?
(4)创建进程-forkA:fork的作用:演示
fork()函数是用来创建进程的,在fork函数执行后,如果成功创建新进程就会出现两个进程,一个是子进程,一个是父进程,fork函数有两个返回值
1:演示一:创建子进程
编写如下C语言文件,进入主函数后,执行fork函数,创建进程
#include <stdio.h>#include <unistd.h>int main(){ printf("执行到fork函数之前其进程为:%d,其父进程为:%d\n",getpid(),getppid()); sleep(1); fork(); sleep(1); prinf("这个进程id为:%d,它的父进程id为%d\n",getpid(),getppid()); sleep(1); return 0;}
运行效果如下
根据上面程序的运行效果,似乎可以发现下面比较值得注意的几点
它们的逻辑关系有些特点从上面的动图可以发现,fork()函数调用完成之后,**它们似乎是同时输出的,这是否告诉我们这两个进程是同时进行的?**或许它可以被画成这样?
2:演示二:创建子进程
前面说过,fork有两个返回值。官方手册中是这样解释到的
在父进程中,fork返回新创建子进程的ID在子进程中,fork返回0未能创建,fork返回负值
在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的ID。我们可以通过fork返回值判断当前进程是什么进程。
根据以上描述,编写C语言代码,使用fork函数的返回值来进行分流
#include <stdio.h>#include <unistd.h>int main(){ prinf("还没有执行fork函数的本进程为:%d\n",getpid()); pid_t=fork();//其返回值是pid类型的 sleep(1); if(ret>0)//父进程返回的是子进程ID printf("我是父进程,我的id是:%d,我的孩子id是%d\n",getpid(),ret); else if(ret==0)//子进程fork返回值是0 printf("我是子进程,我的id是%d,我的父亲id是%d\n",getpid(),getppid()); else printf("进程创建失败\n"); sleep(1); return 0;}
效果如下
3:演示三:一个大的问题
为了方便演示,修改上述代码如下,为每个if语句块内加入死循环,使其不能不断输出
#include <stdio.h>#include <unistd.h>int main(){ prinf("还没有执行fork函数的本进程为:%d\n",getpid()); pid_t=fork();//其返回值是pid类型的 sleep(1); if(ret>0)//父进程返回的是子进程ID { while(1) { printf("----------------------------------------------------------------\n"); printf("我是父进程,我的id是:%d,我的孩子id是%d\n",getpid(),ret); sleep(1); } } else if(ret==0)//子进程fork返回值是0 { while(1) { printf("我是子进程,我的id是%d,我的父亲id是%d\n",getpid(),getppid()); sleep(1); } } else printf("进程创建失败\n"); sleep(1); return 0;}
效果如下
同时再使用之前的命令查看这个进程,发现也是两个进程
但是这里有一个很大的问题:不过是什么语言,if-else执行时每次只能执行一路,怎么可能同时执行多路,同时每个if语句块内都有死循环,一个循环未结束,又怎么可能去执行其他语句呢
在Linux中,进程创建会形成链表,父进程创建子进程,那么父进程的进程指针会指向子进程ID。
所以这两个进程是同时运行的
B:fork相关问题
1.如何理解进程创建
前面说过,操作系统在进行管理时,必然遵循“先描述,再组织”的原则,所以在进行进程管理时。首先会创建相应的task_struct,写入有关信息,然后和你编写好的代码共同组成进程
2.为什么fork有两个返回值
根据上面的描述,可以大致描述fork函数的执行逻辑如下
pid_t fork(){ //先描述,再组织,所以首先为子进程创建结构体 struct task_struct* p=malloc(struct task_struct); //以下逻辑就是写入属性信息 p->XX=father->XX; .... p->status=run; p->id=1888; //到这里之前,子进程创建完毕 return p->id;}
其实,进程数据=代码+数据,代码是共享的,数据是私有的,上述逻辑中return之前的语句是父进程执行,结果就是生成了子进程,等执行return语句时,子进程已经生成,于是父子进程同时执行这一条语句,又因为数据是私有的,所以各自返回不同的值
执行完fork之后,父进程pid不等于0,子进程pid等于0。这两个进程都是独立的,存在于不同地址中,不是公用的。
fork把进程当前的情况进行拷贝,执行fork时,fork只拷贝下一个要执行的代码到新的进程
为了说明变量不共用,可以编写一个C语言代码如下,同一个变量分别在父进程和子进程中修改
#include <stdio.h>#include <unistd.h>int main(){ int cout=0; printf("还未执行fork函数的cout=%d\n",cout); pid_t ret=fork(); if(ret>0) { cout+=1;//父进程cout=1; printf("父进程:cout=%d\n",cout); } else if(ret==0) { cout+=10;//子进程cout=10; printf("子进程:cout=%d\n",cout); } else printf("失败\n"); sleep(1); return 0; }
结果如下,可以发现它们不公用变量
3.为什么两个返回值不一样
其实很好理解,创建进程时相当于形成了链表(Linux)中,父进程指向子进程,所以返回的是子进程的ID,而子进程没有它的子进程,所以返回0。
标签: #c语言fork