Linux基础进程

Posted Ricky_0528

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux基础进程相关的知识,希望对你有一定的参考价值。

文章目录

4. 进程状态

方便操作系统快速判断进程,完成特定的功能,如调度,其本质是一种分类

4.1 分类

  • R(running)运行状态:它表明进程要么是在运行中,要么在运行队列里,并不意味着进程一定在运行中

当我们完成某种任务的时候,任务条件不具备,需要进程进行某种等待:S、D

不要认为进程只会等待CPU资源,等待CPU资源的叫运行队列,其余的叫等待队列

所谓的进程在运行的时候,有可能因为运行需要,可能会处在不同的队列里,其所处的状态是不一样的

  • S(sleeping)睡眠状态:当完成某种任务时,任务条件不具备,需要进程进行某种等待,也叫可中断睡眠

把从运行状态的task_struct(run_queue),放到等待队列中,就叫做等待挂起(阻塞)

从等待队列放到运行队列,被CPU调度就叫做唤醒进程

  • D(disk sleep)磁盘休眠状态:也叫深度睡眠、不可中断睡眠,在这个状态的进程通常会等待IO的结束

    可中断:可以被杀掉 不可中断:不可以被杀掉

  • T(stopped)停止状态:可以通过发送 SIGSTOP 信号给进程来停止进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行,区别于S状态,该状态会彻底暂停,数据不会发生更新

  • X(dead)死亡状态:回收进程资源,这个状态只是一个返回状态,不会在任务列表里看到这个状态

    回收进程资源 = 进程相关的内核数据结构 + 代码和数据

  • Z(zombie)僵尸状态: 维护进程的退出信息,数据存放在task_struct里,Z -> X

4.2 进程状态查看

  • 没有IO的情况

STAT:R+ 表示一直在前台运行(+:前台运行,前台运行时是无法在命令行输入命令的)

  • 有IO的情况

STAT:S+ 表示 IO 在等待外设就绪 R+ 表示正在运行

看起来一直在打印一直在运行,但因为IO等待外设就绪时需要时间的,比CPU慢很多,所以多数在S状态

  • 进程停止

    kill -19 17239
    

  • 进程停止后继续运行

    kill -18 17239
    

    此时程序在后台运行,STAT后面无+,这是可以在命令行输入命令,但无法通过 ctrl+c结束程序,只能通过kill -9 17239

    让一个进程在后台运行 ./proc & 在后面加上&

    输入fg可以再变回前台

  • 查看所有的信号

    kill -l
    

    可以向进程发送信号 kill -[信号值] [进程pid]

5. 僵尸进程

5.1 概念

  • 当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程,即进程退出没人管了
  • 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取子进程的退出状态代码
  • 子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
  • 监测运行状态的shell脚本

    while : ; do ps axj | head -1 && ps ajx | grep myproc | grep -v grep;
    sleep 1; echo "#######################"; done
    

5.2 危害

  • 子进程需要告诉父进程你交给我的任务完成的怎么样了,如果父进程一直不读取子进程的退出码,子进程将会一直处于僵尸状态
  • PCB会一直维护该进程
  • 会造成内存资源的浪费,因为数据结构对象本身就要占用内存
  • 会造成内存泄漏

6. 孤儿进程

父进程提前退出,子进程还在运行,则该子进程被操作系统接管,成为孤儿进程

孤儿进程被1号init进程领养,由init进程回收

7. 进程优先级

7.1 概念

  • cpu资源分配的先后顺序,就是指进程的优先级(priority)
  • 优先级高的进程有优先执行权利。配置进程优先级对多任务环境的 Linux 很有用,可以改善系统性能
  • 还可以把进程运行到指定的CPU上,这样把不重要的进程安排到某个CPU,可以大大改善系统整体性能

7.2 查看系统进程

ps -l 或 ps -al

  • UID:代表执行者的身份
  • PID:代表进程的代号
  • PPID:代表这个进程是由哪个进程发展衍生而来的,即父进程的代号
  • PRI:代表这个进程可被执行的优先级,其值越小越早被执行
  • NI:代表这个进程的nice值

