linux-进程(2)

news2024/11/19 16:39:06

1.通过系统调用获取进程标示符

进程id(PID)

父进程id(PPID)

每一个可执行程序运行起来之后都会成为一个进程,每个进程都有一个自己的id,以及一个父进程id,父进程就是创建自己进程的进程,每个进程都是一个执行起来的程序,所以肯定在这个程序中创建另一个程序,就是自己的子进程。

使用getpid这个函数就可以查看到自己这个进程的id,使用getppid这个函数就可以查看到父进程的id,getpid是一个系统调用函数,需要注意的是一个子进程只有对应的一个父进程,但是一个父进程可以有多个子进程。

进程每一次被启动时对应的pid都不一样,但是父进程的pid永远不会变。

#include<iostream>
#include<unistd.h>
#include<sys/types.h>
using namespace std;

int main()
{
    pid_t id=getpid();
    while(1)
    {
        cout<<id<<endl;
        sleep(1);
    }
    return 0;
}

int main()
{
    pid_t id=getpid();
    pid_t pid=getppid();
    cout<<"Im child: "<<id<<endl;
    cout<<"Im father: "<<pid<<endl;
    return 0;
}

\


2.通过系统调用创建进程-fork初识

这个是fork函数的介绍,需要包含两个头文件,fork函数的返回值是pid_t,并且fork函数有两个返回值。

我们来做一个小测试,看看返回值到底是怎么回事。

#include <unistd.h>
#include <sys/types.h>
#include <iostream>
using namespace std;

int main()
{
    cout << "before fork:Im a process, pid:" << getpid() << ", ppid:" << getppid()<<endl;
    fork();
    cout << "after fork:Im a process, pid:" << getpid() << ", ppid:" << getppid()<<endl;
    sleep(2);
    return 0;
}

可以看到fork之后的代码被执行了两次,也就是从一个进程变成了两个进程,第三个是子进程,它的ppid就是父进程的pid。

那么我们怎么知道哪个是子进程,哪个是父进程呢?可以通过fork的返回值来判断,如果fork成功则对子进程返回0,对父进程返回子进程的id。此时就可以使用if来分流,让父子进程做不一样的事情。

我们都知道进程=内核数据结构+可执行代码和数据,那么子进程的代码和数据是什么呢?它是怎么运行起来的,实际上父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)。但是进程是具有独立性的,互相之间是不影响的。


3.阻塞状态

大家还需要知道的是,一个cpu只有一个运行队列,那么有些进程在等待硬件资源的时候,就会被os从运行队列中拿出来放到对应的硬件的队列中,并且改成阻塞状态,因为cpu也属于硬件,硬件就有自己的结构体,里面就有对应的队列。

那么当我们用户从硬件中输入数据的时候,这个进程就会被从硬件的队列中拿出来链入到cpu的运行队列,并且将进程状态改为运行状态。

4.阻塞挂起状态

挂起状态通常伴随着阻塞,这个状态的前提是计算机的资源比较吃紧,这个时候os就会将这个进程的代码和数据写入到外设当中,当资源足够时再拿过来,写入的这个过程就是在腾空间。这个写入的本质就是用时间换空间,宁愿让进程慢点,也不要让os挂掉。


5.进程状态

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 */ };

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

S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。

D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。

X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态

进程大多数情况下是大量的在运行,那么os怎么管理这些进程呢?就需要先描述再组织,描述就是数据结构+可执行代码和数据,那么组织就需要使用队列来对进程进行排队,因为大部分进程并不是一直在运行,有些进程也可能在等待资源,比如等待我们从键盘输入,所以进程有许多种状态。
 

那么进程的状态决定了上面呢?决定了后序的动作,那么动作的先后就需要进行排队,每一个cpu都有一个自己的运行队列,那么只有进程被放入了这个运行队列,就都是运行状态,就算在排队也是运行状态。

5.1睡眠状态

