Linux操作系统软件编程——多进程
什么是多任务
多任务:让系统具备同时具备处理多个任务的能力
实现多任务的方式:多进程;多线程
进程
什么是进程
正在运行的程序,其运行过程中需要消耗内存和CPU,是操作系统资源分配的最小单位
main.c(程序)(硬盘)-----a.out(程序)(硬盘)-------./a/out(进程)(内存)
程序和进程的区别:
程序是静态的数据集合,存储在硬盘空间,程序运行起来可以产生进程,而一个程序可以产生多个进程;
进程是一个程序动态执行的过程,需要消耗内存和CPU,具备动态生命周期,从产生到调度再到消亡,一个进程可以执行多个程序
进程的产生
进程产生时,操作系统会为其分配0-4G的虚拟内存空间,其中1G用于内核,剩下3G用于四大区
内核作用:文件管理,进程管理,内存管理......
内存空间四区域:栈区、堆区、数据区、文本区
栈区:保存局部变量、函数的形参和返回值;保存函数调用关系(保护现场和恢复现场)
堆区:由开发人员手动分配;使用完要手动释放
数据区:
字符串常量区:保存字符串常量
bss段:未初始化的全局变量;未初始化的静态变量(static)。这是由于bass段初始时按位清零
只读数据段:已初始化的全局变量;已初始化的静态变量
文本区:存放指令代码和常量
进程的调度
cpu:数据处理速度快,遵行宏观并行,微观串行的调度方式,即在微观上先执行进程一个再进程另一个,而在宏观上显示的是同时进行
cpu调度算法:
1)时间片轮询算法,会根据每个任务的执行情况分配时间片,每个任务运行一定时间再跳到下一个任务
2)先来先服务,后来后服务(任务队列)
3)短作业优先调度,优先处理完时间较短的程序
4)高优先级限制性,低优先级后执行,有的cpu会高优先级任务打断低优先级任务
进程的状态
操作系统进程的三态图

Linux操作系统进程状态:

运行态(用户运行态、内核运行态):正在执行,且被CPU任务调度所执行的进程
就绪态(R):正在执行,没有CPU任务调度执行的进程(只缺少CPU)
可唤醒等待态(S):也称睡眠态,阻塞等待资源的进程,类似于阻塞态,可以被主动唤醒
不可唤醒等待态(D):不想被CPU任务调度所打断的进程任务可设置未该状态,只能自己睡醒
暂停态(T):被暂停执行的进程
僵尸态(Z):进程直接结束,空间没有被回收
结束态(X):进程执行结束,空间被回收
进程的消亡
1,进程执行结束(进程退出)
2,回收进程资源空间
进程相关密令
1. ps -aux:查看进程相关参数,以下为参数名称
USER:创建的用户
PID:进程的ID号
VIRT、SHR、S:与内存有关
%CPU,%MEM:CPU占用率,内存占用率
TTY:当前进程关联的终端,如果是问号“?”则表示该进程与任何终端都不关联
STAT:表示当前进程的状态
START:进程启动的时间
COMMAND:进程名称
PR NI:该进程的优先级,PR越小越高
| : 管道 ,前面命令的输出作为后面命令的输入
grep : 字符串查找:在输入中查找和后面字符串相关的数据
所以可以用ps - aux | grep 进程名来查找某一进程,其他密令也可以通过类似操作
2. top:动态查看进程的相关参数
3. ps -ef:查看该进程的ID和父进程ID
PPID :父进程ID号
父进程:产生子进程的进程称为父进程
子进程:父进程产生出来的新进程即为该父进程的子进程
STIME:启动的时间
TIME:被CPU调度的时间
CMD:进程名称
4. pstree:查看进程的产生关系
pstree -p:查看进程的产生关系(有PID号)
pstree -sp 进程PID号:查看某个指定的进程的产生关系
5. kill -信号的编号或者信信号的名称 PID:向进程发送信号,让进程的状态发生变化
kill -l:查看系统支持的信号
例子:
kill -9 PID、kill -SIGKILL PID、killall -9 进程名称:结束PID号的进程
kill -19 PID:将状态改为休眠态
6. jobs:查看当前终端的后台进程
带加号“+”的表示是前台进程,不带的是后台进程
7.fg 后台进程编号:让后台进程切换成前台进程
进程相关编程
进程创建:fork()
进程调度:操作系统完成
进程消亡:
1,进程退出:return、exit()相关函数
注意:必须是main中的return
2,回收资源空间:wait()、waitpid()
僵尸进程:进程退出后,但其资源空间未被父进程回收
如何避免僵尸进程产生:
1. 子进程退出后,父进程及时为其回收资源空间
2. 让该进程成为一个孤儿进程,结束时被操作系统中的系统进程回收。
3.孤儿进程:父进程先消亡,其对应的子进程成为一个孤儿进程,会被系统进程所收养,例如守护类的进程就是孤儿进程
fork()


