linux系统调用fork()创建一个和当前进程完全相同的拷贝进程,其中父进程和子进程的代码段,堆栈段,数据段均独立

进程必须的4要点:

a.要有一段程序供该进程运行

b.进程专用的系统堆栈空间。

c.进程控制块,在linux中具体实现是task_struct

d.有独立的存储空间。

当一个进程缺少其中一个条件时候,我们称其为线程。

1.先看fork()的原型 :

#include<sys/types.h> /* 提供类型pid_t的定义 */
#include<unistd.h> /* 提供函数的定义 */
pid_t fork(void);
返回: 父进程中执行则返回子进程PID,子进程中执行返回0

现在进行一个例子,创建一个子进程,然后根据返回的 PID进行识别:

[cpp] view plaincopy
  1. /*test.c*/
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <unistd.h>
  5. main()
  6. {
  7. int count = 0;
  8. pid_t pid;      /*此时仅有一个进程*/
  9. pid=fork(); /*此时已经有两个进程在同时运行*/
  10. if(pid<0)    /*返回错误*/
  11. printf("error in fork!");
  12. else
  13. {
  14. if(pid==0)      /*代码在子进程中执行*/
  15. printf("I am the child process, my count is %d,my process ID is %d/n",count,getpid());
  16. else        /*代码在父进程中执行*/
  17. printf("I am the parent process,my count is %d, my process ID is %d/n",++count,getpid());
  18. }
  19. }

弄好后,在linux中键入:

$ gcc test.c -o test

$ ./test

在本次试验中

I am the parent process,my count is 1,my process ID is 3196

I am the child process, my count is 0,my process ID is 3776

从代码里面可以看出2者的pid不同,内存资源count是值得复制,父进程改变了count的值,而子进程中的count没有被改变。有人认为这样大批量的复制会导致执行效率过低。其实在复制过程中,子进程复制了父进程的task_struct,系统堆栈空间和页面表,这意味着上面的程序,我们没有执行count++前,其实子进程和父进程的count指向的是同一块内存。而当子进程改变了父进程的变量时候,会通过copy_on_write的手段为所涉及的页面建立一个新的副本。所以当我们执行++count后,这时候子进程才新建了一个页面复制原来页面的内容,基本资源的复制是必须的,而且是高效的。整体看上去就像是父进程的独立存储空间也复制了一遍。

在fork中,父子进程是独立开来的 ,并没有影响

2.vfork函数

vfork创建出来的不是真正意义上的进程,而是一个线程,因为它缺少了上面提到的进程的四要素的第4项,独立的内存资源,我们编一个程序练习:

[cpp] view plaincopy
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <unistd.h>
  4. main()
  5. {
  6. int count = 1;
  7. int child;
  8. printf("Before create son, the father's count is:%d/n", count);//打印没创建进程前
  9. if(!(child = vfork())) //创建子进程
  10. {
  11. printf("This is son, his pid is: %d and the count is: %d/n", getpid(), ++count);
  12. exit(1);
  13. } else
  14. {
  15. printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d/n",
  16. getpid(), count, child);
  17. }
  18. }

然后编译,执行,得到下列结果:

Before create son, the father's count is:1

This is son, his pid is: 4048 and the count is: 2
After son, This is father, his pid is: 4048 and the count is: 2, and the child is: 2748

从这里我们看到,子进程和父进程是共享count的,也就是说,内存区是共享的

另外由vfork创造出来的子进程还会导致父进程挂起,除非子进程exit或者execve才会唤起父进程,看下面程序:

[cpp] view plaincopy
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <unistd.h>
  4. main()
  5. {
  6. int count = 1;
  7. int child;
  8. printf("Before create son, the father's count is:%d/n", count);
  9. if(!(child = vfork()))
  10. {//这里是子进程执行区
  11. int i;
  12. for(i = 0; i < 100; i++)
  13. {
  14. printf("This is son, The i is: %d/n", i);
  15. if(i == 70)
  16. exit(1);
  17. }
  18. printf("This is son, his pid is: %d and the count is: %d/n", getpid(), ++count);
  19. exit(1);//子进程退出
  20. }
  21. else
  22. {//父进程
  23. printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d/n",
  24. getpid(), count, child);
  25. }
  26. }

好,编译通过,执行。。。

Before create son, the father's count is:1

This is son, The i is: 0

...

...

This is son, The i is: 68
This is son, The i is: 69
This is son, The i is: 70
After son, This is father, his pid is: 2564 and the count is: 1, and the child is: 2736

