fork在英文中是“分叉”的意思。为什么取这个名字呢?因为一个进程在运行中,如果使用了fork函数,就产生了另一个进程,于是进程就“分叉”了,所以这个名字取得很形象。下面就看看如何具体使用fork函数,这段程序演示了使用fork的基本框架。
 
函数声明:
 
pid_t fork();
 
  fork函数用于产生一个新的进程,函数返回值pid_t是一个整数,在父进程中,返回值是子进程编号,在子进程中,返回值是0。
 
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> int main()
{
printf("本程序的进程编号是:%d\n",getpid()); int ipid=fork(); sleep(1); // sleep等待进程的生成。 printf("pid=%d\n",ipid); if (ipid!=0) printf("父进程编号是:%d\n",getpid());
else printf("子进程编号是:%d\n",getpid()); sleep(30); // 是为了方便查看进程在shell下用ps -ef|grep book252查看本进程的编号。
}
   
从 fork() 这个函数开始出现后,
便创建了子进程,并且子进程和父进程一样从fork(这个函数一起执行下去,也就是说从fork()开始的下面所有代码分别被父
进程和子进程都执行了一次,如果没有条件判断语句判别fork()的返回值,将无法分别子父进程,根据fork()的返回值可以令子父进程跳过或执行某条语句

运行结果

初学者可能用点接受不了现实。

1)一个函数(fork)返回了两个值?

2)if和else中的代码能同时被执行?

那么调用这个fork函数时发生了什么呢?fork函数创建了一个新的进程,新进程(子进程)与原有的进程(父进程)一模一样。子进程和父进程使用相同的代码段;子进程拷贝了父进程的堆栈段和数据段。子进程一旦开始运行,它复制了父进程的一切数据,然后各自运行,相互之间没有影响。

fork函数对返回值做了特别的处理,调用fork函数之后,在子程序中fork的返回值是0,在父进程中fork的返回是子进程的编号,程序员可以通过fork的返回值来区分父进程和子进程,然后再执行不同的代码。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> #include <stdio.h>
#include <sys/types.h>
#include <unistd.h> void fatchfunc() // 父进程流程的主函数
{
printf("我是老子,我喜欢孩子他娘。\n");
} void childfunc() // 子进程流程的主函数
{
printf("我是儿子,我喜欢西施。\n");
} int main()
{
if (fork() > 0)
{
printf("这是父进程,将调用fatchfunc()。\n");
fatchfunc();
}
else
{
printf("这是子进程,将调用childfunc()。\n");
childfunc();
} sleep(1);
printf("父子进程执行完自己的函数后都来这里。\n");
sleep(1);
}

运行结果:

在上文上已提到过,子进程拷贝了父进程的堆栈段和数据段,也就是说,在父进程中定义的变量子进程中会复制一个副本,fork之后,子进程对变量的操作不会影响父进程,父进程对变量的操作也不会影响子进程。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> int i=10; int main()
{
int j=20; if (fork()>0) //从 fork() 这个函数开始出现后,
//便创建了子进程并且和父进程一样从fork()
//这个函数一起执行下去,也就是说从fork()开始的下面所有代码分别被父///进程和子进程都执行了一次,如果没有条件判断语句判别fork()的返回/////值,将无法分别子父进程,根据fork()的返回值可以令子父进程跳过或执///行某条语句 {
//如果fork大于零,证明是父进程,即执行下面的语句 i=11;j=1; sleep(1); printf("父进程:i=%d,j=%d\n",i,j);
int sum = i + j;
printf("父sum = %d\n",sum); }
else
{
//如果fork小于零,证明是子进程,执行下面的语句
i=12;j=22; sleep(1); printf("子进程:i=%d,j=%d\n",i,j);
printf("子sum = %d\n",i+j); }
}
 
 
从 fork() 这个函数开始出现后,便创建了子进程,并且子进程和父进程一样从fork(这个函数一起执行下去,也就是说从fork()开始的下面所有代码分别被父
进程和子进程都执行了一次,如果没有条件判断语句判别fork()的返回值,将无法分别子父进程,根据fork()的返回值可以令子父进程跳过或执行某条语句

运行结果

来源:www.freecplus.net

作者:码农有道

作业:

(1)编写一个多进程程序,验证子进程是复制父进程的内存变量,还是父子进程共享内存变量?

复制内存变量

2)编写一个示例程序,由父进程生成10个子进程,在子进程中显示它是第几个子进程和子进程本身的进程编号。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> int main()
{
int i = 0;
while (i < 10)
{ if (fork() > 0)
{
i++;
continue; //父进程回到while(循环),
}
else
{
printf("子进程第%d个,pid = %d\n", i, getpid());
break;
}
}
sleep(10); return 0;
}

运行结果

3)编写示例程序,由父进程生成子进程,子进程再生成孙进程,共生成第10代进程,在各级子进程中显示它是第几代子进程和子进程本身的进程编号。

如图

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> int main()
{
int i = 0; //全局变量,计数器,计算第几代子进程
while (i < 10)
{ if (fork()== 0)
{
i++;
continue;
}
else
{
printf("第%d代子进程,pid = %d\n", i, getpid()); 第 0 代子进程是第一个父进程 break;
}
}
sleep(10); return 0;
}

运行结果:

子进程是下一个子进程的父进程