PRI 和 NI

  • PRI:进程的优先级,就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高
  • NI:nice值,表示进程可被执行的优先级的修正数值
  • PRI(new) = PRI(old) + NI 其中PRI(old)为一个恒定值,一直维持不变,修改第二次时并不会继承第一次修改的
  • Linux下调整优先级就是调整nice值
  • nice取值范围为 -20 ~ 19,一共40个级别

PRI 对比 NI

  • 进程的nice值不是进程的优先级,两者不是一个概念,但是进程nice值会影响到进程的优先级变化
  • nice值是进程优先级的修正数据

7.3 修改进程的nice值

  • top
  • 进入top之后按 r
  • 输入进程PID
  • 输入要修改的nice值

注意

  • 优先级再怎么设置也只能是一种相对的优先级,不能出现绝对的优先级,否则会出现严重的“饥饿问题”
  • 调度器:较为均衡的让每个进程享受到CPU资源


7.4 其它概念

  • 竞争性:系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  • 独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰
  • 并行:多个进程在多个CPU下分别同时进行运行,这称之为并行
  • 并发:多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发

8. 环境变量

8.1 基本概念

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
  • 自己的可执行程序需要带上路径才能运行,而系统指令不需要带路径,就是因为环境变量的存在
  • 环境变量通常具有某些特殊用途,在系统当中通常具有全局特性

我们编写C/C++代码,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找

8.2 查看环境变量

echo $NAME NAME为环境变量的名字

常见的有

  • PATH:指定命令的搜索路径
  • HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
  • SHELL:当前Shell,它的值通常是/bin/bash

PATH环境变量

添加环境变量export PATH=$PATH:[要加入的环境变量文件路径]

export PATH=$PATH:/home/ricky/Process/lensson3

修改仅对当前会话有效

本地变量

系统上还存在一种变量,是与本次登录(session)有关的变量,只在本次登陆有效

一些命令

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

8.3 环境变量的组织方式

每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以 ’\\0’ 结尾的环境字符串

8.4 通过代码获取环境变量

  • 命令行参数

    • argc:参数个数,决定有几个有效命令行参数
    • args[]:保存命令行参数的字符串,其最后一个指向NULL
    • 可以使用命令行参数,来使程序呈现出不同的功能,即命令行使用不同的参数,程序执行结果也不一样
    #include <iostream>
    #include <unistd.h>
    #include <cstdio>
    
    int main(int argc, char* args[])
    
        for (int i = 0; i < argc; i++)
            printf("args[%d] -> %s\\n", i, args[i]);
    
        return 0;
    
    

  • 命令行的第三个参数

    #include <stdio.h>
    int main(int argc, char *argv[], char *env[])
    
    	for(int i = 0; env[i]; i++)
    		printf("%s\\n", env[i]);
    	return 0;
    
    
  • 通过第三方变量environ

    • libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时要extern声明
    #include <stdio.h>
    int main(int argc, char *argv[])
    
    	extern char **environ;
    	for(int i = 0; environ[i]; i++)
    		printf("%s\\n", environ[i]);
    	return 0;
    
    

8.5 通过系统调用换取环境变量(推荐)

getenv

常用 getenv 和 putenv 函数来访问特定的环境变量

#include <stdio.h>
#include <stdlib.h>
int main()

	printf("%s\\n", getenv("PATH"));
	return 0;

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

具有全局属性的本质:环境变量可以被子进程继承下去

将自己定义的变量导入环境变量:export MYENV="aaaaaaaaaaaaa"

#include <iostream>
#include <unistd.h>
#include <cstdio>

int main()

    char* env = getenv("MYENV");
    if (env)
        printf("%s\\n", env);

    return 0;

结果发现输出了 aaaaaaaaaaaaa
但若没有用 export 导入,则不会输出结果,导入之后 MYENV 属于 .bash 这个进程
而 myproc 属于 .bash 的一个子进程,故其可继承来自 .bash 的环境变量

以上是关于Linux基础进程的主要内容,如果未能解决你的问题,请参考以下文章

Linux进程组和会话

Linux命令总结

linux基础编程—selectpollepoll

python---基础知识回顾进程和线程

Linux C与C++一线开发实践之三 Linux多进程

Linux C与C++一线开发实践之三 Linux多进程