Linux—进程-PCB-状态-孤儿进程-环境变量-0801 4

本文详细介绍了Linux操作系统中的进程控制块(PCB)、task_struct结构体及其内容分类,以及如何查看和管理进程。讨论了进程状态,包括僵尸进程和孤儿进程,以及如何避免僵尸进程的危害。同时,阐述了进程优先级和调度算法,如时间片轮转、短作业优先等,并探讨了环境变量的作用和常见类型。通过对系统调用的讲解,展示了如何获取和设置环境变量。
摘要由CSDN通过智能技术生成

目录

1. PCB

2. task_ struct内容分类

3. 查看进程

4. fork

4.1 创建子进程的逻辑

5. 进程状态

5.1 僵尸进程危害

6. 孤儿进程

7. 进程优先级

7.1 查看进程优先级的命令

7.2 进程调度算法

7.3 调度优先级

8. 环境变量

8.1 常见的环境变量

8. 2相关命令

8.3 通过系统调用获取或设置环境变量

8.4 环境变量通常是具有全局属性的


文件=内容+属性

可执行程序加载到内存中时,仅是把内容拷贝,在内存会创建一个PCB用以保存了包含进程所有属性的结构体。于是对进程的管理,变成了对进程PCB结构体链表的增删查改。

linux对程序的管理理念是先描述,后管理。

PCB:进程控制块。就是描述进程的结构体。

什么叫做进程:进程=对应的代码和数据+进程对应的PCB结构体。

1. PCB

在不同的操作系统中,PCB名字不一样。在linux操作系统中为 task_struct

2. task_ struct内容分类

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器: 程序中即将被执行的下一条指令的地址。
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]
  • IO状态信息: 包括显示的I/O请求,分配给进程的IO设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  • 其他信息

3. 查看进程

ps axj显示所有进程

ps axj | head -1  拿到第一行

ps axj | grep 'myproc' 显示关键词进程 //myproc是一个一直在运行的进程。

 pid :进程id

ls /proc 查看所有进程的目录(动态的)

 get pid 获得进程id     get ppid 获得父进程id

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    while(1)
    {
        pid_t id =getpid();//获取的是自己的进程PID
        printf("hello world,pid: %d\n",id);
        sleep(1);
    }
    return 0;
}

kill -9 pid  结束对应pid的进程

父进程永远都是bash kill -9 ppid   Xshell将不能正常运行。

4. fork

创建一个子进程 #include <unistd.h>

pid_t fork();

返回值:失败时:返回-1

成功时:a.给父进程返回子进程的pid

b.给子进程返回0

从fork往后程序变为两个

 

pid_t ret=fork();

printf("ret: %d\n",ret);

 

fork之后父进程子进程共享代码,解决方法:根据返回值不同进行不同程序。

#include <stdio.h>
#include <unistd.h>
int main()
{
    pid_t id =fork();
    if(id<0) 
    {
        //创建子进程失败
        perror("fork");
        return 1;
    }
    else if(id==0)
    {
        //子进程执行
    }
    else 
    {    
        //父进程执行
    }

    return 0;
}

4.1 创建子进程的逻辑

在内存中struct task_struct结构体中的内部属性要以父进程为模板。

return时核心代码已经执行完了吗?Y

为什么有两个返回值?

1.因为fork内部,父子会各自执行自己的return语句

2.返回两次,并不意味着保存两次。

父子进程谁先运行?不一定,由调度器决定

task_struct结构体按照算法排成队列(数据结构),CPU按照队列顺序先后执行。所以操作系统和cpu运行某一个进程,本质上就是从task_struct形成的队列中挑一个来执行它的代码。

进程调度:从task_struct形成的队列中挑一个

5. 进程状态

新建:字面意思

运行:task_struct结构体在运行队列中排队,就叫做运行态

阻塞:系统中存在各种资源(cpu,硬盘,网卡等),不在cpu队列中排队而在其他资源中排队称阻塞态。

挂起:当内存不足的时候,操作系统通过适当的置换进程的代码和数据到磁盘,进程的状态就叫做挂起。

进程分为 前台进程 和 后台进程(&)

R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠 )。
D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态,在这个状态的进程通常会等待IO的结束。
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。 终止状态,瞬时性很强
Z:僵尸状态。进程已经退出,而还不允许被操作系统释放,处于一个被检测的状态。目的是维持该状态,为了让父进程和操作系统来进行回收。只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

只有就绪态和运行态可以相互进行转换。其他都是单向转换。

就绪态的进程通过调度算法从而获得CPU时间,转为运行状态。而运行状态的进程,在分配给他的CPU时间片结束之后,就会转为就绪态,等待下次CPU调度。

