创建进程 fork 函数|学习笔记

简介: 快速学习创建进程 fork 函数

开发者学堂课程【物联网开发- Linux 高级程序设计全套视频创建进程 fork 函数】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/660/detail/10985


创建进程 fork 函数

 

内容简介:

一、创建进程

二、常用 <!DOCTYPE> 文档类型

三、应用实例

 

一、创建进程

1、在Linux环境下创建进程

接下来讲一下进程的创建fork,要想在程序当中再去创建一个进程,就用fork函数。

先看一下在Linux操作系统下创建进程的方法,

如下所示:

#include<sys/types.h>

#include<unistd.h>

pid t fork(void);

pid t vfork(void);

主要就是以上两个函数,一个是 fork,一个是 vfork,这两个函数都是创建进程的,但创建的进程的效果不太一样,讲完了这两个函数之后就知道它们的区别了。

2、创建新进程

看fork函数它没有参数,返回值有一个进程号,fork函数用于从一个已经存在的进程当中创建一个新的进程,新建成为子进程,原来的进程被称为父进程。

注意此函数和其他函数不太一样,其他函数只有一个返回值,而fork函数不太一样,调一次fork它有两个返回值,因为现在有两个进程了,在子进程当中它返回值为零,在父进程当中返回值为子进程的ID,进程号都是大于等于零的,然后出错了就返回负一,注意使用fork得到的子进程是父进程的一个复制品,是克隆,然后注意它从父进程当中继承了整个地址空间。

父进程有什么样的变量,子进程就有什么样的变量,父进程有什么样的代码,子进程就有什么样的代码。

3、地址空间

那么地址空间包括什么?

进程的上下文、进程的堆栈、进程当中打开的文件描述符、信号的控制设定(后边再讲信号,比如它的父进程设定一下收到哪一个信号,去干什么事,就像按钮一样,设置一下当按钮被按下的时候干什么事一样,是类似的意思)、进程的优先级、进程组号、子进程所独有的只有它的进程号,计时器等是它独有的。


二、fork 函数及进程

1、fork 函数执行结果

使用fork函数的代价是很大的,因为它是将父进程复制了一份,父进程是有堆、有栈、有BBS区、有数据区、有代码区,等fork之后,子进程是完全复制过来的,它会创建这一块内存,然后将父进程的数据复制过来,

如下图所示:

image.png

2、fork 函数创建多任务过程

(1)输入代码

接下来写一下fork的过程,讲述一下它创建多任务的原理,代码如下:

//父进程

int main()

{

pid_t pid;

pid=fork();

//.....

if(pid<0)

{  

//创建进程失败

}

else if(pid==0)

{

}

else

{

//父进程将来执行此代码

}

//公共代码

return 0;

}

//子进程

int main()

{

pid_t pid;

pid=fork();

//.....

if(pid<0)

{

//创建进程失败

}

else if(pid==0)

{

}

else

{

//父进程将来执行此代码

}

//公共代码

return 0;

}

(2)代码说明

写了一个main、写了一个代码之后编译运行,然后它就开始执行,点斜杠运行的时候便启动一个进程,那个进程是父进程,fork是创建一个子进程,创建子进程的时候,父进程当中有什么代码,子进程就有什么代码,那么父进程创造子进程,父子进程的代码是完全一样的,那么创建子进程的目的是什么?

让父进程干一个事情,子进程干另外一个事情,父子进程干不一样的事情,要不然创建子进程是没用的,那代码完全一样,怎样让父子进程执行不一样的代码?

就根据返回值来定的,子进程当中它的fork的返回值给变量赋值为零,子进程当中它的返回值是为零的,父进程返回值是子进程的进程号,所以说其是父进程,在父进程pid是大于零的,子进程号是大于零的,在子进程当中pid等于零,所以可以通过pid的值不一样来执行不同的代码,虽然父子进程的代码一样,但是pid的值是不一样的,可以通过pid的值让它执行不同的代码,如果pid小于零代表创建进程失败,然后做处理就可以了。

可以看到上述代码中子进程的代码和父进程的代码是一样的,先执行父进程,然后就创建子进程,父进程生了儿子之后,父进程再往下执行,子进程当中pid等于零,子进程当中fork的返回值等于零,注意fork只调一次,在子进程当中子进程是从第八行往后执行的,它不可能从第四行往后走,如果创建了子进程,子进程从main往后执行,那么子进程就又去fork,就又创建了子进程,子进程再去刻意创建子进程,那子子孙孙无穷无尽了,就好比克隆羊多莉,中国有克隆牛,那么克隆羊和克隆牛是从什么时候执行的?

从创建它之后去执行的,在生它之前的那些代码是不会执行的,虽然两头羊是一模一样的基因资源,但是新的羊应该是从生到了它之后再去执行的,即子进程是从第六行之后执行的,继续看父进程执行完else之后再往下执行,直到return 0。

