进程基本知识

前言

进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。进程是操作系统动态执行的基本单元,对我们学习操作系统有着很关键的作用

进程的标识符

pid_t 类型 代表的是进程号
进程号是独一无二的
要获取一个函数的进程,可以使用getpid() getppid()
getpid返回当前进程标识,getppid返回父进程标识

进程的产生

pid_t fork(void);
功能:该函数可以动态的生成一个同名进程。
父子进程具有相同的逻辑和空间,类似于克隆程序。
但是父子进程执行的位置不同,子进程永远从fork函数之后执行。
如果要区分父子进程的执行逻辑,可以根据函数返回值来判断
约定 fork返回值为0 的是子进程执行逻辑
fork返回值>0 的是父亲进程执行逻辑

参数:无
返回值:
大于0 表示父进程
等于0 表示子进程
小于0 表示异常
对于克隆的理解,克隆的意思就是完全的复制出来一个相同的程序,他们享有相同的物理内存。
对于连续使用两个fork函数,会有一个父亲进程,一个兄弟进程,两个孙子进程

fork后父子进程的区别:fork的返回值不一样,pid不同,ppid也不同,未决信号和为文件锁不继承,资源利用率清零
init进程:1号,是所有进程的祖先进程
调度器的调度策略来决定哪个进程先运行
fflush的重要性(就是在fork复制完后需要刷新缓存区,不然会出现在输出的时候出错)

进程的终止

正常终止
从main函数返回
调用exit函数
调用_exit或_Exit ------ 和exit的区别一个是系统调用一
个是库函数,还有_exit函数是不执行钩子函数和内存清理

最后一个线程从其启动历程返回
最后一个线程调用pthread_exit

异常终止
调用abort
接到一个信号并终止
最后一个线程对其取消请求做出相应
atexit ()钩子函数

进程的消亡及释放资源

1、进程的退出
return 关键字:在main函数中,表示进程结束。
在非main函数中,表示当前函数结束调用。

1.1 在父子进程中都可以使用return关键字结束进程。

1.2 exit函数
#include <stdlib.h>

void exit(int status);
功能:使进程正常终止
参数:status 进程结束时候的状态,用于返回进程调用者
返回值:无

1.3 _exit函数
#include <unistd.h>

void _exit(int status);
功能:类似exit函数可以使进程正常结束。

exit和_exit函数的区别,exit结束时候会自动刷新缓存区
_exit结束时候不会刷新缓存区

僵尸进程:父子进程创建后,子进程退出
父进程运行
子进程变为僵尸进程
判断依据: ps axf ==>STAT 列为 Z

孤儿进程:父子进程创建后,父亲进程退出
子进程运行
子进程变为孤儿进程

判断依据: ps -ef ===>PPID 列为 系统pid
R:运行态
S:睡眠态,可以被信号或者事件唤醒
D:沉睡态,不可以被信号或者事件唤醒,只可以被硬件唤醒
T:停止态
X:终止态,程序正常结束
Z:僵尸态,程序结束,没有人回收资源(一般父进程给自进程收尸)
如果父进程消亡,会被init进程接管
孤儿态:父进程消亡
孤儿僵尸态:父进程消亡,没人回收资源

进程的回收

2.1 wait 函数回收
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
功能:该函数可以阻塞等待并回收任意子进程退出的资源。
一次该函数执行只能回收一个子进程的资源。
该函数只能有创建者进程调用,否则无效。
参数:status 回收的子进程返回的状态,如果不关注
子进程的返回值,则用NULL表示,如果要关注
子进程的返回值,则用WEXITSTATUS获取返回值。
pid_t waitpid(pid_t pid, int *status, int options);
功能:该函数可以指定回收进程的资源信息。
参数:pid 要回收的目标进程pid号,
特殊: pid > 0 要回收的目标pid
pid = 0 相同组id的进程
pid = -1 任意子进程,等价于 wait
pid < -1 按照pid的绝对值等于组id的进程
status 表示要回收的子进程资源信息,可以用WEXITSTATUS宏
获取其数据值;
options 回收子进程资源的方式,0 表示阻塞回收
WNOHANG 表示非阻塞回收
返回值:成功 回收资源的pid号
失败 -1
没有回收到资源 0

exec函数族

1、exec家族函数 ====>摆脱单文件写两个进程的复杂操作
使用exec家族函数完成其他程序的启动

int execl(const char *path, const char *arg, …);
功能:该函数可以用于启动一个指定路径+名称的程序。
参数: path 要启动的程序的路径+名称,一般是绝对路径。
arg 要启动的程序的选项,一般类似于 argv[0] argv[1] …
… 表示启动程序的参数,为可变长参数。
所有的参数到最后必须以NULL结尾。

返回值:成功 没有返回,当前进程空间转嫁到目标程序
失败 返回errno

int execv(const char *path, char *const argv[]);
功能:该函数可以将指定路径+名称的程序启动执行。
参数:path 要启动的程序路径+名称
argv[] 要启动的目标程序参数所构成的数组;
返回值:成功 不会返回,会转嫁到目标程序
失败 -1;
int execlp(const char *file, const char *arg, …);
功能:该函数可以启动指定的程序。
参数:file 要启动的程序名称,同时该程序要位于系统环境变量范围内 。
arg … 启动程序的参数,参考 execl 一样
返回值:成功 不会返回
失败 -1

*对excl函数的理解,可以用一句话表示就是“我还是我,但我已经不是我了”

理解

学完这三个函数其实可以发现在linxu世界中,其实就是由fork,excl,wait函数组成,由祖先进程init不断的通过fork函数进行克隆,然后通过excel函数变换,最后通过wait函数结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值