当前位置: 首页 > news >正文

初识Liunx下的进程状态和环境变量以及进程优先级

文章目录

  • 前言
  • 1.进程状态
    • 1.阻塞与挂起
  • 2.Linux下的进程状态
    • 1.概念知识
    • 2.R状态
    • 2.休眠状态(S/D)
    • 3.T状态
    • 4.Z状态(僵尸进程)和X状态
    • 5.孤儿进程
  • 3.环境变量
    • 1.概念
    • 2.获取环境变量
      • 1.环境变量表
      • 2.函数获取环境变量
    • 3.关于环境变量的理解和main函数中的两个参数
      • 1.环境变量的理解
      • 2.关于main函数两个参数
  • 4.进程优先级
    • 1.概念
    • 2.指令查看进程优先级以及更改进程优先级
  • 5.补充知识

前言

之前对进程进行了初步的介绍,谈及了进程的创建。本文将围绕进程状态和环境变量进行讲解,更深入一点了解进程。


1.进程状态

1.阻塞与挂起

阻塞和挂起是操作系统中一组常见的概念。先说阻塞,进程因为等待某种就绪条件而不推进的姿状态称为阻塞。这样说概念可能显得干巴巴的,我们平时有没有遇到过这样这一种情况:当我们用电脑打开很软件是不是有事时候会卡顿呢?这种卡顿就是进程被阻塞了不能正常工作。为什么会阻塞呢?我们知道当打开很多软件的时候,就相当于在内存中有很多进程,进程需要被cpu调度处理进程才能真正运转起来。这个时候cpu就可能忙不过来了,没有被cpu处理的进程就需要等待cpu忙完有空闲的时候来处理它。也就是说进程通过等待的方式,等需要的资源被被其他进程用完后,在被自己使用。从而推出:进程等待某种资源就绪的过程就被称为阻塞。

操作系统管理着软硬件资源,进程也是被操作系统管理着的。那么操作系统怎么知道每个进程需不需被阻塞等待资源呢?还是之前谈到的管理:先描述,再组织。

各种外设也是被操作系统管理的,为了便于管理可将这些设备抽象成一个一个的Dev结构体。当某个进程需要某种外设资源的时候就把该进程pcb与所需的对应资源的结构体连接起来。我们知道内存中可能很多进程,很多进程看需要着相同的资源。比如100个进程需要网络资源,我们可将网卡设备的结构体中加入一个 struct taks * Oueue 指针成员变量,将这些需要网络资源的进程pcb依次连接起来形成一个等待队列,便于操作系统进行管理。

在这里插入图片描述

这些被阻塞的进程相当于在等待队列进行排队,这就是进程被阻塞后所干的事情。


什么是挂起呢?举个例子:内存中有个进程是进行下载任务的,这个进程被cpu调度处理了,但是下载到一半突然没网了,这个时候该进程只能去网卡的等待队列中进行排队等待网络资源。我们知道进程是由两部分组成:pcb+代码和数据 ,当该进程在等待的时候,这个代码和数据其实没啥用,一直在内存中还占据空间,如果这个时候内存资源不足,操作系统就会将该进程的数据和代码和磁盘进行交换释放,数据和代码移动到外设上。这种进程状态就是挂起.也就是说进程pcb还处在等待队列中,但是进程对应的代码和数据在内存外就是挂起。挂起是一种特殊的阻塞。


2.Linux下的进程状态

1.概念知识

在这里插入图片描述

一般在学校上操作系统这门课的时候都看见过这张图或者和这张图类似的图。课本上的操作系统理论放在任何一个具体的操作系统中都是对的,包括上面的图,但是这是抽象的概念。好像什么都说了,又好像什么都没说。我们要学习一款具体的操作系统来认识操作系统。我将Linux为准介绍进程状态。

在这里插入图片描述

我们知道进程pcb里面有进程所有属性,那么进程状态也肯定里面。pcb是一个struct_task结构体,这个结构体中有一个status字段表示进程状态,进程所有状态表示就在上图中的字符数组中。下面我就来学习几种比较重要的进程状态。


