Linux学习笔记之进程

进程

进程的定义

  进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,也是操作系统结构的基础。
  例如当QQ程序运行的时候,计算机会先从磁盘读取QQ程序到内存,然后OS管理这个程序,这就是进程。简单来说进程就是OS处理进程的数据结构加代码与数据。一般在Linux中这个数据结构就是task_struct结构体,本质就是单链表。如下代码就是一个进程结构体,里面有进程的状态,ID,分配的内存等。

struct task_struct {
    // 进程状态,例如:TASK_RUNNING, TASK_INTERRUPTIBLE 等
    volatile long state; 
    // 进程的进程号(PID)
    pid_t pid; 
    // 指向下个进程的 task_struct 指针
    struct task_struct *next; 
    // 进程的进程组号
    pid_t tgid; 
    // 进程的优先级
    int prio; 
    // 进程的虚拟内存描述符
    struct mm_struct *mm; 
    // 进程的内核栈指针
    void *stack; 
    // 进程的可执行文件信息
    struct files_struct *files; 
    // 进程的文件系统信息
    struct fs_struct *fs; 
    // 进程的信号处理相关信息
    struct signal_struct *signal; 
    // 进程的命名空间信息
    struct nsproxy *nsproxy; 
    // 进程的调度信息
    struct sched_entity se; 
    // 进程的运行时间统计
    u64 utime, stime; 
    // 进程的启动时间
    unsigned long long start_time; 
    // 进程的命令行参数
    char comm[TASK_COMM_LEN]; 
};

进程的目的与意义

  一般在电脑,手机上,我们不止要运行一个程序,会同时运行qq,杀毒软件,浏览器等。如果我们不先描述进程的属性定义一个结构体,进程之间会产生干扰,那么OS就无法较好的管理内存。计算机就会是不是蓝屏,这对于用户来说十分的不友好。

进程采用单链表的原因

  在使用QQ的时候,我们会打开他,不用的时候可以关闭它,或者让他保持后台运行,因此对于进程而言,就有大量的增删操作,如果我们采用数组的方式就会造成数据处理慢,也就是使用起来变卡了。
  其次使用数组就必须提前分配一大段连续的地址空间,但可能OS不需要如此大的空间,就会造成资源浪费,其次在数组扩容的时候,计算机可能没有足够大的连续空间,就会造成内存不够。采用单链表的方式就更加的灵活,充分利用散落空间。

  进程就是运行的程序,在Linux中被描述为task_struct结构体,用单链表进行管理。可以通过XShell来访问服务器.ps ajx命令来查看进程,如下图
在这里插入图片描述

1.进程相关的函数

1.1getpid()

	man getpid

  在Linux中可以用上述命令查询该函数。
在这里插入图片描述

  在操作系统中有多个进程,为了区别他们,就引入了类似于身份证号的概念,每个进程都有自己唯一的pid(process Identification),当程序运行起来时就是一个进程,因此可以在程序中获取当前pid然后打印出来。

 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 
  5 int main()
  6 {
  7 
  8     pid_t id=getpid();
  9 
 10     printf("我的ID是%d\n",id);                                                                                  
 11 
 12 
 13     return 0;
 14 }
~

运行程序,便可以得到如下ID。

在这里插入图片描述

1.2getppid()

	man getppid

  在Linux中可以用上述命令查询该函数。如下图
在这里插入图片描述
  在Linux中-bash就是命令行程序,我们输入的ls,mkdir命令在被bash解析后都会转化为一个进程,此时bash就是父进程,ls就是子进程,在子进程内调用getppid就可以得到父进程的pid。
在这里插入图片描述
  当我们打开多个命令行时便会有多个bash,如下图。
在这里插入图片描述
  我们可以通过如下例子证明任何进程(bash除外)是由父进程创造的,
在这里插入图片描述

ps ajx | head -1 && ps ajx | grep bash

  上述命令可以分为两个命令,用&& 连接,ps ajx | head -1 ,表示显示ps ajx结果的第一行,也就是状态栏。
在这里插入图片描述
  ps ajx | grep bash表示在进程信息中查询有关键词bash的,此时会有两个符合条件,第二个时命令行bash进程自然可以被检索到,而第一个仔细看其实是grep进程。grep是我们在命令行输入的指令,在经过bash解析后生成一个进程。此时grep的父进程ID就是32095,恰好就是bash的ID。
