一. 多任务处理:
在应用程序中,可以同时去处理多个任务(功能),任务间是互相独立,这样的设计方式;
多任务处理的实现方式:
1. 多进程
2. 多线程
1. 进程及进程控制
1.1 什么是进程,进程如何标识?
进程是程序的一次执行过程,是系统进行资源分配的最小单元。
每当系统中产生一个进行,系统就会为该进程分配一个编号(PID),用来标识该进行
1.2 进程控制块(PCB)
用来记录或者存储进程在运行期间的一些信息数据的,(资源信息,PID,状态信息...),
以便进程结束后,系统可以进程资源的回收。
通过内核提供的 task_struct 结构体来描述的。
1.3 进程号(PID)
进程的标识,
本质:非零的正整数;
1.4 进程的特征:
1) 独立性: 每一个进程都是独立的运行在自己的虚拟地址空间的,互不干扰
2) 并发性: 多个进程可以同时运行
3) 异步性: 多个进程的运行并不是齐头并进的,而是有先后顺序;
4) 动态性: 进程有产生及消亡的过程,是一个活动的状态
5) 结构特征:进程的地址空间会被系统划为不同的内存结构
代码段: 程序指令
数据段: BSS数据段 存放未初始化的全局变量
只读数据段 存放初始化的全局变量,静态变量 常量
堆段: 动态申请存放数据
栈段: 局部变量
1.5 进程的工作模式:
1) 用户模式
2) 内核模式
1.6 进程的状态及状态转换
运行态: 进程正在运行...
就绪态: 进程除了CPU资源外,已经具备了其他所有资源
阻塞态: 进程因等待某时间发生而暂停运行
停止态: 进程结束了
僵尸态: 进程结束了,但PCB尚未回收
1.7 进程的基本操作
1) 进程创建
fork / vfork
头文件: #include <sys/types.h>
#include <unistd.h>
函数原型: pid_t fork(); / pid_t vfork();
函数功能: 创建子进程
函数参数: 无
函数返回值:
成功 :父进程中返回子进程的ID
子进程中返回0
出错 :返回-1. 错误码存放在 errno
fork与vfork 函数的区别:
1. fork 函数创建的子进程与父进程具有各自的地址空间,
vfork 函数创建的子进程与父进程共享父进程的地址空间,
2. fork 函数创建的子进程与父进程的运行顺序取决于系统的调度策略,
vfork 函数创建的子进程会先于父进程运行,
3.注意:vfork 创建的子进程只有调用了 exec 族函数 或 exit/_exit 函数后
父进程才能正常运行;
2) 获取进程ID
getpid / getppid
头文件: #include <sys/types.h>
#include <unistd.h>
函数原型:pid_t getpid(); / pid_t getppid();
函数功能: 获取自身PID / 获取父进程PID
函数参数: 无
函数返回值: 返回相应数据
3) 进程等待
wait / waitpid
头文件: #include <sys/types.h>
#include <unistd.h>
函数原型: pid_t wait(int *status); / pid_t waitpid(pid_t,pid,int *status,int option);
函数功能: 阻塞调用进程,直到某子进程退出
函数参数: status:用来接收子进程退出时返回给父进程的状态数据
需要借助 WEXITSTATUS() 来转换
pid: 指定等待的子进程ID
option: 附加选项,往往写0;
函数返回值: 已结束的子进程PID
4) 进程退出
exit / _exit
头文件: #include <sys/types.h>
#include <unistd.h>
函数原型:void exit(int status); / void _exit(int status);
函数功能: 结束进程
函数参数: 返回给父进程的状态数据
函数返回值: 无
5) 启动新程序
exec 函数族/函数簇
头文件: #include <sys/types.h>
#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, char* const arg[]);
int execvp(const char* file,char* const arg[]);
int execve(const char* path,char* const arg[],char* const envp);
函数功能: 在调用进程中启动新程序,覆盖调用进程的地址空间
函数参数: path:目标程序的路径
arg: 目标程序的命令行参数
envp:自定义环境变量的数组,存储传递给被启动程序的数据。
函数返回值: 已结束的子进程PID
自定义环境变量: 格式: 变量名=值
例如: TITLE=五一小长假你想去哪里
char* const envp[] = {"TITLE=五一小长假你想去哪里","CONTEXT=是否想去天涯海角",NULL};
execle(tarDir,tarname,...NULL,envp);
exec 族函数的区分方法:
第五字符: l : list 罗列 : 被启动的程序的命令行参数需要一一罗列
v : vector 动态数组 被启动的程序的命令行参数需要先放置到一个数组然后传递
第六字符:
无: 被启动的程序要指定路径
p: path: 如果被启动的程序是放置在PATH环境变量代表的路径下,被启动的程序
只需提供名称,不需要指定路径
e: enviorment: 可以通过自定义环境变量的方式向被启动的程序传递数据
注意: 由于exec族函数成功执行会覆盖调用进程的地址空间,所有如果想要保证调用进程及被启动的新程序能够
独立并发运行,那么具体做法为,先创建子进程,然后在子进程中调用exec族函数去启动新程序,
延伸知识:
system
头文件: #include <stdlib.h>
函数原型:int system(const char *command);
函数功能: 执行命令行程序
函数参数: 启动的命令行程序
函数返回值: 详情查看man手册