2.R状态

R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里.进程状态,一般也看进程在哪里排队等待资源。

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

我写下了如图所示的代码编译运行起来了,通过查询我们看到该进程的状态是S+并不是R状态,S是休眠状态,关于这个+和S状态等下会介绍。我们现在可以判断出该进程一定不是R状态,为啥会产生这样的现象呢?

我们知道上面的代码是向显示屏打印数据的,也就是说该进程需要像显示屏这样的外设资源的。cpu的执行速度是远远大于外设的,假如该进程被cpu调度,这个时候外设有一定的响应时间,操作系统不允许该进程在持有cpu的时候,而等待外设。这个时候就会将该进程添加到等待队列中。那我们可能会有个疑问,我们确确实实看到运行结果了啊,为啥还是s+呢?我们看到这段代码很短基本上很快就执行了。可能1秒的时间内,有 99.9%在进行等待,剩下的0.01%的时间被执行了。这种微小的时间的变化人是察觉不到的,同时你可能输上上万次指令才可能刚好捕捉到这个运行态。

我们在看这样的代码

在这里插入图片描述
查看进程状态

在这里插入图片描述

这次我们发现该进程是R状态了 ,因为代码执行过程不需要其他外设资源,只要该进程被cpu调度就能运行。


2.休眠状态(S/D)

S是S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。 休眠状态本质是一种阻塞状态,进行因为等待某种资源而进行休眠等待

关于这个D状态我来画图讲故事来说明一下

在这里插入图片描述

但是一般来说只要出现一个D状态的进程就说明机器快宕机了。因为出现D状态主要是因为像磁盘这样的外设来不及进行数据的写入,IO请求过多,磁盘压力过大。这个时候内存也好不到哪去。

3.T状态

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

我们来执行一下面的代码
在这里插入图片描述
在这里插入图片描述

补充知识

kill指令先前的博客用过一次,这个kill指令可以给进程发送不同的信号达到不一样的效果。kill -l 可以查看kill指令相关选项。

kill - 19 进程pid #发送停止信号

通过指令我们发现这个进程经过kill -19后状态就是T了。右边也可以看到程序确实是停止了。 我们通过18号信号指令来让程序继续运行。

在这里插入图片描述

确实是继续运行了,但是我们发现S+的+号消失了,我们试着来终止一下这个程序。

在这里插入图片描述

我们发现按下ctrl +c终止不了,为啥呢?当没有+号表示在后台运行,这个时候想要终止程序可以使用kill -9 指令来杀死进程。

在这里插入图片描述

关于这个进程在后台运行就像:我们手机上一次打开很多app 哪怕我从某个app界面退出了 其实它还在后台挂着的。除非我手动的将它的后台给关掉,它才算真正意义上的退出。

T状态一般是由用户自己对进程设定的,当然某些进程如果进行非法权限访问,操作系统不想或者不能杀死该进程就会让该进程进入T状态。T状态和S状态是有区别的,S本质就是一种阻塞状态。我们在调试代码的时候让程序在断点处停下来本质就是让进程暂停,也就是让进程进入T状态。

补充一点
在这里插入图片描述

当我用gdb进行调试的时候在第4行处打了一个断点,按下r运行至断点处的时候,查询到该进程的状态由S变为了t,这个t是追踪式断点,也是暂停状态的一种,当我们打断点进行调试的时候gdb就会像该进程发送暂停信号。


4.Z状态(僵尸进程)和X状态

X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。它一个瞬时状态,很难捕捉到它。

Z:僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后续会说明)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程,僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程就会进入Z状态。

对僵尸状态的理解

谈及僵尸状态之前,我们先思考一个问题,为啥要创建进程呢?我们创建进程就是让进程帮我们来办事的,既然进程是办事的,那我们肯定是关心事情处理的结果的,这件事办没办成?于是就有了进程退出码的概念,进程退出码就是进程在退出消失之前告诉我们事情办没办好,这样的好处是,无须看到程序结果,程序自己就可以判断最后的结果正确与否。