在这里插入图片描述

1.3 fork

  既然进程是由父进程创造的,那我们平时写的test.c文件在编译运行后也是一个进程,就可以由这个进程在创造出子进程,Linux就提供了fork函数建立子进程。
在这里插入图片描述
  在man介绍中返回值最重要,如下图
在这里插入图片描述
  成功时,在父进程中会返回子进程的进程 ID(PID),而在子进程中会返回 0。失败时,在父进程中返回 -1,不会创建子进程,并且会适当地设置 errno。

  于是我们便可以通过下属例子证明子进程是由父进程建立的。

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

int main()
{

    pid_t id=fork();
    if(id == -1)
    {
        printf("子进程创建失败\n");
    }

    if(id == 0)
    {
        //子进程
        while(1)
        {
            printf("我是子进程,PID为%d,PPID为%d\n",getpid(),getppid());
            sleep(1);
        }
    }
    else 
    {
        //父进程
        while(1)
        {
            printf("我是父进程,PID为%d,子进程ID为%d\n",getpid(),id);
            sleep(1);
        }

    }


    return 0;
}

在这里插入图片描述

1.4结束进程

  在Linux中可以使用ctrl+c结束进程,如下图。按下ctrl+c后进程就结束了
在这里插入图片描述
  也可以使用kill -9 +ID结束进程。其中-9表示结束信号,

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

  如下图使用kill -9在新开的命令行中结束父进程
在这里插入图片描述

2.进程属性

  在Linux中为了方便管理进程,就设置了多种属性,有如下状态。

* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

  Linux要管理进程就必须遵循一个原则先描述再组织,即将进程各种属性封装再结构体内部,在通过队列组织起来,这样对于进程的管理就转化为对于数据结构的管理。在Linux中通常以固定的时间片来刷新进程,即Linux为了保证每个进程公平,当一个进程运行固定的时间后就切换到下个进程,依次循环往复。对应于队列就是头删尾插。

2.1 R(运行状态)

  运行状态实际上就是进程正在内存中的运行队列中,此时进程就在CPU中不断切换运行。

  1 #include<stdio.h>
  2 
  3 int main()
  4 {
  5     while(1)
  6     {                                                                                 
  9     }
 10     return 0;
 11 }

  让上述进程进入到死循环中,就会一直运行,再查看进程就可以看到R(运行状态)。此时proc进程就一直在内存中的运行队列中。
在这里插入图片描述

2.2 S(休眠状态)

  根据之前的冯诺依曼架构可以知道,CPU只与内存进行数据交换,由于磁盘等输出设备读取速度相对于内存过慢,CPU不会与输出设备例如显示器,磁盘,进行数据交换,而是要通过内存间接交换
在这里插入图片描述
  当进程要与外部设备输出时,这个消耗的时间对于CPU来说时巨大的,为了避免资源的浪费,进程在Linux中就是一个task_struct结构体,可以放在任何task_struct队列中,于是便将进程从内存的运行队列中取出换到设备的等待队列中等待数据交换完毕。。此时进程的属性就是休眠状态。如下例子

#include<stdio.h>
  2 
  3 int main()
  4 {
  5     while(1)
  6     {
  7         printf("我是一个进程\n");
  8                                                                                                  
  9     }
 10     return 0;
 11 }

  在上述的代码中仅仅加入一条打印语句,进程就处于S休眠状态,说明此时进程被移动到显示器的等待队列中了。但这个程序是个死循环,一定会有再次加载到CPU中的时候,也就是R状态,但是由于CPU运行速度十分快,刚好查询到R状态概率十分小

在这里插入图片描述

for i in $(seq 1 1000); do ps ajx | head -1 && ps ajx | grep ‘<proc>’ | grep -v grep; done

  运行上述脚本,在尝试数分钟后终于也是找到了那一瞬间为R的状态

在这里插入图片描述