公共代码是父进程和子进程都要执行的,也就是说父进程创建完子进程之后,父子进程的代码完全一样,父进程接下来执行else里边的代码,然后执行公共代码,而子进程从fork之后再执行,执行pid等于零的代码,然后再去执行公共代码。这样虽然父子进程的代码一样,但它执行的代码块不一样,就相当于进程干一个事,子进程干一个事,这就实现了多任务。

 

三、举例子说明

1、输入代码

接下来举例子:先输入以下代码:

[01_day]1s

aaa.txt dest.txt my_cp my_cp.c pid pid.c read read.c test.txt wanqi.txt

[01_day]vi fork.c

执行之后换个平台继续输入以下代码:

#include <unistd.h>

#include <stdio.h>

int main(int argc, char *argv[])

{

pid_t pid;

pid=fork();

if(pid<0)

{

perror(“fork”);

return 0;

}

else if(pid == 0)

{

while(1)

{

printf(“this is son process\n”);

sleep(1);

}

}

else

{

while(1)

{

printf(“this is father process\n”);

sleep(1);

}

}

return 0;

}

现在让父进程循环打印、子进程循环打印,以前没有多任务的时候,只有一个while在循环,另外一个while不会执行到,现在有两个while同时在运行,子进程在循环干什么事?

每隔一秒打印一句话,父进程当中也给它一个循环,这两个进程是独立的,各干各的事。

2、代码实现

将以上代码执行,结果如下:

[01_day]1s

aaa.txt dest.txt my_cp my_cp.c pid pid.c read read.c test.txt wanqi.txt

[01_day]vi fork.c

[01_day]gcc fork.c -o fork

[01_day]./fork

this is father process

this is son process

this is father process

this is son process

3、代码说明

可以看到两个循环都在执行,注意它是两个独立的进程,操作系统是调度这两个进程,意思是先调到父进程,可以看到每次调的都是父进程,这是根据操作系统的调度算法来确定的,

注意:

一旦创建一个进程之后,到底是先调度哪一个进程取决于操作系统,这是不确定的,要是非得让某一个进程先执行,就得用同步互斥了。可以看到现在是两个进程在并发的在执行,两个while都在执行,这就实现了多任务,父进程干一个事情,子进程干一个事情,这是第一个多任务的程序,所以需要清楚多任务程序的框架,代码一模一样,父进程在哪执行、执行哪一块代码、子进程执行哪一块代码,因为父子进程的代码是完全一样的。

另外需要注意:

子进程是从fork之后执行的,不是从main函数开始执行的,就是生它的地方往后执行,到这里fork就已经讲完了,大家可以自己将上文中的代码实现一下,实现一个并发的程序,看看是不是两个进程同时在运行。

相关文章
|
2月前
|
Linux C语言
C语言 多进程编程(三)信号处理方式和自定义处理函数
本文详细介绍了Linux系统中进程间通信的关键机制——信号。首先解释了信号作为一种异步通知机制的特点及其主要来源,接着列举了常见的信号类型及其定义。文章进一步探讨了信号的处理流程和Linux中处理信号的方式,包括忽略信号、捕捉信号以及执行默认操作。此外,通过具体示例演示了如何创建子进程并通过信号进行控制。最后,讲解了如何通过`signal`函数自定义信号处理函数,并提供了完整的示例代码,展示了父子进程之间通过信号进行通信的过程。
|
2月前
|
编译器
【收藏】内核级利用通用Hook函数方法检测进程
【收藏】内核级利用通用Hook函数方法检测进程
|
3月前
|
Linux API
Linux源码阅读笔记07-进程管理4大常用API函数
Linux源码阅读笔记07-进程管理4大常用API函数
|
4月前
|
小程序 Linux
【编程小实验】利用Linux fork()与文件I/O:父进程与子进程协同实现高效cp命令(前半文件与后半文件并行复制)
这个小程序是在文件IO的基础上去结合父子进程的一个使用,利用父子进程相互独立的特点实现对数据不同的操作
102 2
|
4月前
|
NoSQL Linux Redis
c++开发redis module问题之避免在fork后子进程中发生死锁,如何解决
c++开发redis module问题之避免在fork后子进程中发生死锁,如何解决
|
5月前
|
算法 Linux 调度
Linux进程——进程的创建(fork的原理)
Linux进程——进程的创建(fork的原理)
194 2
|
5月前
|
运维 JavaScript Serverless
Serverless 应用引擎产品使用合集之函数计算里中FC出现函数还没有执行完进程就关闭了是什么导致的
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
6月前
|
Linux Shell 程序员
【进程控制】进程程序替换的原理以及exec函数族
【进程控制】进程程序替换的原理以及exec函数族
|
6月前
|
存储 算法 Unix
【创建进程】fork函数与写时拷贝
【创建进程】fork函数与写时拷贝

相关实验场景

更多
下一篇
无影云桌面