代码示例
在这里插入图片描述
在这里插入图片描述

通过echo $?可以查询到进程退出码。

有了进程退出码的概念后,我们再来谈谈僵尸进程。当某个进程被父进程创建后,在进程退出消失的之前需要告诉父进程事情办得怎么样了。这个时候该进程没有立即死亡,而是维持着一种特殊的状态等待父进程(或者OS)读取最后执行的结果正确与否。这种状态就是僵尸进程。

我们来看个代码示例

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

从图中我们可以看出当子进程被杀死后,不是X状态,而是僵尸状态。如果父进程一直不读取状态码结果,子进程就会一直维持着僵尸状态。

僵尸状态的危害

维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护!那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费.因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象)是要在内存的某个位置进行开辟空间的!这样就会出现内存泄漏。

5.孤儿进程

Liun下进程一般是以父子的形式出现的,我们知道子进程退出前会返回给父进程执行结果,父进程接收后子进程才会被回收。那如果父进程先退出会发生什么呢?我们看看如下代码。

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

从上图中我们可以看到父进程退出后,子进程的ppid发发生了改变。也就是说子进程找了新爸爸,被1号进程给领养了。在被领养前,子进程就没有了爸爸,这样的进程就被称为孤儿进程。当进程退出后一般由该进程的父进程读取退出码并且回收该进程。一旦子进程没有爸爸就必须找个新爸爸,这样才能有人给子进程收尸。这个1号进程叫nit进程。我们不禁有个疑问:为啥没有看见父进程的Z状态呢?根据前面的知识,既然没有看到父进程的Z状态,那么肯定父进程被它的父进程读取退出码后回收了。

补充小知识
在这里插入图片描述

除了kill -9 进程pid能杀掉进程外,killall 进程对应的程序文件名 也可以杀掉进程

在这里插入图片描述

这个Makefile文件中的$@ 是指目标文件 $^是文件依赖列表,不管:后面的文件有多个文件依赖,$^表示所有的问文件依赖


3.环境变量

1.概念

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。

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

我们知道在linux下运行自己编译好的可执行程序需要加./也就是在当前路径找到这个程序。但是为啥我们使用Liunx中的系统指令的时候就不用呢,比如ls.它们本质也是可执行程序啊和我们自己写的程序差不多,无非就是前者被加入到了系统库中。其实这因为环境变量提前将这些指令的路径保存好了,在使用的时候,系统通过环境变量来匹配程序路径。

环境变量既然是个变量里面肯定是被写入东西了的,我们可以通过 echo $环境变量名来查看该环境变量里的内容

在这里插入图片描述
在这里插入图片描述
USER环境变量保存着当前用户信息

在这里插入图片描述

不同的环境变量有不同的功能,输入env可以查看当前系统下的所有环境变量。

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

我们知道通过history指令可以查看历史指令,这个HISTSIZE环境变量表示最多可以记录的历史命令条数,这里最大记录容量是3000条指令。这个PWD环境变量记录我们当前所处的路径,我们的pwd指令就是根据这个实现的。

我们可以将自己写的程序路径添加到环境变量中像系统指令一样操作

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

export PATH=$PATH:路径

在PATH环境变量中添加路径。当我们没有向PATH添加路径,也可以将程序文件添加到PATH的路径中也是一样的效果,这个就相当于在Liunx中安装软件,将指定程序和相关配置文件移动到特定的路径中,卸载程序不就是在将程序相关的文件从特定路径下移除。

2.获取环境变量

1.环境变量表

在谈及获取环境变之前,我们思考一个问题C语言中的main函数最多有几个参数呢?答案是3个,这些参数都和环境变量有关。

main(int argc,char *argv[],char* envp[])