4)利用尽可能少的代码快速fork出更多的进程,试试看能不能把linux系统搞死。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> int main()
{
int i = 0; //全局变量,计数器,计算第几代子进程
while (i < 10)
{ if (fork()>0)
{
fork(); }
}
printf("pid=%d",getpid()); return 0;
}

5)ps -ef |grep book251命令是ps和grep两个系统命令的组合,各位查一下资料,了解一下grep命令的功能,对程序员来,grep是经常用到的命令。

https://blog.csdn.net/weixin_52273136/article/details/110451596

来源:C语言技术网(www.freecplus.net

作者:码农有道

关于linux多线程fork的理解和学习的更多相关文章

  1. 20155321 《信息安全系统设计》Linux多线程的深入学习

    再次学习之多线程 基本概念的再次学习 线程是程序执行的最小单位(进程是资源管理的最小单位),线程隶属于某个进程中 进程有自己的数据段.代码段和堆栈段.线程通常叫做轻型的进程,每个线程共享其所附属进程的 ...

  2. Linux系统的理解及学习Linux内核的心得

    作业列表      (点击作业跳转) linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作 linux内核分析作业:操作系统是如何工作的进行:完成一个简单的时间片轮转多道程序内核 ...

  3. linux多线程同步pthread_cond_XXX条件变量的理解

    在linux多线程编程中,线程的执行顺序是不可预知的,但是有时候由于某些需求,需要多个线程在启动时按照一定的顺序执行,虽然可以使用一些比较简陋的做法,例如:如果有3个线程 ABC,要求执行顺序是A-- ...

  4. 【转】linux 中fork()函数详解

    在看多线程的时候看到了这个函数,于是学习了下,下面文章写的通俗易懂,于是就开心的看完了,最后还是很愉快的算出了他最后一个问题. linux 中fork()函数详解 一.fork入门知识 一个进程,包括 ...

  5. 进程 | 线程 | 当Linux多线程遭遇Linux多进程

    背景 本文并不是介绍Linux多进程多线程编程的科普文,如果希望系统学习Linux编程,可以看[<Unix环境高级编程>第3版] 本文是描述多进程多线程编程中遇到过的一个坑,并从内核角度分 ...

  6. 【转】Linux下Fork与Exec使用

    Linux下Fork与Exec使用 转自 Linux下Fork与Exec使用 一.引言 对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值.for ...

  7. 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

    <Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...

  8. 推荐《Linux 多线程服务器端编程》

    赖勇浩(http://laiyonghao.com) 最近,有一位朋友因为工作需要,需要从网游的客户端编程转向服务器端编程,找我推荐一本书.我推荐了<Linux 多线程服务器端编程——使用 mu ...

  9. Linux下Fork与Exec使用

    Linux下Fork与Exec使用   一.引言 对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值.fork函数是Unix系统最杰出的成就之一, ...

随机推荐

  1. 位运算符 按位与 &——整数n的二进制数中1的个数

    整数n的二进制数中1的个数 编写一个函数,输入是一个整数,返回其二进制表达式中数字位数为 '1' 的个数 代码如下: int func(int n)//char ch { int count = 0; ...

  2. HTML5 版的flappy bird

    Flappy Bird这款简单的小游戏累计下载量已经超过5000万次,每天收入至少5万美元.然而,2月10日其开发者Dong Nguyen却将Flappy Bird从苹果App Store和Googl ...

  3. buuoj [RoarCTF 2019]Easy Calc(利用PHP的字符串解析特性)

    web [RoarCTF 2019]Easy Calc(利用PHP的字符串解析特性) 先上源码 <?phperror_reporting(0);if(!isset($_GET['num'])){ ...

  4. SimpleDateForma求日期,2008-11月第6周星期日是几号?

    题目4: 巧妙利用SimpleDateFormat根据各种信息求日期.2008-11月第6周的星期日是几号? import java.text.ParseException;import java.t ...

  5. mysql各个集群方案的优劣

    集群的好处 高可用性:故障检测及迁移,多节点备份. 可伸缩性:新增数据库节点便利,方便扩容. 负载均衡:切换某服务访问某节点,分摊单个节点的数据库压力. 集群要考虑的风险 网络分裂:群集还可能由于网络 ...

  6. An=n的前n项和的前n项和

    #include<iostream> using namespace std; int main() { int n,a=0,b=0; cin>>n; for(int i=1; ...

  7. C++---初识C++

    C和C++的关系 C语言是结构化和模块化的语言, 面向过程. C++是在C语言的基础上, 增加了面向对象的机制, 并对C语言的功能进行了扩充. 变量的定义可以出现在程序中的任何行 提供了标准输入输出流 ...

  8. typora简单使用手册

    typora简单使用手册讲解`` 下载网站 网址:https://typoraio.cn/ 苹果电脑:https://typora.en.softonic.com/ 正版呢当然是收费 破解版自行百度 ...

  9. Model, HttpServletRequest, ModelMap区别

    看了spring mvc的底层会发现,model数据最终还是写到HttpServletRequest属性中,只是model的写法更体现了MVC思想减少各层间耦合 写法: 1.request.setAt ...

  10. JavaWeb学习day1-web入门&服务器安装

    初步了解了web的发展历程,对比分析学习了动态页面与静态页面的优缺点. 选择安装使用最广泛的Tomcat 安装流程: 1.打开官网:https://tomcat.apache.org/ 2.选择下载版 ...