当前位置: 首页 > news >正文

c语言多任务处理(并发程序设计)

. 多任务处理(并发程序设计)
1. 何谓多任务处理?
多任务处理是指同一时间内处理或者执行多个独立的功能任务,这样的事物处理方法
称为多任务处理。

 2. 多任务处理方式的背景?
应用程序中往往是要支持多种复杂功能,我们就不能按照以前,某个功能执行完毕后再执行下一个功能任务,
设计方式来设计程序,我们期望的是某些独立的功能任务可以在同一时间共同执行(并发),以提升程序的运行
效率,这样就需要多任务处理方式了。

 3. 多任务处理方式的实现
3.1  多进程
3.2  多线程

 4. 进程初步
4.1  基础概念
1) 进程:
统一认知:进程是程序的一次执行过程,是程序执行和资源管理的最小单元
2) 进程的资源信息描述 (PCB)
PCB(进程控制块):用于记录系统对进程资源,状态,标识符分配信息等等
本质是Linux内核提供的一个数据类型 (struct task_struct)来表示。
3) 进程的标识(PID)
PID(进程号):用来唯一标识系统中的一个进程,本质是非零的正整数。
4.2 进程特征  
4.2.1  独立性:进程一旦产生系统会为每一个进程分配4GB虚拟地址空间,每一个进程都运行在自己的
虚拟地址空间中,互不干扰
4.2.2  并发性:不同的进程可以在同一时间内同时运行;
4.2.3  异步性:由于进程要竞争CPU资源,所以会产生周期性的等待,也就是说进程其实并不是"齐头并进";
4.2.4  动态性:因为进程是程序执行过程,有创建及消亡的过程,
4.2.5  结构特征:
统会为每一个进程分配4GB虚拟地址空间,同时系统将该地址空间进行可结构划分,主要划分为
以下的内存结构,(自下而上)

           代码段
数据段
堆段
内存映射段
栈段
命令行参数段
环境变量存储段
4.3 进程的模式
4.3.1  内核模式:
不可被干扰,内核模式执行完毕,进程会转入用户模式:
4.3.2  用户模式
大部分情况下,进程都是运行在用户模式的,一旦遇到系统调用或者发生硬件中断,进行
将转入内核模式.

     4.4 进程的状态及状态转换

          基本状态:
1)   运行状态:   进程正在运行
2)   就绪状态:   进程已经获取除了CPU之外的所有资源,一旦分配CPU资源就可以运行
3)   阻塞状态:    进程因为等待某个事件的发生,暂停运行
4)   僵尸状态:   进程已经运行完毕,但是进程资源(PCB)没有被回收
5)   停止状态:   进程已经运行完毕,进程资源(PCB)被回收


状态转换:   详见  进程状态转换.bmp

      注意事项: 如果在实现多任务处理过程中,选择使用多进程解决方案,则一定要确保父进程不能先于子进程
退出,否则会造成程序已经运行结束的假象。而且使得子进程称为孤儿进程。

  5. 进程基础操作
5.1   进程创建
函数头文件    #include <unistd.h> 
#include <sys/types.h> 
函数原型:     pid_t fork(void) / pid_t vfork(void)
函数功能:    进程创建
函数参数:    无
函数返回值:  说明:fork/vfork 调用一次返回两次:
成功  子进程返回0
父进程返回子进程PID
失败 返回 -1, 错误码放在errno

          fork / vfork 区别:
1. fork 创建子进程成功后, 系统为子进程分配独立的地址空间
vfork 创建子进程成功后,子进程和父进程共享父进程的地址空间
2. fork 创建子进程成功后, 父子进程执行顺序取决于系统的调度
vfork 创建子进程成功后,子进程先于父进程运行,子进程只有在调用了
exit/_exit 及 exec函数簇,父进程才可以正常运行。
3. 应用场景:
1.在系统硬件资源充足的情况下,推荐使用fork创建进程,否则使用vfork,
2.在使用exec函数簇时,推荐使用vfork创建子进程,在子进程中利用exec启动新程序。

5.2   获取进程ID
函数头文件    #include <unistd.h> 
#include <sys/types.h> 
函数原型:     pid_t getpid(void) / pid_t getppid(void)
函数功能:    进程ID获取
函数参数:    无
函数返回值:  说明:getpid  返回自身进程ID:
getppid 返回父进程ID:                    
该函数调用不会失败 
5.3   进程退出
函数头文件    #include <unistd.h> 
#include <stdlib.h> 
函数原型:     void exit(int status) / void _exit(int status)
函数功能:    进程退出
函数参数:    status: 进程退出后传递给父进程的数据(status & 0377)
函数返回值:  无

