文章目录

  • BEGIN
  • Demo 1 - 了解fork执行方式
    • code & result
    • comprehension
  • Demo 2 - fork的返回值研究
    • code & result
    • comprehension
  • Demo 3 - lockf锁和并发
    • code & result
    • comprehension
  • Demo 4 - 控制fork创建顺序
    • code & result
    • comprehension
  • END

BEGIN

Demo 1 - 了解fork执行方式

code & result

#include <cstdio>
#include <iostream>
#include <unistd.h>
using namespace std;int main ( void  ) {fork();fork();fork();cout << "S" << endl;return 0;
}

comprehension

执行第一个fork调用时,
进程A创建了进程B;

执行第二个fork调用时,
进程A创建了进程C,
进程B创建了进程D;

执行第三个fork调用时,
进程A创建了进程E,
进程B创建了进程F,
进程C创建了进程G,
进程D创建了进程H。

如图,

Demo 2 - fork的返回值研究

code & result

#include <iostream>
#include <unistd.h>
using namespace std;int main ( void  ) {cout << "Program begin." << endl;int pid = fork();if ( pid != 0 ) {cout << "Process 'pid != 0' -> true (parentId, selfId):" <<"(" << getppid() << ", " << getpid() << ")" <<" / pid=" << pid << endl;for ( int i = 0; i < 10; ++i  ) {cout << "Parent " << "\t" << i << endl;sleep(1);}} else {cout << "Process 'pid != 0' -> false (parentId, selfId):" <<"(" << getppid() << ", " << getpid() << ")" <<" / pid=" << pid << endl;for ( int i = 0; i < 10; ++i  ) {cout << "Child " << "\t\t" << i << endl;sleep(1);}}cout << "Program end." << endl;return 0;
}

comprehension

也就是可以理解为, 当执行 fork() 之后, 产生的子进程是从当前fork()函数调用的位置开始继续执行.

并且, fork() 是返回两个值的, 一个给自己, 一个给子进程. 也正是如此, if else 才能都输出.

Demo 3 - lockf锁和并发

code & result

#include <iostream>
#include<unistd.h>
using namespace std;/* lockf(files,function,size),* file 文件描述符: 1表示stdout标准输出;* function 锁定和解锁: 1表示锁定, 0表示解锁;* size 锁定或者解锁的字节数: 为0, 表示从文件的当前位置到文件尾.*/int main() {cout << "Program begin." << endl;int p1, p2,i;while( ( p1=fork() ) == -1 ); // main create processif( p1 != 0 ) { // ***main self***cout << endl <<"Process 'p1 != 0' -> true" << " / p1=" << p1 <<" (parentId, selfId):" << "(" << getppid() << ", " << getpid() << ")" <<"\t(main self when 1st process created.)" << endl;cout << endl;while( ( p2 = fork() ) == -1 ); // main create processif ( p2 != 0 ) { // ***main self***lockf( 1, 1, 0 ); // lockcout << "Process 'p2 != 0' -> true" << " / p2=" << p2 <<" (parentId, selfId):" << "(" << getppid() << ", " << getpid() << ")" <<"\t(main self when 2st process created)" << endl;for ( i = 0 ; i < 5 ; ++i ) cout << "A: " << "\t\t" << i << endl;lockf( 1, 0, 0 ); // unlock} else { // main's 2th sub processlockf( 1, 1, 0 ); // lockcout << "Process 'p2 != 0' -> false" << " / p2=" << p2 <<" (parentId, selfId):" << "(" << getppid() << ", " << getpid() << ")" <<"\t(main's 2th sub process)" << endl;for ( i = 0 ; i < 5 ; ++i ) cout << "C: " << "\t\t" << i << endl;lockf( 1, 0, 0 ); // unlock}}else { // main's 1th sub processlockf( 1, 1, 0 ); // 加锁cout << "Process 'p1 != 0' -> false" << " / p1=" << p1 <<" (parentId, selfId):" << "(" << getppid() << ", " << getpid() << ")" <<"\t(main's 1th sub process)" << endl;for ( i = 0 ; i < 5 ; ++i ) cout << "B: " << "\t\t" << i << endl;lockf( 1, 0, 0 ); // 解锁}cout << "Program end." << endl;return 0;
}