功能:通过拷贝父进程产生一个新的子进程,会有两个进程同时在工作,所以如下代码会有两次。子进程完全拷贝父进程0-3G的虚拟内存空间。子进程拷贝父进程PCB(进程控制块)中的部分内容:PID不拷贝


返回值:

注:
1. 子进程完完整整拷贝父进程0-3G虚拟内存空间,至于先调度谁取决于CPU,但是子进程是从fork下一行开始运行
2. 父子进程栈区、数据区、文本区、堆区完全独立,数据不共享
3. 要想共享数据,需要使用进程间通信方式实现

值得注意的是,fork返回的pid号只是作为父子进程内部的自我标识,而非真正的pid号,所以在通过类似ps -ef | grep ./a.out显示出的pid号并不为子进程返回的0。可以通过子进程的PPID等于父进程的PID来区分父子进程
getpid()、getppid()

功能:获取该进程的pid号,获得父进程的pid号
sleep()

功能:使进程休眠一定时间
exit()

![]()
功能分为三种情况
exit()、_exit():结束一个进程
exit(0):正常退出
exit(!0):由于进程产生某种问题,需要主动退出进程
wait()


功能:阻塞等待回收子进程的资源空间(即使子进程先结束)
参数:保存子进程消亡状态的变量地址,如果是NULL,则不保存子进程退出的状态
wait的参数可以接收子进程返回的值,这个数字代表了一个具体的消亡状态,在系统中定义了不同的宏
返回值:成功则为回收到的子进程的PID号,失败则为-1
效果:造成同步的效果。进程本身是异步的效果,即这个进行这个那个进行那个,而同步就是导致进程有了进行的顺序
那么什么是阻塞等待回收呢?如果父进程使用了该函数,则子进程结束后才会继续进行父进程的代码,以下为例



第一个为没加wait时的结果,第二个为加了wait后的结果
waitpid()

功能:回收指定子进程的资源空间,和wait功能类似,但是比wait更灵活
参数:
pid:
>0:回收指定ID的子进程
0:回收和当前调用waitpid一个组的所有子进程,回收组内的所有子进程
-1:回收组内组外的任意子进程
<-1:回收指定进程组内的任意子进程(例如-100,表示等待回收GID(组ID)=100的进程组中的任意子进程)
wstatus:子进程退出时候的状态,如果不关注退出状态则用NULL
options:如果是0则表示回收过程会阻塞等待;如果是WNOHANG表示非阻塞模式回收
返回值:成功则为接收资源的子进程pid,失败则为-1,如果设定为非阻塞且没有回收到子进程则为0
子进程资源空间回收策略
1,wait阻塞回收:一般情况下,父进程专门负责资源回收
2,waitpid非阻塞方式回收:必须搭配轮询方式回收
3,不回收:子进程的任务需要一直执行
4,异步回收:当子进程结束时通知父进程进行回收
exec函数族

作用:在进程内执行另外一个可执行文件
execl
l:list,以列表的形式传递
参数:要执行的文件的路径和名称(包括系统文件,可以通过whereis+命令查看文件的位置);执行该可执行文件时需传递的参数;多个和前面相似的参数,若没有则填NULL
返回值:出错则为-1
本质:将文本区的指令代码替换成exec要执行的文件的指令,整个过程没有新的进程产生


结果只输出了new,所以该类函数是代替,而非产生
execlp
p:path,以路径的方式传递,路径一般为系统路径
功能:从PATH指定的系统路径下寻找该可执行文件
参数:需要执行的可执行文件的文件名(系统路径下已有的),其余与execl相同


execv
v:vector,以容器的方式传递
参数: 要执行的文件的路径和名称;将参数放在一个数组内,传递这个数组的指针,数组内参数形式和execl相同


e:env,以环境变量的方式传递,可以直接在终端输入env查看环境变量
sysytem

参数:指令字符串,例如ls,touch

该函数与exec不同,它重新产生了一个子进程,该子进程运行过后继续进行父进程的代码,所以相当于父进程使用了wait()
更多推荐



所有评论(0)