2.3 D(深度休眠状态)

  这个状态十分少见,仅在系统濒临崩溃的边缘才可以看见。假如现在进程A里存储了1000W人口信息资料,此时要保存到磁盘中,那么给他状态设置为S,此时OS(操作系统)在管理进程,内存严重的不足了,OS的使命是保护系统正常运行,他看见A进程是S状态,又占用大量的内存,就把A进程强制结束了(就像手机打开应用闪退一样)。此时如果磁盘正常存储结束也就没什么问题,但是D磁盘内存也可能不足,此时磁盘向进程A返回错误信息,发现A进程没了,直接人傻了。十分重要的数据就发生了丢失,这是决定不允许的。
  于是便引入了D状态(磁盘休眠/深度休眠)。==系统可以崩溃,但是数据不可以丢失。==二者取其轻,选择相对可以接受的选择。

2.4 T(停止状态)

  在Linux中可以使用kill向进程发送信号。如下图
在这里插入图片描述
  其中19号信息就可以暂停进程。

在这里插入图片描述

在这里插入图片描述

kill -18 16394

可以再次启动进程

2.5 t(追踪停止状态)

  在Linux中经常会使用gdb进行调试,虽然不怎么好用哈。当我们在程序中打断点,并且r运行到断点时,此时程序就是t状态。

gcc -g -o test test.c
gdb test

在这里插入图片描述

在这里插入图片描述

2.6 X(死亡状态)

  死亡状态就是进程彻底结束,资源全部释放的时候,是一瞬间的状态,不能被检测到。

2.7 Z(僵尸状态)

  僵尸状态就是进程没有完全释放的状态,但是进程不在运行了。进程可以理解为是内核数据结构(task_struct)+代码和数据,当子进程完成任务时,就会先释放代码加数据,但保留task_struct供父进程判断检测子进程是否完成任务。死亡状态也就是将最后的tast_struct也释放完毕的瞬间状态。

  ls对于命令行解释器bash来说是其的子进程,当ls进程执行完时,返回的退出状态可以用==echo ¥?==显示出来,如下图。
在这里插入图片描述
  ls执行错误时也会返回对应的错误码,然后bash根据错误码打印对应信息。
在这里插入图片描述
  如果僵尸进程不被父进程管理回收那么他将永远是僵尸进程,如果父进程不管理僵尸进程的话,由此便有可能造成内存泄漏,也可以通过下面例子认识。

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

int main()
{

    pid_t id=fork();
    if(id == -1)
    {
        printf("子进程创建失败\n");
    }

    if(id == 0)
    {
        //子进程
        while(1)
        {
            printf("我是子进程,PID为%d,PPID为%d\n",getpid(),getppid());
            sleep(1);
        }
    }
    else 
    {
        //父进程
        while(1)
        {
            printf("我是父进程,PID为%d,子进程ID为%d\n",getpid(),id);
            sleep(1);
        }

    }


    return 0;
}

  运行上述程序并且使用kill结束子进程,但此时父进程没有做任何处理,那么子进程就是僵尸状态,如果父进程一直不处理那么就会造成内存泄漏。

在这里插入图片描述
  刚才是父进程和子进程都存在的情况下,结束子进程那么子进程是僵尸进程。如果结束父进程的话那么子进程就会操作系统领养称之为孤儿进程。操作系统的pid为一。

在这里插入图片描述

3 进程优先级

3.1 进程优先级意义

   CPU的资源具有稀缺性,进程优先级是进程获得CPU资源的一种先后顺序,即竞争力,就像我们下课时去食堂排队打饭一样,先到的他的优先级就越高就越先打到饭吃饭。

3.2 修改优先级

  Linux优先级由两部分组成一部分是priority(默认优先级),一部分是nice(微调优先级),进程的真实优先级等于priority+nice。在Linux中修改进程的优先级只能修改nice不能修改默认优先级。
在这里插入图片描述

3.2.1 top修改优先级

  按照以下步骤操作修改,top -> r ->pid -> nice值
在这里插入图片描述
在这里插入图片描述
  需要注意的是普通用户禁止频繁修改优先级, 如果被系统弹出禁止,需要切换到超级用户或者用sudo执行top。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
  在这里需要注意的是nice的值的范围是从-20到19,输入超过这个范围的值会自动适配到这个范围内。并且这个priority优先级是最初的优先级加上修改后的nice,而不是上一次的priority加上nice值
在这里插入图片描述

3.2.2 命令行修改优先级

renice <nice值> -p <进程ID>

在这里插入图片描述
  也可以修改为负数。在原来八十的优先级上减十就得到了现在七十的优先级.
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/969020.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