睡眠状态也就是进程在等待事件的完成,那么为什么执行了一下的代码,在查询该进程信息的时候,会是睡眠状态呢?这个进程不是一直在运行吗?当我们去掉sleep的时候,这个进程还是s状态,其实是因为cout这个函数的本质是向显示器进行打印,显示器是在我们面前,可是这个可执行程序是在远端的云服务器上运行的,cpu比外设要快很多,所以注定了cout的大部分时间是在等待着执行。

#include<iostream>
#include<unistd.h>
#include<sys/types.h>
using namespace std;

int main()
{
    while(1)
    {
        cout<<"Im a process, pid: "<<getpid()<<endl;
        sleep(1);
    }
    return 0;
}

当我们去掉cout,死循环里面什么都不做,就能查到是运行状态。 

 进程的睡眠状态其实就是os的阻塞状态,这里的睡眠有时候也叫做可中断睡眠,因为可以用ctrl+c来终止。  

 5.2停止状态

当我们使用kill -19 这条命令就可以使一个进程停止,也就是进入停止状态。

 如果我们还想让这个进程跑起来,可以使用kill -18这个命令。

5.3僵尸状态

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程

僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

我们创建进程就是为了给我们完成某件事,那么这个进程退出时就需要给我们返回结果,一个进程在退出时可以释放掉代码和数据,因为都没有用了,但是需要先保存一下pcb,因为需要被os或者其他进程获取到该进程的退出信息,我们把一个进程已经退出但并没有被获取退出信息的状态称为僵尸状态。

下面这段代码就是前5秒父子进程同时运行。后面5秒父进程单独运行,在第5秒时子进程会被强制退出,那么就进入了僵尸状态Z。 为什么要有Z状态呢?我们创建进程就是为了将这个进程完成某个工作, 

int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        int cnt = 5;
        while (cnt)
        {
            cout << "Im child, pid: " << getpid() << ", ppid: " << getppid() << endl;
            sleep(1);
            cnt--;
        }
        exit(0);
    }
    int cnt = 10;
    while (cnt)
    {
        cnt--;
        cout << "Im father, pid: " << getpid() << ", ppid: " << getppid() << endl;
        sleep(1);
    }
    wait(NULL);
    cout<<"father wait child success....."<<endl;
    return 0;
}

  僵尸进程危害

进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!

维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说, Z状态一直不退出, PCB一直都要维护?是的!

那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!

内存泄漏?是的!

 5.4孤儿状态

父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?

父进程先退出,子进程就称之为“孤儿进程”

孤儿进程被1号init进程领养,当然要有init进程回收喽。

当父进程退出之后,子进程还一直在运行,这时子进程就会变成孤儿进程, 它的ppid也变成了1,也就是被1号进程领养了,被回收了,从s+变成了s,也就是变成了后台进程,此时只能使用kill -9这个命令来杀掉。

int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        int cnt = 100;
        while (cnt)
        {
            cout << "Im child, pid: " << getpid() << ", ppid: " << getppid() << endl;
            sleep(1);
            cnt--;
        }
        exit(0);
    }
    int cnt = 10;
    while (cnt)
    {
        cnt--;
        cout << "Im father, pid: " << getpid() << ", ppid: " << getppid() << endl;
        sleep(1);
    }
    // wait(NULL);
    // cout<<"father wait child success....."<<endl;
    return 0;
}

 


6.进程优先级 

6.1基本概念

cpu资源分配的先后顺序,就是指进程的优先权(priority)。

优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能.。

 在一台计算机中,资源绝对是占多数,硬件绝对是占少数,所以要合理的安排进程,就需要给它们设置优先级。 

6.2查看系统进程

在linux或者unix系统中,用ps –l命令则会类似输出以下几个内容:

UID : 代表执行者的身份

PID : 代表这个进程的代号

PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号

PRI :代表这个进程可被执行的优先级,其值越小越早被执行

NI :代表这个进程的nice值

6.3 PRI and NI

PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高,PRI的范围是60-99,进程的默认PRI是80

那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值

PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为: PRI(new)=PRI(old)+nice

这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值

nice其取值范围是-20至19,一共40个级别

6.4 PRI vs NI

需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。

可以理解nice值是进程优先级的修正修正数据