comprehension

进程创建之后是并发执行的.

如图所示, main进程创建了两次新进程,
在main进程中, p1 和 p2 分别为 子进程的 pid,
在子进程中, p1 和 p2 都为0, 这也是子进程的标记.

fork()函数有两个返回值,
返回给父进程 -> 子进程pid
返回给子进程 -> 0

也正是充分利fork()之后
父子进程皆从fork调用位置继续执行fork()的两个返回值
这两大性质, 才得以控制代码中进程的逻辑关系.

Demo 4 - 控制fork创建顺序

code & result

#include <iostream>
#include<unistd.h>
using namespace std;/* lockf(files,function,size),* file 文件描述符: 1表示stdout标准输出;* function 锁定和解锁: 1表示锁定, 0表示解锁;* size 锁定或者解锁的字节数: 为0, 表示从文件的当前位置到文件尾.*/int main() {cout << "Program begin." << endl;int p1, p2,i;while( ( p1=fork() ) == -1 ); // main create processif( p1 != 0 ) { // ***main self***lockf( 1, 1, 0 ); // 加锁cout << "Process 'p1 != 0' -> false" << " / p1=" << p1 <<" (parentId, selfId):" << "(" << getppid() << ", " << getpid() << ")" <<"\t(main's self)" << endl;for ( i = 0 ; i < 5 ; ++i ) cout << "A: " << "\t\t" << i << endl;lockf( 1, 0, 0 ); // 解锁}else { // main's 1th sub processwhile( ( p2 = fork() ) == -1 ); // main's 1th process create processif ( p2 != 0 ) { // ***main's 1th sub process self***lockf( 1, 1, 0 ); // lockcout << "Process 'p2 != 0' -> true" << " / p2=" << p2 <<" (parentId, selfId):" << "(" << getppid() << ", " << getpid() << ")" <<"\t(main's 1th sub process self when main's 1th sub process's 1th sub process created)" << endl;for ( i = 0 ; i < 5 ; ++i ) cout << "B: " << "\t\t" << i << endl;lockf( 1, 0, 0 ); // unlock} else { // main's 1th sub process's 1th sub processlockf( 1, 1, 0 ); // lockcout << "Process 'p2 != 0' -> false" << " / p2=" << p2 <<" (parentId, selfId):" << "(" << getppid() << ", " << getpid() << ")" <<"\t(main's 1th sub process's 1th sub process when main's 1th sub process's 1th sub process created)" << endl;for ( i = 0 ; i < 5 ; ++i ) cout << "C: " << "\t\t" << i << endl;lockf( 1, 0, 0 ); // unlock}}cout << "Program end." << endl;return 0;
}

comprehension

对比 Demo3 理解它!

END

相信聪明的你一定明白了吧!