泛型 类 接口 方法 通配符

泛型 泛型类 what: 类型参数化 why use&#xff1a; 1. 输出时候是object类型 而不是真正类型转化麻烦 import java.util.ArrayList; import java.util.List;public class ObjectExample {public static void main(String[] args) {List<Object> list new ArrayLi…

打穿内网三重奏-红日7

靶机下载地址&#xff1a; 漏洞详情 (qiyuanxuetang.net) 攻击链路&#xff1a; DMZ区IP段为192.168.11.1/24 第二层网络环境IP段为192.168.52.1/24 第三层网络环境IP段为192.168.93.1/24 这里DMZ和攻击者我用的是192.168.11.1 这个网段&#xff0c;其他不变 这里我加了两张…

windows 10安装sqlyog详细步骤

sqlyog下载链接&#xff1a; 链接: https://pan.baidu.com/s/1D_iRna8V90omfHsKHyeBtg 提取码: bqht 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 1. 下载完以后解压&#xff0c;双击SQLyog-12.0.9-0.x64 2. 如下图&#xff0c;选择Ok 3 . 如图&#xff0c;点…

OpenAI 放王炸,将发布整合多项技术的 GPT-5,并免费无限使用,该模型有哪些技术亮点

对于 ChatGPT 的免费用户&#xff0c;将可以无限制地访问 GPT-5&#xff0c;但仅限于标准的智能级别。该级别会设定滥用限制&#xff0c;以防止不当使用(意思就是你得付费嘛)。 OpenAI CEO Sam Altman 今天在 X 上透露了 GPT-4.5 和 GPT-5 的最新发展计划。 OpenAI 将发布代…

深度学习框架探秘|TensorFlow vs PyTorch:AI 框架的巅峰对决

在深度学习框架中&#xff0c;TensorFlow 和 PyTorch 无疑是两大明星框架。前面两篇文章我们分别介绍了 TensorFlow&#xff08;点击查看&#xff09; 和 PyTorch&#xff08;点击查看&#xff09;。它们引领着 AI 开发的潮流&#xff0c;吸引着无数开发者投身其中。但这两大框…

UEFI PI PEI(2. PEI Services and Table)

PEI Services 1. PEI Services Table介绍 PEI Foundation建立了一个名为PEI Services Table的系统表&#xff0c;该表对系统中的所有Pre-EFI初始化模块&#xff08;PEIMs&#xff09;可见。 PEI Foundation在系统初始化时所需要的功能、命令或其他能力&#xff0c;会被抽象然…

2025常用的SEO工具有哪些?

在互联网时代&#xff0c;如何让自己的网站或内容脱颖而出&#xff0c;成为许多企业和个人站长们最关注的问题。而在这个过程中&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;作为一种有效的提升网站曝光度和吸引流量的手段&#xff0c;已经成为了网站运营的核心之一。对…

Winform自定义控件与案例 - 一款功能丰富的自定义文本按钮(TextButton)控件

深入解析:TextButton —— 一款功能丰富的自定义文本按钮控件 在 WinForms 开发中,标准的按钮控件虽然能够满足基本需求,但在现代 UI 设计中显得过于简单。为了提升用户体验和界面美观度,我们开发了 TextButton,一个基于 WWControlBase 的自定义文本按钮控件。它不仅支持…

安卓自我学习

纯粹三分钟热度, 这里 我百度查询资料, 按步骤创建了emtry 项目, 这里选择apk 12 , java 别问我kotlin, 啥都不会, …… 至于是叫小林学习,最初是在csdn 那里看到小林博主的文章, 激起一点点热度, 想学习一下 找了一圈 我先右上角选择 trouble ,, ,,看图1-1 图1-1 点运行…

【SpringBoot3.x+】slf4j-log4j12依赖引入打印日志报错的两种解决方法

最开始引入了1.7.5版本的slf4j-log4j依赖包&#xff0c;但是控制台不报错也不显示日志 在https://mvnrepository.com/找到最新的2.0.16版本之后出现报错&#xff1a; 进入提示的slf4j网站中可以找到从2.0.0版本开始&#xff0c;slf4j-log4j已经被slf4j-reload4j取代&#xff1…

LabVIEW袜品压力测试系统