exit / _exit 区别:
1.  exit 是标准库函数, _exit Linux内核函数
2.  exit 在进程退出前会处理IO缓存。
5.4   进程等待
函数头文件    #include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
函数原型:     pid_t wait(int *status) /pid_t waitpid(pid_t,pid,int *status,int option)
函数功能:    阻塞调用进程,直到某个子进程/指定子进程 退出
函数参数:    [OUT]status: 用户获取子进程退出值(需要利用 WEXITSTATUS 宏转换)
pid:  指定的子进程ID
option: 附加选项: 往往取值为0
函数返回值:  退出的子进程ID

说明: 进程等待的目的:
1. 父进程想要获取子进程退出值;如果父进程不关注子进程的退出值,status可以设为NULL
2. 回收子进程的进程资源。
3. 为了确保父进程不能先于子进程退出。

      5.5  进程中启动新程序
函数头文件    #include <unistd.h> 
函数原型:     int execl (const char *path,const char* arg,...);
int execlp(const char *file,const char* arg,...);
int execle(const char *path,const char* arg,...,char* const envp[]);

              int execv (const char *path,const char* argp[]);
int execvp(const char *file,const char* argp[]);
int execve(const char *path,const char* argp[],char* const envp[]);

        函数功能:    进程中启动新程序
函数参数:    path:待启动的应用程序路径
arg:  待启动的应用程序命令行参数,以程序名开始,NULL结束
argp: 存储待启动的应用程序命令行参数的字符指针数组,元素以程序名开始,NULL结束
envp:用户自定义环境变量数组(NULL结束),用于在启动新程序的同时,传递给新程序的数据。
函数返回值:  成功返回0
失败返回-1,错误码放置在errno          

          引申的知识点:  自定义环境变量

自定义环境变量的语法格式:
环境变量名(大写) = 环境变量值 (字符串)

            例子: NAME = TeacherYu
AGE  = 45
char* const envp[] = {"NAME = TeacherYu"," AGE  = 45",NULL};

      exec函数簇的区分:

函数名的第五个字符:    
l:  (list)    利用exec函数参数罗列被启动程序的命令行参数
v:  (vector)  用数组将被启动程序的命令行参数先存储起来,然后将数组传递给exec函数参数

         函数名的第六个字符:
无:  
p: (Path):系统会到PATH环境变量所代表的路径下去找寻待启动程序,如果未找到,exec函数调用失败
e: (enviorment): 在启动启动程序时,可以通过自定义环境变量向待启动程序传递数据。

http://www.xdnf.cn/news/1331803.html

相关文章:

  • 挑战极限:在256MB内存的机器上构建MySQL极简安装方案
  • 基于SpringBoot的旅游攻略系统网站【2026最新】
  • mysql-8.0.37-linux-glibc2.12-x86_64安装
  • 【shell脚本编程】-7 寻找到在5分钟内改动的文件
  • 【C++】基础:C++11-14-17常用新特性介绍
  • 【Obsidian插件】HiNote
  • ansible playbook 实战案例roles | 实现db2自动安装
  • spring第9课,spring对DAO的支持
  • 【C++】模版(初阶)
  • 【STM32】HAL库中的实现(六):DAC (数模转换)
  • wpf之ComboBox
  • uniapp学习【上手篇】
  • Ubuntu 重连usb设备(断电和不断电方案)亲测可行
  • 【科研绘图系列】R语言绘制平滑曲线折线图
  • SQL面试题及详细答案150道(41-60) --- 条件查询与分组篇
  • 【报错】Please do not run this script with sudo bash
  • 开源大模型如何选择?GPT-OSS综合评估
  • IDEA切换分支时,提示:Git Checkout Problem
  • 4位量化:常规的线性层被替换成了4位线性层(48)
  • 服务器硬件电路设计之 SPI 问答(二):SPI 与 I2C 的特性博弈及多从机设计之道
  • 基于单片机环境火灾安全检测
  • 27.语言模型
  • 3D max制作蝴蝶结详细步骤(新手可跟)♥️
  • Angular入门教程
  • Angular由一个bug说起之十八:伴随框架升级而升级ESLint遇到的问题与思考
  • 【机器学习】什么是损失景观(Loss Landscape)?
  • FPGA实现Aurora 64B66B图像视频点对点传输,基于GTH高速收发器,提供2套工程源码和技术支持
  • 大数据毕业设计选题推荐-基于大数据的1688商品类目关系分析与可视化系统-Hadoop-Spark-数据可视化-BigData
  • 新手向:使用STM32通过RS485通信接口控制步进电机
  • 实验8.20