可以看到父进程总是等子进程执行完毕后才开始继续执行

进程控制1--fork vfork函数相关推荐

  1. 小何讲进程: Linux进程控制编程 (fork、vfork)

    所谓进程控制,就是系统使用一些具有特定功能的程序段来创建进程.撤消进程以及完成进程在各种状态之间的转换, 从而达到多进程高效率并发执行和协调资源共享的目的.进程控制是进程管理和处理机管理的一个重要任务 ...

  2. 进程控制(2):进程操作

    前言: 关于进程控制这块的好文很多,下面转载的这篇内容很丰富,也会举适当的栗子,与其写的一知半解不如参读学习别人的优秀博文,感谢原作,本系列摘录自:https://www.cnblogs.com/xi ...

  3. UNIX环境高级编程笔记之进程控制

    本章重点介绍了进程控制的几个函数:fork.exec族._exit.wait和waitpid等,主要需要掌握的是父进程和子进程之间的运行机制,怎么处理进程的正常和异常终止.以及怎么让进程执行不同的程序 ...

  4. 实验四 linux进程控制实验报告,Linux系统进程控制操作系统实验报告4

    实验课程名称:操作系统 实验项目名称Linux系统进程控制实验成绩 实验者专业班级组别 同组者实验日期年月日第一部分:实验分析与设计(可加页) 实验内容描述(问题域描述) 要求:掌握Linux系统中进 ...

  5. UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid...

    本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID 1 进程标识符(Process Identifiers ...

  6. Linux系统编程之进程控制(进程创建,fork函数,进程中止,进程等待,程序替换)

    进程创建 fork()------复制,返回值,写时复制 vfork()创建子进程-子进程与父进程共用同一块虚拟地址空间, 为了防止调用栈混乱,因此阻塞父进程直到子进程调用exit()退出或者进行程序 ...

  7. linux创建进程fork函数和vfork函数

    #include <unistd.h>pid_t fork(void);#include <sys/types.h>#include <unistd.h>pid_t ...

  8. linux c之创建进程fork和vfork函数之间的区别

    1.函数简介 1).得到当前的进程id pid_t getpid(); 2).fork函数 要创建进程,必须调用fork函数, 系统调用fork用于派生一个进程,函数原型如下 #include< ...

  9. linux系统编程学习_(2)进程控制-- fork函数、exec函数族、回收子进程--孤儿进程僵尸进程、wait函数

    linux系统编程学习_(2)进程控制-- fork函数.exec函数族.回收子进程–孤儿进程僵尸进程.wait函数 进程控制 fork()函数 创建一个子进程. pid_t fork(void); ...

最新文章

  1. 2021年春季学期-信号与系统-第四次作业参考答案
  2. 初创公司谁来当你们的运维
  3. android+包+反编译,简单的Android之apk包反编译方法
  4. [代码整洁]自我感悟
  5. 吴恩达神经网络1-2-2_图神经网络进行药物发现-第2部分
  6. 今晚直播丨管中窥豹 - PostgreSQL、openGauss、达梦和OceanBase的初步介绍
  7. 搜索、推荐、广告中的曝光偏差问题
  8. Java基础,使用双循环嵌套,实现输出1-1000之间所有的素数,并统计有多少个
  9. Python 学习 Day23
  10. 许鹏:从零开始学习,Apache Spark源码走读
  11. SOLD2算法详解之1 backbone(CVPR2021 源码解析)
  12. GTK+ GUI库使用现状
  13. 考研数学1-考试大纲(2022年)
  14. Kettle的“增加序列”(自增字段)的使用
  15. 拉格朗日乘子法详解(Lagrange multiplier)
  16. 重装系统(无法开机时候操作方法)
  17. 学校计算机专业春联大全带横批,关于学校的春联带横批.doc
  18. 啊哈添柴挑战Java1221. 输出三角形
  19. 2022.2.20自制豆腐
  20. harries算子特征提取与图像匹配

热门文章

  1. 什么linux系统是中文的,什么是Linux系统
  2. mysql 性能状态_MySQL获取系统性能和状态_MySQL
  3. vue双向数据绑定v-model绑定单选框,复选框,下拉框
  4. 第8章 硬盘和显卡的访问与控制
  5. spring框架(三)mvc
  6. save(),saveOrUpdate(),merge()的区别
  7. 推荐几个配色和图标网站
  8. DB2 常用命令小结
  9. 用ASP.NET 2.0设计网络在线投票系统
  10. 46. Permutations