关于 Linux fork()进程创建函数 的 执行方式 返回值 lockf锁和并发 控制创建顺序 的探索相关推荐

  1. php linux fork进程 多个进程/线程共享一个 socket连接 出现多个进程响应串联

    简单说来就是:因为fork,父子进程共享了一个redis连接.然后父子进程在发送了各自的redis请求分别获取到了对方的响应体. 复现示例代码: testFork.php <?php requi ...

  2. linux中进程退出函数:exit()和_exit()的区别

    linux中进程退出函数:exit()和_exit()的区别 (1)_exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核. (2)调用_exit函数时,其会关闭 ...

  3. Linux 将进程放入后台执行,解决网络,ssh断开导致进程结束(nohup, setsid, , disown)...

    Linux 将进程放入后台执行,解决网络,ssh断开导致进程结束(nohup,  setsid,  &, disown) 1.nohup 命令 我们知道,当用户注销(logout)或者网络断开 ...

  4. 函数二的变量作用域,多函数执行,返回值,函数参数,拆包,引用

    函数二 一.变量作用域 1.局部变量是函数内部变量,在函数临时保存数据,函数调用完则销毁,在函数外访问即报错 2.全局变量函数内外都可访问,当不同函数都要用到某一变量时,则可使用全局变量 def fu ...

  5. python函数+定义+调用+多返回值+匿名函数+lambda+高级函数(reduce、map、filter)

    python函数+定义+调用+多返回值+匿名函数+lambda+高级函数(reduce.map.filter) Python 中函数的应用非常广泛,比如 input() .print().range( ...

  6. mysql_ping()函数的作用以及返回值的类型正确的是,[单选] mysql_ping()函数的作用以及返回值的类型正确的是:()...

    [单选] mysql_ping()函数的作用以及返回值的类型正确的是:() 更多相关问题 中华田园犬,雄性,2岁,昨晚外出未归,今晨发现患犬精神沉郁,呼吸急促,体温39℃,左胸侧壁中下部有创 1884 ...

  7. C语言中函数参数传递的方式:值传递,地址传递

    ** C语言中函数参数传递的方式:值传递,地址传递 ** 值传递:将实参的值复制至形参的相应存储单元中,实参与形参占用不同存储单元,单向传递 地址传递:使用数组名或者指针作为函数参数,传递的是该数组的 ...

  8. 汇编和c语言函数的参数,C函数与汇编函数之间参数及返回值传递方法

    AAPCS对ARM结构的一些标准做了定义,在这里我们只重点介绍函数调用部分,如图8所示,AAPCS为ARM的R0~R15寄存器做了定义,明确了它们在函数中的职责: 图 8 AAPCS关于ARM寄存器的 ...

  9. linux文件的定义变量的值,linux shell 自定义函数方法(定义、返回值、变量作用域)...

    一.定义shell函数(define function) 语法: [ function ] funname [()] { action; [return int;] } 说明: 1.可以带functi ...

最新文章

  1. Chrome使用技巧和编辑框拖动怪问题。
  2. 编写一个方法,找出两个数字中最大的那一个。不得使用if-else或其他比较运算符。...
  3. 选中文字改变默认颜色
  4. 【转】 vi常用操作
  5. 用鸿蒙跑了个 hello world
  6. python PyQt5中文教程☞【第二节】PyQt5基本功能(创建窗口、应用程序图标、显示提示语、通过按钮关闭窗口、消息框(关闭窗口确认框)、窗口显示在屏幕中间【居中显示】)
  7. s2-045 java_S2-045漏洞初步分析
  8. 锁 唤醒_Java笔记|等待唤醒机制
  9. c和go 两种语言结合使用 (一)
  10. 快速清除oracle多个表,Oracle数据库之批量清除一个表的数据,TB级别数据
  11. Windows Phone 7 自定义弹出窗口
  12. 蓝桥杯真题 杨辉三角形 C++
  13. uni-app打开其他APP应用
  14. PDF转ONENOTE的方法
  15. 计算机等级考试数据库三级模拟题7
  16. BeagleBone Black 从零到一 (2 MLO、U-Boot)
  17. sencha touch总结
  18. 电脑关闭所有应用的快捷键
  19. WEB前端项目实战/酒仙网开发-李强强-专题视频课程
  20. 【动态】雷电网络预览:以太坊扩容解决方案发布开发者演示

热门文章

  1. java计算机毕业设计高校请假管理系统MyBatis+系统+LW文档+源码+调试部署
  2. 需求工程:第五章 确定项目的前景和范围-目标分析第六章 涉众分析与硬数据采样
  3. oracle数据库升级导致的数据库对象不可用或无效解决办法
  4. VMWare Workstation:局域网PC连接虚拟机里的远程桌面或端口
  5. p标签实现自动换行CSS
  6. 使用Behavior Designer插件简单制作NPC AI
  7. JavaScript中undefined详解
  8. Linux系统chmod,chown和chgrp的区别
  9. 《课程格子》的一个笔试题目
  10. Underwear fight