《Linux进程概念,进程创建退出等待替换,环境变量等基础操作 ---总结》

前言

Linux系统的进程概念,进程状态,以及操作创建进程,还有环境变量及相关指令,程序地址空间等一些知识的梳理,将自己的理解总结如下,希望和各位一起进步,一起学习。


以下是本篇文章正文内容。

一、Linux系统进程

1.概念引入

操作系统(OS):简单来说就是一个基本程序的集合,笼统的理解,操作系统包含内核(进程管理、内存管理、文件管理、驱动管理)和其他程序(例如函数库、shell程序等)。
为什么会有操作系统呢?
首先是为了与硬件交互,管理所有的软硬件资源。其次OS为用户程序(应用程序)提供一个良好的执行环境。
OS的定位是一个搞管理的软件。
系统调用:操作系统提供的用户访问系统内核的接口。
库函数与系统调用接口的关系:库函数实际上就是对系统调用接口进行的一层封装后的接口。
进程概念:简单来说就是运行中的程序称为进程。即:程序+执行=进程。
对于操作系统来说:进程就是一个程序运行的描述,通过这个描述,操作系统可以进行程序的调度运行管理。实际上对于系统来说,进程就是pcb。
这个程序运行的动态描述称为pcb进程控制块,通常在Linux系统下是一个task_struct结构体。
描述信息有:内存指针、上下文数据、程序计数器、进程ID–pid,IO信息,进程优先级,进程状态。
查看进程命令:ls /proc/
进程状态: 就绪态、运行态、阻塞态。
运行态(R):正在运行或者轮转到时间片则能够运行统称运行态。
可中断休眠态(S):可以被中断的休眠状态(满足唤醒条件或者休眠被中断则进入运行态)
不可中断休眠态(D):不能被中断的休眠状态(满足唤醒条件之后才会进入运行态)
停止态(T):程序停止运行的状态。(任然会被调度,但是什么都不做)
死亡态(X):这个状态只是一个返回状态。
僵尸态(Z):进程以已经退出不再调度了 ,但是这个进程的资源换没有被完全释放,等待处理的一种状态。
僵尸进程:处于僵尸态的进程,是一种退出了,但是资源没有完全被释放的进程。产生原因是:子进程先于父进程退出,但是父进程没有关注到子进程的退出,因此系统不会完全释放子进程的资源,这个子进程进入僵尸状态。子进程退出之后,在进程pcb中保存了自己的退出返回值,在父进程没有关注处理的情况下,pcb资源是不会被释放的。危害:资源泄露(一种是pcb所占的内存资源一直无法被回收,一种是一个用户能创建的进程数量是有限制的)。解决方案:一种是退出父进程来处理;另一种是进程等待来避免。
孤儿进程:父进程先于子进程退出,此时子进程称为孤儿进程。运行在后台,此时父进程成为1号进程(init进程)。孤儿进程被1号init进程领养。当然也是由init进程回收。

2.进程创建

创建进程:进程就是一个pcb是一个task_struct结构体(在Linux系统中),创建一个进程实际就是创建一个task_struct 结构体。使用以下接口创建:
pid_t fork()—创建进程的接口,即通过复制调用这个接口的进程(父进程),创建一个新的进程(子进程)。父进程返回大于0的值,子进程返回0,失败返回-1。
pid_t vfork()--通过复制父进程闯进子进程,父子进程共有虚拟地址空间,但是创建子进程后,父进程会阻塞,直到子进程exit退出或者子进程替换之后父进程才会运行。
父子进程的区分:由返回值确定。对于父进程会返回创建的子进程的pid,对于子进程会返回0,返回值小于0则错误。
getpid —查看进程ID。
ps -ef /aux–查看所有进程信息, 或者与管道符连接 ps -aux | grep fork
写时拷贝技术:创建子进程后,子进程与父进程各自有自己的虚拟地址空间,但是数据映射的实际上是同一块物理内存,等待内容发生改变的时候为子进程重新开辟一块独立的空间,保存子进程的数据(保持进程的独立性)。

3.进程退出

进程退出即退出一个进程。
退出进程的方式有:正常退出和异常退出两种。
正常退出方式有:通过以下三种退出方式退出的进程,查看结果是否符合预期。
1.main函数中调用return。
2.使用库函数void exit(int status);此exit函数可以在任意位置调用都可以退出进程。在退出之前会刷新文件缓冲区。
3.使用系统调用接口void _exit(int status);
exit和_exit区别:exit是库函数接口,在退出时会刷新缓冲区,然后释放资源;而_exit不会刷新缓冲区,直接进行资源释放。

异常退出:程序因为某些错误异常崩溃退出。
ctrl+c,信号终止。
查看上一次调系统调用接口使用错误原因的接口
void perror(const char s);
char strerror(int errnum);

具体使用如下代码:
在这里插入图片描述

4.进程等待