6.5查看进程优先级的命令

6.5.1用top命令更改已存在进程的nice:

top

进入top后按“r”–>输 入进程PID–>输入nice值

7.其他概念

竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级

独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰

并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行

并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发


今天的分享到这里就结束啦,感谢大家的阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

玩转nginx的配置文件3

1. limit_req_zone配置限流 limit_req_zone $binary_remote_addr zonemylimit:10m rate10r/s;upstream myweb {server 10.0.105.196:80 weight1 max_fails1 fail_timeout1;}server {listen 80;server_name localhost;location /login {limit_req zonemylimit;proxy_pass http:…

C++/QT + Mysql + Tcp 企业协作管理系统

目录 一、项目介绍 二、项目展示 三、源码获取 一、项目介绍 1、项目概要&#xff1a;C/S架构、数据库Mysql、C、QT&#xff1b;支持实时通信、局域网内通信&#xff0c;可多个客户端同时登录&#xff1b; 2、&#xff08;Server&#xff09;管理端&#xff1a;用户管理、…

详解js中的console对象

对于前端开发而言&#xff0c;console对象大家肯定都很熟悉&#xff0c;最常用的 console.log() 是开发调试必用的 但是对于console对象的其他方法&#xff0c;相对而言使用的就比较少了。下面详细介绍一下&#xff1a; 谷歌浏览器输出console对象&#xff1a; 值得一提的是不…

2018-2023年上市公司富时罗素ESG评分数据

2018-2023年上市公司富时罗素ESG评分数据 1、时间&#xff1a;2018-2023年 2、来源&#xff1a;整理自WIND 3、指标&#xff1a;证券代码、简称、ESG评分 4、范围&#xff1a;上市公司 5、指标解释&#xff1a; 富时罗素将公司绿色收入的界定和计算作为公司ESG 评级打分结…

Windows批处理脚本,用于管理Nginx服务器

先看截图&#xff1a; Windows批处理脚本&#xff0c;用于管理Nginx服务器。它提供了启动、重启、关闭Nginx以及刷新控制台等功能。 设置环境变量&#xff1a; set NGINX_PATHD:&#xff1a;设置Nginx所在的盘符为D盘。set NGINX_DIRD:\nginx1912\&#xff1a;设置Nginx所在…

以太网ARP协议解析

一、什么是ARP协议 ARP协议&#xff0c;全称是Address Resolution Protocol&#xff0c;即地址解析协议。 ARP协议的作用&#xff0c;就是在已知目标设备的IP地址但是不知道其MAC地址的时候&#xff0c;根据IP地址&#xff0c;获取到其MAC地址&#xff0c;以便组成完整的IP包进…

profinet协议基础

文章目录 工业以太网自动化通讯金字塔工业以太网技术比较 profinet概述profinet特性 EtherNet通信EtherCAT通信EtherCat特性EtherCat过程同步 工业以太网 工业以太网是基于IEEE 802.3 (Ethernet)的强大的区域和单元网络。 自动化通讯金字塔 各个组织与工业以太网 工业以太网…

2024.4.25

#include <iostream> #include <iomanip> using namespace std; class Person{const string name;int age;char sex; public:Person(const string name):name(name){cout << "第一个Person构造函数" << endl;}Person():name("zhangsan&…

面试经典150题——路径总和

​ 1. 题目描述 2. 题目分析与解析 2.1 思路一 注意题目的关键点&#xff1a;判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;起点是root&#xff0c;终点是叶子节点。 那么我们就可以从根节点按照层序遍历的方式&#xff0c;从根节点从根到 叶子不断对路径进行加…

javaSE(九):线程

目录 一、程序,进程,线程 1.概念 2.三者之间的关系&#xff1a; 二、创建线程 ①继承Thread类的方式 ②实现Runnable接口的方式 三、Thread类中方法 1.常用方法 2.线程优先级 四、线程状态 ①线程在它的生命周期中会处于不同的状态 ②线程的状态 五、多线程 1.概念…

君正X2100 RTOS 固件升级

使用cloner工具烧写固件需要在上电之前让boot_sel[2:0]处于boot from USB模式&#xff0c;但是电路板装在机壳内部后不方便改变boot_sel[2:0]的状态&#xff0c;如果要升级固件&#xff0c;需要通过机壳留出的USB口、网口、或者无线网络进行固件更新。 一、升级方案 1、固件分…

vivado Versal 串行 I/O 硬件调试流程、使用 Vivado Serial I/O Analyzer 来调试设计

Versal 串行 I/O 硬件调试流程 Versal ™ ACAP 无需再生成 IBERT IP &#xff0c; 因为使用系统内串行 I/O 调试所需的必要逻辑现已集成到 GTY 收发器架构内。使 用 GTY 收发器的任何设计均可用于串行 I/O 硬件调试。 Versal 串行 I/O 硬件调试流程具有 2 个不同阶…

10.JAVAEE之网络编程

1.网络编程 通过网络,让两个主机之间能够进行通信 >基于这样的通信来完成一定的功能进行网络编程的时候,需要操作系统给咱们提供一组 AP1, 通过这些 API才能完成编程&#xff08;API 可以认为是 应用层 和 传输层 之间交互的路径&#xff09;&#xff08;API:Socket API相当…

【Qt常用控件】—— QWidget 核心属性

目录 &#xff08;一&#xff09;控件概述 1.1 关于控件体系的发展 &#xff08;二&#xff09;QWidget 核心属性 2.1 核心属性概览 2.2 enabled 2.3 geometry 2.4 windowTitle 2.5 windowIcon 2.6 windowOpacity 2.7 cursor 2.8 font 2.9 toolTip 2.10 focus…

java的ArrayList LinkedList的操作

文章目录 ArrayList1. ArrayList集合的特点2. 操作 LinkedList1. LinkedList集合的特点2. 操作 参考链接 ArrayList 1. ArrayList集合的特点 2. 操作 add(Object element) 向列表的尾部添加指定的元素。size() 返回列表中的元素个数。get(int index) 返回列表中指定位置的元素…

Git ignore、exclude for TortoiseGit 小结

1.Ignore Type&#xff1a;忽略类型&#xff0c;也即忽略规则&#xff0c;如何去忽略文件? 1.1.Ignore item(s) only in containing folder(s)&#xff1a;仅忽略在包含在文件夹中项目。 仅忽略该文件夹下选定的patterns。the patterns其实就是文件类型&#xff0c;比如.txt后…

MATLAB循环语句

MATLAB 循环语句 在某些情况下&#xff0c;您需要多次执行一个代码块。通常&#xff0c;语句是按顺序执行的。首先执行函数中的第一条语句&#xff0c;然后执行第二条&#xff0c;依此类推。 编程语言提供了各种控制结构&#xff0c;允许更复杂的执行路径。 循环语句允许我们…

把 KubeBlocks 跑在 Kata 上,真的可行吗?

背景 容器的安全性一直是广受关注的话题。这个领域也产生了很多不错的开源项目。Kata就是其中之一。 Kata Containers&#xff08;简称 Kata&#xff09;是一种开源项目&#xff0c;它提供了一种安全而高性能的容器运行时环境。Kata Containers 利用虚拟化技术&#xff08;通常…

【深度学习实战(24)】如何实现“断点续训”?

一、什么是断点续训&#xff1a; 中断的地方&#xff0c;继续训练。与加载预训练权重有什么区别呢&#xff1f;区别在于优化器参数和学习率变了。 二、如何实现“断点续训” 我们需要使用checkpoint方法保存&#xff0c;模型权重&#xff0c;优化器权重&#xff0c;训练轮数…

TablePlus for Mac/Win:开启高效数据开发新纪元

在当今数字化时代&#xff0c;数据的重要性日益凸显。无论是企业还是个人&#xff0c;都需要一款强大而实用的本地原生数据开发软件来提升工作效率。而 TablePlus for Mac/Win 正是这样一款卓越的工具&#xff0c;它为用户带来了全新的体验&#xff0c;让数据开发变得更加轻松、…