这里面的第3个参数表示的是环境变量表。我们学过C语言的都知道envp是指针数组每个元素都是一个指针(地址)。环境变量都是都是由字符构成的字符串,将这些环境变量以表结构组织起来就形成了环境变量表。envp接收的就是这个表的地址。

在这里插入图片描述

代码示例
在这里插入图片描述
在这里插入图片描述

确实将所有的环境变量打印出来了,但是我们平时写main函数的时候没有写参数啊,其实这些都是编译器在背后偷偷做的。当我们不使用这个参数的时候也能直接访问这个环境变量表,系统提供了一个全局变量environ指向的就是环境变量表的地址。我们可以通过 man environ查询这个变量

在这里插入图片描述

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

从图中可以看出,两种方式效果是一样的。从中我们也可以知道进程内部本身具体环境变量表,这个表是别人传过来的,虽然暂时不知道这个表是由谁传过来的,但是我们可以通过遍历这张表来访问环境变量,但是这样的访问方式不太好,主流的方式是通过函数来访问。

2.函数获取环境变量

我们可以像获取进程pid一样通过系统提供的函数来获取指定的环境变量。这个函数就是getenv,我们可以通过man函数查询这个函数。

在这里插入图片描述

代码示例
在这里插入图片描述
在这里插入图片描述

通过先前的铺垫我们已经知道这个环境变量本质是字符串,虽然我们不知道这个getevn函数是如何实现的,但是可以大致猜到getenv应该就是通过传入的参数去环境变量表中查找匹配的字符串,如果没找到就返回null。那么获取环境变量有什么用呢?我们可以简单写一个自己的pwd。

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

这里确实实现了和pwd一样的功能,我们很多指令都是直接或者间接通过环境变量来实现的。再来看一份代码。

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

从图中可以看出哪怕是root也不能访问。我们可以根据环境变量写出于系统强相关的代码。

3.关于环境变量的理解和main函数中的两个参数

1.环境变量的理解

环境变量本质是一张内存级别的表,在用户登录系统的时候会给特定的用户形成属于自己的环境变量表。环境变量变量中的每个变量都有特定的作用,比如:有的是查找路径的,有的是身份认证等等。那么环境变量是从哪里来的呢?其实,是从系统相关的配置文件中读取的。

在这里插入图片描述

我们来一一验证图中的说法

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

从图中可以看出,确实是获取到myval,打印出了100.myval=100这个整体作为字符串被添加到环境变量表中,在获取的时候之会读到myval=后面的100.


在这里插入图片描述

在这里插入图片描述

这里就看到hell没有被getenv获取,这个hell就是个shell本地变量。可能有人会有疑问,echo也是在命令行上输入的指令应该是shell创建的子进程才对,作为子进程怎么可能会读到hell呢?其实这种指令叫内建指令,这里先不做过多赘述。

2.关于main函数两个参数

之前提到过main函数有3个参数,最后一个参数是接收环境变量表。那么前2个参数是干啥的呢?其实这两个参数是传递命令行参数的。我们来看这样的一段代码。

在这里插入图片描述

在这里插入图片描述

从上面的图我们可以看出命令行输入的可执行程序和命令行参数选项都会被转化成一个表,由shell将这个表传递给子进程,实现了同一个程序可以有不同的执行效果。基于此我们自己可以写个小代码。

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

我们之前学习C语言的时候main函数没有带上参数主要是因为没有使用场景,在Liunx下主要使用的命令行,通过选项参数让同一个程序实现不同的效果。


4.进程优先级

1.概念

优先级与权限的区别,前者是已经被允许,但是谁先谁后;后者是是否被允许,能不能的问题。为啥会出现优先级呢?是资源太少了,不够完全平分。进程之所以会有优先级主要是因为cpu资源有限,就会出现多进程竞争cpu资源,就会产生优先级的问题。

2.指令查看进程优先级以及更改进程优先级

输入指令ps -al 查看进程优先级

在这里插入图片描述

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

PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小 进程的优先级别越高.那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值 PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice.这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值nice其取值范围是-20至19,一共40个级别.但是并不是说可以随意设置优先级,调度器是会加以限制的。需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。可以理解nice值是进程优先级的修正修正数据。同时这个PR(old)是80,并不是那之前的PRI.

修改进程优先级进入top后按“r”–>输入进程PID–>输入nice值
在这里插入图片描述

这个改变进程优先级一般用不到,基本上都是使用的默认进程优先级。


5.补充知识

竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。简单来说并发就是你和同学去网吧打游戏,但是只有一台机器,于是你俩隔1个小时,换着来玩。在两个小时这个时间段你俩看起来好像同时拥有电脑的,cpu并发处理进程也是这样的,只不过这个时间间隔特别小,用户察觉不到。并行就是网吧里有两台电脑,一人可以拥有一台电脑打游戏。

以上内容如有问题,欢迎指正!谢谢!

相关文章:

初识Liunx下的进程状态和环境变量以及进程优先级

文章目录前言1.进程状态1.阻塞与挂起2.Linux下的进程状态1.概念知识2.R状态2.休眠状态(S/D)3.T状态4.Z状态(僵尸进程)和X状态5.孤儿进程3.环境变量1.概念2.获取环境变量1.环境变量表2.函数获取环境变量3.关于环境变量的理解和main函数中的两个参数1.环境变量的理解2…...

JavaEE——何为线程及创建线程

文章目录一、认识线程1. 线程的概念2. 出现多线程的原因3. 进程与线程4. 对多线程的详细解释二、初次实现多线程代码1. 初步了解2. 使用 Java 中的工具查看当前的所有线程3. Java 中创建线程的多种方式一、认识线程 1. 线程的概念 所谓线程,就是指在一个 ‘执行流…...

linux配置核查MySQL 配置规范 (Linux)_S3A3G3

linux的配置核查问题: 解决: 1.检查是否禁止mysql对本地文件存取 方法一:在my.cnf的mysql字段下加local-infile0 方法二:启动mysql时加参数local-infile0 /etc/init.d/mysql start --local-infile0 假如需要获取本地文件&#xf…...

Protobuf简介