进程等待意思是父进程等待子进程的退出,获取退出子进程的返回值,释放退出子进程的资源,目的是为了避免产生僵尸进程。
进程等待操作
pid_t wait(int *status):其中status是一个整型空间的地址,此函数用于获取退出子进程返回值。成功则返回退出子进程的pid,失败则返回-1.此处的等待是等待任意一个子进程的退出,如果当前没有子进程退出则一直阻塞等待。需要注意的是:只要有退出的子进程,这个接口就会进行处理。
阻塞:为了完成一个功能,发起一个调用,若当前不具备完成条件,则一直等待。
非阻塞:为了完成一个功能,发起一个调用,若当前不具备完成条件,则立即返回。
pid_t waitpid(pid_t childpid,int *status,int options):可以等待任意一个子进程退出,也可以只等待指定的子进程。可以阻塞等待子进程退出,也可以非阻塞等待子进程退出。其中childpid:-1表示等待任意子进程,大于0表示等待指定的子进程;status:用于获取退出子进程的返回值;options:0表示默认阻塞等待,WNOHANG表示设置非阻塞等待。函数返回值:错误则返回-1,没有子进程退出则返回0.有子进程退出则返回子进程的id。

退出子进程返回值/wait的参数获取到的值:status不能简单的当作整型来看待,可以当作位图来看待。位图包含了进程退出返回值和异常退出信号值。其中异常信号退出值为0,表示进程正常退出,非0表示异常退出。

5.进程程序替换

程序替换:替换一个进程正在调度运行的程序,程序替换只是替换了运行的程序,而pcb中也只是重新初始化了一些信息(如虚拟地址空间,页表…)。在一个进程中执行程序替换接口,就能实现改变当前调用进程运行的程序。
exec函数族:以下函数中第一参数是新的程序文件路径名,第二个参数是程序运行参数,第三个参数是环境变量。如下函数所示:
其中l表示参数采用列表,v表示参数用数组,p表示由p自动搜索环境变量PATH,e表示自己维护环境变量。
extern char* environ;
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 argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char const envp[]);

exec函数有p时,程序文件若是命令程序可以不用带路径,默认去path环境变量指定的路径下找程序.带p的函数,常用于执行替换命令程序时使用;exec函数有e时,表示由我们自己设定环境变量,否则默认使用原有环境变量。

6.环境变量

环境变量:是一种变量,用来保存系统运行环境参数的变量,便于运行环境参数的配置和进程之间的数据通信(子进程的环境变量就是由父进程那而来的)。
命令操作
env:查看所有的环境变量
set:查看shell中所有的变量,不限于环境变量。
echo:查看指定变量
unset:删除环境变量
export:设置为环境变量
具体命令操作如下:先定义一个变量MYVAL=1000,此时用env命令查看环境变量是查看不了的,因为定义的MYVAL是一个变量,不是环境变量,但是可以用set命令查看,因为set可以查看所有的变量,如果要将MYVAL设置成环境变量用export命令即可完成,此时MYVAL已被定义为环境变量,使用env命令就可以看到了MYVAL的值了,当然也可以用echo $来查看变量,unset命令删除环境变量。
在这里插入图片描述
典型环境变量
PATH:程序运行的默认搜索路径–在命令行终端中输入命令名称可以直接执行对应名称的命令程序,实际上是因为shell捕捉到输入的命令名称之后,然后去PATH环境变量指定的路径下去找这个程序,找到了就运行,找不到就报命令没有找到的错误。
HOME:指定用户的主工作目录(即用户登录到Linux系统中时,默认的目录)
SHELL:它的值通常是/bin/bash。

环境变量接口
getenv:通过环境变量名称获取变量值。char *getenv(const char *name);
putenv: 增加或者改变环境变量值。int putenv(char *string);
注意:环境变量通常具有全局属性的,也就是说可以被子进程继承下去。

7.程序地址空间

地址:通常所说的地址是内存的地址,也就是内存单元的编号。
实际上在进程中,程序访问的这些地址(变量地址…)实际上是一个虚拟地址。我们所说的程序地址空间实际上叫做进程的虚拟地址空间。
虚拟地址空间实际上是系统给进程所描述的一个假的地址空间。是一个mm_struct结构体。并且每个进程都有自己独立的虚拟地址空间,也就是有自己的mm_struct内存描述。进程访问的都是虚拟地址,访问内存数据的时候,先将虚拟地址转换为物理地址然后访问
在这里插入图片描述
使用虚拟地址空间目的:为了让进程能够访问一块连续的,完整的地址,并且经过页表映射到物理内存之后,可以实现数据在物理内存上的离散式存储,提高内存的利用率,在页表中可以进行内存访问控制。

内存管理方式
1.分段式:将地址空间分为多段(代码段、数据段等),目的是便于编译器进行地址管理。分段式虚拟地址组成:段号+段内的地址偏移量;在系统中有一个段表:一个个段表项(段号,物理内存段起始地址)起始地址+段内偏移地址就是它的地址。

2.分页式:将地址空间分为多个小块(页),目的实现离散式存储,提高内存利用率。分页式虚拟地址组成:页号+页内偏移;在系统中有一个页表(页号,物理内存起始地址,权限控制,缺页中断位),页表:页号+物理块地址。

3.段页式:将虚拟地址空间进行分段,在每个分段内进行分页式内存管理,集合了分段分页的优点进行内存管理。

缺页中断:缺页中断表示当前地址要访问的数据不在物理内存中。

交换内存:当物理内存不够使用的时候,则将物理内存中不活跃的数据,保存到磁盘的交换分区中,腾出的物理内存可以给新的程序数据使用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值