开发了一种基于LabVIEW开发的袜品压力测试系统。该系统利用LabVIEW并结合灵敏的传感器和高精度的处理模块&#xff0c;实现了对袜品压力的精确测量和分析。系统不同于传统的服装压力测试方法&#xff0c;为研究和评价袜子的舒适性提供了新的测试手段。 ​ 项目背景 该系统的…

【Unity Shader编程】之顶点着色器

来一张AI提供的资料 一&#xff0c;坐标空间转换 空间转换中&#xff0c;一般有五个空间转换&#xff0c;模型空间→世界空间→视图空间→裁剪空间→NDC空间&#xff08;其次坐标空间&#xff0c;执行其次坐标后的空间)→屏幕空间 核心原则 1&#xff0c;数据依赖原则 当逻…

咸鱼换绑手机号能换ip属地吗?深入探讨

随着移动互联网的普及&#xff0c;手机已经成为我们日常生活中不可或缺的一部分。而在各种网络应用中&#xff0c;手机号码往往扮演着重要的角色&#xff0c;它不仅是身份验证的关键&#xff0c;还关联着用户的地理位置信息。在二手交易平台如闲鱼上&#xff0c;用户的手机号和…

历史性突破!DeepSeek双模型GitHub热度超OpenAI,展现中国AI力量

在2025年2月7日&#xff0c;中国AI领域传来了一则振奋人心的消息&#xff1a;DeepSeek旗下的两大开源项目在GitHub平台上实现了历史性突破&#xff0c;其Star数成功超越了OpenAI的明星项目。这一成就不仅标志着DeepSeek在技术研发和市场影响力上的重大飞跃&#xff0c;也为中国…

【论文笔记】ZeroGS:扩展Spann3R+GS+pose估计

spann3r是利用dust3r做了增量式的点云重建&#xff0c;这里zeroGS在前者的基础上&#xff0c;进行了增量式的GS重建以及进行了pose的联合优化&#xff0c;这是一篇dust3r与GS结合的具有启发意义的工作。 abstract NeRF和3DGS是重建和渲染逼真图像的流行技术。然而&#xff0c;…

【CLIP系列】4:目标检测(ViLD、GLIP)

目录 1 ViLD2 GLIP2.1 前言2.2 损失计算2.3 模型框架 1 ViLD OPEN-VOCABULARY OBJECT DETECTION VIA VISION AND LANGUAGE KNOWLEDGE DISTILLATION 从标题就能看出来&#xff0c;作者是把CLIP模型当成一个Teacher&#xff0c;去蒸馏他自己的网络&#xff0c;从而能Zero Shot去…

基于Docker-compose的禅道部署实践:自建MySQL与Redis集成及故障排查指南

基于Docker-compose的禅道部署实践&#xff1a;自建MySQL与Redis集成及故障排查指南 禅道镜像版本&#xff1a;easysoft/zentao:21.4 Redis版本&#xff1a;redis:6.2.0 Mysql版本&#xff1a;mysql:8.0.35 文章目录 **基于Docker-compose的禅道部署实践&#xff1a;自建MySQL与…

Elasticsearch:同义词在 RAG 中重要吗?

作者&#xff1a;来自 Elastic Jeffrey Rengifo 及 Toms Mura 探索 RAG 应用程序中 Elasticsearch 同义词的功能。 同义词允许我们使用具有相同含义的不同词语在文档中搜索&#xff0c;以确保用户无论使用什么确切的词语都能找到他们所寻找的内容。你可能会认为&#xff0c;由于…

0基础学LabVIEW

对于零基础的朋友来说&#xff0c;学习LabVIEW需要一个科学的学习路径和方法。通过观看优质的B站教程打好基础&#xff0c;再结合实际项目进行实践操作&#xff0c;能够快速提升LabVIEW的应用能力。以下是从入门到进阶的学习建议。 ​ 一、利用B站入门教程打基础 筛选优质教程…

7. Docker 容器数据卷的使用(超详细的讲解说明)

7. Docker 容器数据卷的使用(超详细的讲解说明) 文章目录 7. Docker 容器数据卷的使用(超详细的讲解说明)1. Docker容器数据卷概述2. Docker 容器数据卷的使用演示&#xff1a;2.1 宿主 和 容器之间映射添加容器卷2.2 容器数据卷 读写规则映射添加说明2.3 容器数据卷的继承和共…