Protobuf简介 1. Protocol Buffers1.1. 什么是Protocol Buffers?1.2. 选择你最喜欢的语言1.3. 如何开始2. Protocol Buffer Basics: C++2.1. 问题领域2.2. 在哪里找到示例代码2.3. 定义协议格式(Defining Your Protocol Format)1. Protocol Buffers Protocol Buffers(协议缓冲…...

【Kubernetes】第十七篇 - ECS 服务停机和环境修复

一,前言 上一篇,介绍了 Secret 镜像的使用; 三台服务每天大概 15 块钱的支出,用一个月也是不少钱; 闲时可以停掉,这样每天只有 4 块钱支出,剩下一大笔; ECS 服务停机后公网 IP 会…...

Vue2的生命周期(详解)

Vue的生命周期一、生命周期的概念二、钩子函数三、Vue2的生命周期3.1 初始化阶段3.2 挂载阶段3.3 更新阶段3.4 销毁阶段一、生命周期的概念 Vue实例的生命周期: 从创建到销毁的整个过程 二、钩子函数 Vue框架内置函数,随着组件的生命周期阶段,自动执行 作用:特定的时间点,执行特…...

Potions (Hard Version) and (Easy Version)(背包DP + 反悔贪心)

[TOC](Potions (Hard Version) and (Easy Version)) 一、Potions(Easy Version) 1、问题 2、分析(背包DP 贪心) 简而言之就是我们需要从左到右开始选数字,选的过程中我们需要保证我们选的数字的和始终是大于等于0的,在满足这个…...

剑指 Offer II 017. 含有所有字符的最短字符串

题目链接 剑指 Offer II 017. 含有所有字符的最短字符串 hard 题目描述 给定两个字符串 s和 t。返回 s中包含 t的所有字符的最短子字符串。如果 s中不存在符合条件的子字符串,则返回空字符串 ""。 如果 s中存在多个符合条件的子字符串,返回任…...

Modbus协议初探(C#实现)

由于作者水平有限,如有写得不对得地方请指正 趁着今天休息,就折腾一下Modbus协议,之前零零散散的看过几篇博客,听说搞上位机开发的要会这个协议,虽然我不是搞上位机开发的,但个人对这个比较感兴趣。按照我个…...

【华为OD机试2023】静态扫描 C++ Java Python

【华为OD机试2023】静态扫描 C++ Java Python 前言 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过率。 Tips1:机试为ACM 模式 你的代码需要处理输入输出,input/cin接收输入、…...

函数栈帧的创建和销毁(详解)

函数栈帧的创建和销毁🦖函数栈帧是什么?🦖函数栈帧的创建和销毁解析🐋栈是什么?🐋认识相关寄存器和汇编指令🐋解析函数栈帧的创建和销毁🐳预备知识🐳函数的调用堆栈&…...

【100个 Unity实用技能】 | 脚本无需挂载到游戏对象上也可执行的方法

Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。Unity 平台提供一整套完善的软件解决方案&#xff…...

条件期望5

条件期望例题 随机图 从节点1开始, N为一个随机变量, 表示整个过程第一次出现"贪吃蛇"情形时, 所进行的步数.即Nk⇒Xk(1)∈{1,X(1),X2(1),...Xk−1(1)}其中1,X(1),X2(1),...Xk−1(1)各不相同N k \Rightarrow X^k(1) \in \{1,X(1), X^2(1),...X^{k-1}(1)\} \\ 其中1…...

RecyclerView ViewType二级

实现效果描述: 1、点击recyclerview中item,列表下方出现其他样式的item,作为子item,如下所示 所需要的java文件和xml文件有: 1、创建FoldAdapteradapter, 在FoldAdapter中,定义两种不同的类型&#xff…...

将对象或数组存在 dom元素的属性上,最后取不到完整数据,只取到 [{

目录 一、问题 二、问题及解决方法 三、总结 一、问题 1.我需要在dom元素里面添加了一个属性test存一个对象数组temp,以便我下一次找到这个dom元素时可以直接拿到属性里面的数据来渲染页面。 2.dom 属性上存 对象和数组,必须先JSON.stringify(arr),转…...

Flask源码篇:Flask路由规则与请求匹配过程(超详细,易懂)

目录1 启动时路由相关操作(1)分析app.route()(2)分析add_url_rule()(3)分析Rule类(4)分析Map类(5)分析MapAdapter类(6)分析 url_rule_…...

Jmeter接口测试教程之【参数化技巧总结】,总有一个是你不知道的

目录:导读 一、随机值 二、随机字符串 三、时间戳 四、唯一字符串UUID 说起接口测试,相信大家在工作中用的最多的还是Jmeter。 大家看这个目录就知道jmeter的应用有多广泛了:https://www.bilibili.com/video/BV1e44y1X78S/? JMeter是一个…...

缓存与数据库的双写一致性

背景 在高并发的业务场景下,系统的性能瓶颈往往是出现在数据库上,用户并发访问过大,压力都打到数据库上。所以一般都会用redis做缓存层,起到一个缓冲作用,让请求先访问到缓存层,而不是直接去访问数据库&am…...

力扣-213打家劫舍II(dp)

力扣-213打家劫舍II 1、题目 213. 打家劫舍 II 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通…...

关于【网格结构】岛屿类问题的通用解法DFS(深度遍历)遍历框架+回溯+剪枝总结

最近在刷力扣时遇见的问题,自己总结加上看了力扣大佬的知识总结写下本篇文章,我们所熟悉的 DFS(深度优先搜索)问题通常是在树或者图结构上进行的。而我们今天要讨论的 DFS 问题,是在一种「网格」结构中进行的。岛屿问题…...

测试markdown--肇兴

day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...