当外部事件发生时,阻塞态可以转为就绪态,如果此时没有其他进程运行,便转为运行态。

5.1 僵尸进程

当自进程退出,父进程运行,子进程必须等到父进程捕获到了子进程的退出状态才真正结束,在子进程退出后,父进程读取状态之前,此时称为僵尸状态。

僵尸进程的目的是为了维护子进程的信息,为了方便父进程以后在某个时候获取。但是僵尸进程会占据内核资源,需要避免僵尸进程的产生或者立即结束子进程的僵尸状态。

5.1.1 僵尸进程的危害

Z状态一直不退出,PCB一直都需要维护.PCB本身是做为一个结构体变量存在某数据结构中,数据结构的开辟需要空间,会带来内存泄漏。

5.1.2 如何避免僵尸进程

  1. ⽗进程调⽤wait/waitpid等函数等待⼦进程结束,如果尚⽆⼦进程退出wait会导致⽗进程阻塞。 waitpid只会等待由pid参数指定的⼦进程,同时也是⾮阻塞,⽬标进程正常退出返回⼦进程PID,还没结束返回0。
  2. 通过 signal() 函数⼈为处理信号 SIGCHLD。只要有⼦进程退出⾃动调⽤指定好的回调函数,因为⼦进程结束后, ⽗进程会收到该信号 SIGCHLD ,可以在其回调函数⾥调⽤ wait() 或 waitpid() 回收;
  3. 忽略SIGCHLD信号,这常⽤于并发服务器的性能的⼀个技巧因为并发服务器常常fork很多⼦进程,⼦进程终结之后需要服务器进程去wait清理资源。如果将此信号的处理⽅式设为忽略,可让内核把僵⼫⼦进程转交给init进程去处理,省去了⼤量僵⼫进程占⽤系统资源。

6. 孤儿进程

 父进程退出子进程还在,子进程就叫做孤儿进程。孤儿进程会被领养,被1号进程领养(init,系统本身该子进程的ppid变为1)目的是回收写在父进程,需要有进程帮助子进程回收。

7. 进程优先级

因为CPU有限,需要用过某种方式竞争资源。

ps -la 显示更详细进程

PRI:优先级.就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高

NI:nice值,其表示进程可被执行的优先级的修正数值.nice其取值范围是-2019,一共40个级别

优先级=老的优先级+nice值。在Linux环境下调整优先级,就是调整nice值。每次设置优先级都是根据默认值的优先级基础上增删。

7.1 查看进程优先级的命令

bash: top

进入 top 后按 “r”–> 输入进程 PID–> 输入 nice
CPU运行代码并不是执行完才进行下一个,有时间片,抢占与出让等概念。
并发:在一定时间段内,每个进程都有所推进。
并行 : 多个进程在多个 CPU 下分别,同时进行运行,这称之为并行.
如果进程A正在被运行,cpu内的寄存器里面,一定保存的是进程A的临时数据。寄存器的临时数据叫做A的上下文。当进程A暂时被切换下时,A需要带走自己的上下文数据,暂时保存进度。不可以被丢弃。

7.2 进程调度算法

1.先来先服务

非抢占式的调度算法,按照请求的顺序进行调度。

有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。

2.短作业优先

非抢占式的调度算法,按估计运行时间最短的顺序进行调度。

长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。

3.最短剩余时间优先

最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。

当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。
如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。

4.时间片轮转

注意:在所有非抢占CPU调度算法中,系统平均响应时间最优的是 短任务优先算法

7.3 调度优先级

当进程的时间片用完,此时降低进程的优先级,以给其他进程调度的机会,是合理的。

进程刚刚完成IO操作,刚进入就绪态等待被调度,此时降低他的优先级是不合理的。

进程持久处于就绪队列,一直没有被调度,此时更应该提高他的优先级。

进程刚开始运行就降低优先级,有可能会被其他进程抢断,也是不合理的。

8. 环境变量

现象:系统命令pwd ls不用跟路径,自己写的程序执行时需要带路径 ./myproc 。

查看环境变量:  echo $PATH

8.1 常见的环境变量

PATH :指定命令的搜索路径

HOME :指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)

SHELL :当前Shell,它的值通常是/bin/bash

普通用户和root用户的环境变量不相同。

8. 2相关命令

1.echo: 显示某个环境变量值
2. export: 设置一个新的环境变量
3. env: 显示所有环境变量
4. unset: 清除环境变量
5. set: 显示本地定义的 shell 变量和环境变量

8.3 通过系统调用获取或设置环境变量

#include <stdio.h>
#include <stdlib.h>
int main()
{
 printf("%s\n", getenv("PATH"));
 return 0;
}

8.4 环境变量通常是具有全局属性的

 在命令行上使用export 相当于定义了一个全局变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值