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

Linux之进程概念

 9efbcbc3d25747719da38c01b3fa9b4f.gif

                                                      作者主页:     作者主页

                                                      本篇博客专栏:Linux专栏

                                                      创作时间 :2024年9月28日

9efbcbc3d25747719da38c01b3fa9b4f.gif

基本概念:

进程说白了其实就是一个程序的执行实例,正在执行的程序。

内核层面来说,就是一个担当分配资源(CPU时间,内存)的实体

写过代码的都知道,当你的代码进行编译链接之后就会形成一个可执行的程序了,这个程序本质上是一个文件,是放在磁盘上的。当我们双击这个程序让他运行起来之后,本质上是让这个程序加载到内存当中去了,因为只有加载到内存当中去CPU才能对他进行逐语句执行,而一旦将这个程序加载到内存之后,我们就不应该叫他程序了,严格意义上应该称他为进程。

描述进程-PCB

系统中可以同时存在大量的进程,当我们使用ps aux命令时便可以看见此时存在的所有进程

当我们电脑开机时,打开的第一个程序其实就是操作系统(即操作系统是第一个加载到系统中的),我们都知道操作系统是管理工作的,其中一个就是进程管理,那么我们电脑上这么多的进程,操作系统是如何进行管理的呢?

这时我想首先告诉大家一个六字真言:就是先描述,再组织,操作系统管理也是如此,操作系统作为管理者是不需要直接和被管理者进行沟通的,当一个进程出现时,操作系统会直接对其进行描述,然后对他的管理其实就是对其描述信息的管理,进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合,这个就是PCB

操作系统将每一个进程进行描述,形成一个个的进程控制块(PCB),并且通过双链表的形式将他们连接起来。

这样,操作系统只要拿到这个双链表的头指针就可以对这个双链表进行管理,这样操作系统对各个进程的管理就变成了对双链表的管理。

例如我们创建一个进程时首先就是将改进程的代码和数据加载到内存,然后操作系统对此进程进行描述形成对应的进程控制块(PCB),并将这个PCB插入到双链表中,想要退出这个进程时就直接从双链表当中删去这个节点(PCB)即可。这样一来,操作系统对于进程的管理就变成了对一个双链表的增删查改。

task_struct --PCB的一种

进程控制块(PCB)是描述进程的,再c++中我们称之为面向对象,而在c语言当中我们称之为结构体,因为Linux是用C语言写的,当然PCB也是用c语言写的了,也就是用结构体来实现的。

  • PCB实际上是对进程控制块的统称,在Linux中描述进程的结构体叫做task_struct
  • task_struct是Linux中的一种数据结构,他会被装载到RAM(内存)里并包含进程的信息

task_struct 内容分类

task_struct 就是Linux中的进程控制块,它包含着以下的一些信息。

  • 标识符:描述本进程的唯一标识符,用来区别其他标识符
  • 状态:任务状态,退出代码,推出信号等
  • 优先级:相对于其他进程的优先级
  • 程序计数器:程序中即将被执行的下一条指令的地址
  • 内存地址:包含程序代码和进程相关的指针,还有和其他进程共享的内存块中的指针
  • 上下文数据:进程执行时处理器的寄存器中的数据
  • I/O状态信息:包含显示的I/O请求等
  • 记账信息:可能包含处理器时间的总和等
  • 其他信息

查看进程

通过系统目录来查看信息:

在根目录下有一个名为proc的系统文件夹,其中包含了大量进程信息,其中一些子目录的名字为数字

这些数字其实是一某一进程的PID,对应的文件夹中记录中对应进程的各种信息,想要查看直接输入ls /proc/对应的数字 即可

通过ps命令查看:

ps与对应的指令想叠加,便可以显示对应的进程的信息 

 ps aux | head -1 && ps aux | grep proc | grep -v grep

通过系统调用获得对应的进程的PID和PPID

通过系统调用函数,getpid和getppid两个函数分别可以获得对应进程的PID和PPID

当我们执行该程序之后,这个程序会不停的执行下去

我们通过ps命令得到对应进程的PID和PPID,就可以发现和getpid与getppid得到的值是一模一样的

通过系统调用创建进程-fork初始

fork函数创建子程序

加入fork函数之后,运行结果如下:

循环打印两行数据,这两行数据分别为:第一行是该进程的PID和PPID,第二行是fork创建的子进程的PID和PPID,我们可以发现fork创建的子进程的PPID是子进程的PID,说明这两个进程的关系为父子关系。

同样,操作系统也会为这个新建的进程创建PCB。

我们知道加载到内存中的数据和代码是属于父进程的,那么子进程的数据和代码又是从哪里来的呢?

我们可以看到,fork之前的代码是父进程自己执行的,之后的代码是父子进程都执行

需要注意的是,虽然父子进程共享代码了,但是其实是各自开辟空间(采用写时拷贝);

小贴士:使用fork函数创建子进程后就有了两个进程,这两个进程的调度顺序是不确定的,取决于操作系统调度算法具体的实现。

fork返回值:

1.如果fork函数创建子进程成功,那么在父进程中返回父进程的pid,子进程的返回0

2.如果创建失败,那么父进程的返回-1.

Linux运行状态:

一个进程都创建而产生到因撤销而销毁的整个生命期间,有时占有处理器执行,有时虽然可以运行但是分不到处理器。有时虽然有空闲处理器但是由于待某个时间的发生而无法执行,这一切就说明进程和程序有区别,进程是活动的且状态变化的,所以叫做进程

这里我们具体谈一下进程中的一些状态:

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 *task_state_array[] = {"R (running)",       /*  0*/"S (sleeping)",      /*  1*/"D (disk sleep)",    /*  2*/"T (stopped)",       /*  4*/"T (tracing stop)",  /*  8*/"Z (zombie)",        /* 16*/"X (dead)"           /* 32*/
};

运行状态——R

一个程序处于运行状态,并不一定一定处于运行当中,一个进程处于R状态,表示处于运行当中或者处于运行队列(runqueue)当中,所有会存在多个进程同时处于R状态。

浅睡眠状态——S

一个进程处于浅睡眠状态,也叫可中断睡眠状态,意味着等待某件事情的完成,处于浅睡眠状态的进程随时可以被唤醒,也可以随时被杀掉

当我们在一个进程中加入sleep(100),意思就是在这里休息一百秒,此时编译运行之后就会出现浅睡眠状态。

深睡眠状态——D

一个进程处于深度睡眠状态,表示这个进程不可以被杀掉,即便是操作系统也是不可以的,只有这个进程自动唤醒才可以恢复,该进程也被称为不可中睡眠状态。

例如:某一进程对磁盘进行写入操作时,再写入期间,就会处于D状态,是无法被杀掉的,因为该进程必须磁盘回复是否写入成功,以做出相应的回应

暂停状态——T

在Linux中,我们可以通过向进程发送SIGSTOP信号使进程进入暂停状态(T),发送SIGCONT可以让处于暂停状态的进程继续运行。

僵尸状态——Z

当一个进程将要退出的时候,在系统层面,这个系统曾经申请的资源并不会被马上释放,而是暂时存储一段时间,以供操作系统或者其父进程进行读取,如果信息一直未被读取,则相关数据会一直存在,不会被释放掉的,如果一个进程等待着数据被读取,那么我们就说他正处在僵尸状态。

僵尸状态时应该存在的,因为我们调用一个程序时,调用方是应该知道这个完成情况的,所以僵尸状态必须是要存在的,以便后续的相关操作。

例如我们在编写程序时都会在最后写一个return 0,它的作用就是告诉操作系统这个程序顺利完成结束了。

在Linux中,我们可以通过echo $命令来获取最近的一次进程的退出码

死亡状态——X

死亡状态只是一个返回状态,当一个进程的信息被退出之后,该进程申请的资源会立即被释放,所以你不会在进程状态中看到死亡状态。

僵尸进程

前面我们已经说过僵尸状态的概念,相信大家也有了一个大致的了解,而处于僵尸状态的进程,就被称为僵尸进程。

例如,对于下面的代码,当程序执行五次之后,子进程便会退出,但是父进程不知道它退出了,那么此时子进程就处于僵尸状态。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{printf("I am running...\n");pid_t id = fork();if(id == 0){ //childint count = 5;while(count){printf("I am child...PID:%d, PPID:%d, count:%d\n", getpid(), getppid(), count);sleep(1);count--;}printf("child quit...\n");exit(1);}else if(id > 0){ //fatherwhile(1){printf("I am father...PID:%d, PPID:%d\n", getpid(), getppid());sleep(1);}}else{ //fork error}return 0;
} 

运行该代码之后,我们可以通过下面这个简单的脚本进行监控

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

运行之后我们发现:当子进程退出之后,子进程就会编程僵尸状态。

僵尸进程的危害:

  1. 僵尸进程的退出状态会一直维持下去,因为它需要告诉父进程执行的相应的结果信息。但是父进程一直在不停的执行,所以子进程就一直处于僵尸状态
  2. 僵尸进程的信息会一直存在与task_struct(PCB)中,所以PCB就需要一直去维护
  3. 若一个父进程创建了多个子进程,并且不对其进行回收,那么就会造成资源浪费,因为数据结构对象本身就要占据内存
  4. 僵尸进程越来越多,申请的资源无法进行回收,那么僵尸进程越多,实际可用的资源就越少,也就是说僵尸进程会造成内存泄漏

孤儿进程:

孤儿进程是指在操作系统中,其父进程已经结束(正常或异常终止),但该进程本身还在继续运行的进程。当一个进程创建子进程后,如果父进程在子进程结束之前就已经退出,那么子进程就会成为孤儿进程。例如,一个父进程启动了一个子进程,之后父进程由于某种原因(如完成了它的任务或者遇到了错误而终止)退出,此时子进程就变成了孤儿进程。

对于以下代码,父进程执行五次后退出,子进程就变成了孤儿进程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{printf("I am running...\n");pid_t id = fork();if(id == 0){ //childint count = 5;while(1){printf("I am child...PID:%d, PPID:%d\n", getpid(), getppid(), count);sleep(1);}}else if(id > 0){ //fatherint count = 5;while(count){printf("I am father...PID:%d, PPID:%d, count:%d\n", getpid(), getppid(), count);sleep(1);count--;}printf("father quit...\n");exit(0);}else{ //fork error}return 0;
} 

观察代码运行,会发现父进程退出后,子进程的PPID变成了1,这就说明他被一号进程领养了

进程优先级:


基本概念:

什么是进程优先级?优先级实际上就是进程获取某些资源的先后顺序,而进程优先级实际上就是进程获取CPU资源分配的先后顺序,就是指进程的优先权,优先权高的进程具有优先执行的权力

为什么要有进程优先级?

进程优先级存在的主要原因就是我们的资源是有限的,就像我们的电脑,一般都是单CPU的,一个CPU一次只能执行一个进程,而进程有多个,所以需要存在进程优先级,确定获取CPU资源的先后顺序。

查看系统进程

在Linux中输入ps -l可以看到以下的东西:

我列出其中重要的几个信息:

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

PRI和NI

  • PRI代表着进程的优先级,这个值越小进程的优先级越高
  • NI代表着nice值,其表示进程可被执行的优先级的修正数值
  • PRI(new)=PRI(old)+NI;
  • 若NI值为负值,那么PRI变小,优先级变高
  • 调整进程的优先级,在Linux下就是调整NI,即nice值
  • NI的范围是-20-19,也就是说进程优先级一共分为四十个级别

注意:在Linux系统中,PRI默认的值是80,也就是PRI=80+NI。

当我们创建一个进程之后,我们可以通过ps -al查看进程的优先级。

通过top命令修改进程优先级

这里的top命令其实就相当于Windows中的任务管理器,可以调整进程优先级。

使用top命令后按r,然后输入要调整的进程的PID,然后调整后的nice值即可

注意:要想将nice调整为负值,需要加上sudo提升权限

通过renice调整进程优先级

输入 renice +更改后的nice +PID即可

四个重要概念:

竞争性:由于只有一个CPU,所以资源有限,会出现资源竞争,为了高效完成任务,合理分配CPU资源,所以会出现进程优先级

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

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

并行:多个进程在多个CPU下同时进行

环境变量:

基本概念

环境变量一般是指在操作系统中指定操作系统运行环境的一些参数

常见环境变量

  • PATH:指定命令的搜索路径
  • HOME:指定用户的主工作目录
  • SHELL:当前shell,他的值一般是/bin/bash

查看当前环境变量的方法

使用echo来查看:

echo $NAME //NAME为待查看的环境的名称

测试PATH

大家有没有想过这样一个问题:为什么执行ls命令时不用带./,而在执行我们自己的可执行程序时就必须要带上?

容易理解的是,我们在执行一个程序的时候,必须要先找到他在哪里,既然不带ls就可以执行ls,说明操作系统可以找到他,而系统找不到我们的可执行程序,必须带上./来说明他在我们的当前目录下。

而系统就是通过环境变量PATH来找到ls的,查看环境变量PATH,可以看到下面内容:

可以看到很多路径,这些路径通过冒号隔开,然后执行ls命令时,系统会从左到右开始寻找ls命令

而ls命令确实存在与这些路径中的某个路径下面。

那我们可不可以让自己的可执行程序不带./就执行呢

两个方法:

  • 一个就是在系统默认的路径下创建这个程序,然后生成可执行程序或者将这个可执行程序拷贝到PATH的某一个路径下面
  • 将可执行程序所在的路径导入到PATH这个路径下面

部分环境变量说明:

set:显示本地定义的shell变量和环境变量

unset:清楚环境变量

通过代码来获取环境变量:

你知道main函数其实是由参数的嘛?

我们平常情况不会使用他,所以基本不会写出来。

在这里我们可以看到,调用main函数时向其传递了三个参数。

我们先来说说前两个参数

我们在Linux下写下这个程序并运行:

                                                                                                                                                                                 
#include <stdio.h>
int main(int argc,char *argv[])
{
for(int i=0;i<argc;i++)
{
printf("argv[%d]:%s\n",i,argv[i]);                                                                                                                                                                 }                                  return 0;                        }                                    

执行结果如下:

现在我们来说说main函数中的前两个参数,其中的第二个参数是一个字符指针数组,数组中第一个字符指针存储的是可执行程序的位置,其余字符指针存储的是所给的若干选项。最后一个指针为空,而前面那个第一个参数就代表着字符指针数组中有效元素的个数

下面我们来写一个简单的代码,这个代码运行起来之后会根据你所给的选项的不同给出不同的提示语句:

现在我们来说说main的第三个参数:

main的第三个参数实际上是接受的环境变量表

可通过他获得系统的环境变量:

通过系统调用获取环境变量:

程序地址空间:

下面我们来验证一下:

最后:

十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:

1.一个冷知识:
屏蔽力是一个人最顶级的能力,任何消耗你的人和事,多看一眼都是你的不对。

2.你不用变得很外向,内向挺好的,但需要你发言的时候,一定要勇敢。
正所谓:君子可内敛不可懦弱,面不公可起而论之。

3.成年人的世界,只筛选,不教育。

4.自律不是6点起床,7点准时学习,而是不管别人怎么说怎么看,你也会坚持去做,绝不打乱自己的节奏,是一种自我的恒心。

5.你开始炫耀自己,往往都是灾难的开始,就像老子在《道德经》里写到:光而不耀,静水流深。

最后如果觉得我写的还不错,请不要忘记点赞✌,收藏✌,加关注✌哦(。・ω・。)

愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚菜鸟逐渐成为大佬。加油,为自己点赞!

相关文章:

Linux之进程概念

作者主页&#xff1a; 作者主页 本篇博客专栏&#xff1a;Linux专栏 创作时间 &#xff1a;2024年9月28日 基本概念&#xff1a; 进程说白了其实就是一个程序的执行实例&#xff0c;正在执行的程序。 在内核层面来说&#xff0c;就是一个担当分配资源&#xff08;CPU时间…...

小程序-使用npm包

目录 Vant Weapp 安装 Vant 组件库 使用 Vant 组件 定制全局主题样式 API Promise化 1. 基于回调函数的异步 API 的缺点 2. 什么是 API Promise 化 3. 实现 API Promise 化 4.调用 Promise 化之后的异步 API 小程序对 npm 的支持与限制 目前&#xff0c;小程序中已经…...

【springboot】整合沙箱支付

目录 1. 配置沙箱应用环境2. 配置springboot项目1. 引入依赖2. 配置文件注册下载ngrok 3. 创建支付宝支付服务类4. 支付界面模板5. 控制类实现支付6. 测试 1. 配置沙箱应用环境 使用支付宝账号登录到开放平台控制台。 使用支付宝登录后&#xff0c;看到以下页面&#xff0c;下…...

技术速递|Python in Visual Studio Code 2024年9月发布

排版&#xff1a;Alan Wang 我们很高兴地宣布将于 2024 年 9 月发布适用于 Visual Studio Code 的 Python 和 Jupyter 扩展&#xff01; 此版本包括以下公告&#xff1a; Django 单元测试支持使用 Pylance 从 inlay 提示转到定义 如果您有兴趣&#xff0c;可以在我们的 Pyth…...

数据结构-3.5.队列的顺序实现

一.队列的顺序实现&#xff0c;初始化操作以及判断队列是否为空&#xff1a; 1.图解&#xff1a; 2.代码&#xff1a; #include<stdio.h> #define MaxSize 10 //定义一个队列最多存储的元素个数 ​ typedef struct {int data[MaxSize]; //用静态数组存放队列元素int f…...

preconnect 预解析

preconnect 是一种浏览器优化技术&#xff0c;用于告诉浏览器提前与指定的域名建立连接&#xff0c;包括DNS解析、TCP握手和TLS协商&#xff08;如果适用&#xff09;。这样做可以减少客户端在请求资源时所需的往返时间&#xff08;RTT&#xff09;&#xff0c;从而提高页面加载…...

Leecode热题100-283.移动零

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: […...

如何高效使用Prompt与AI大模型对话

一、如何与人工智能对话 在人工智能的世界里&#xff0c;提示词&#xff08;Prompt&#xff09;就像是一把钥匙&#xff0c;能够解锁AI智能助手的潜力&#xff0c;帮助你更高效地获取信息、解决问题。但如何正确使用这把钥匙&#xff0c;却是一门艺术。本文将带你了解提示词的…...

Java 之深入理解 String、StringBuilder、StringBuffer

前言 由于发现 String、StringBuilder、StringBuffer 面试的时候会经常问到&#xff0c;这里就顺便总结一下&#xff1a;本文重点会以这三个字符串类的性能、线程安全、存储结构这三个方面进行分析 ✨上期回顾&#xff1a;Java 哈希表 ✨目录 前言 String 介绍 String 的不可变…...

vue3项目执行pnpm update后还原package.json文件后运行报错

项目场景&#xff1a; vue官方版本已更新到vue3.5&#xff0c;项目中还在使用vue3.4&#xff0c;因此想要更新项目vue版本。 问题描述 执行了 pnpm update 命令&#xff0c;一键更新了所有包&#xff0c;更新完成后项目不能正常运行。为了还原项目代码&#xff0c;先删除 nod…...

蓝桥杯【物联网】零基础到国奖之路:十七. 扩展模块之单路ADC和NE555

蓝桥杯【物联网】零基础到国奖之路:十七. 扩展模块之单路ADC和NE555 第一节 硬件解读第二节 CubeMx配置第三节 代码1&#xff0c;脉冲部分代码2&#xff0c;ADC部分代码![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/57531a4ee76d46daa227ae0a52993191.png) 第一节 …...

SolveigMM Video Splitter方便快捷视频分割合并软件 V3.6.1309.3-供大家学习研究参考

视频分割功能(Splitter)支持各种编码格式的AVI(DivX、DV、MJPEG、XVID、MPEG-4)、WMV、ASF(DivX、MJPEG、XVID、MPEG-4、WM Video 7/9)F、MPEG(*.mpg、*.mpeg、*.mpv、*.m2v、*.vob)文件、也支持受损的WMV、ASF格式的分割。视频合并功能(Joiner)则支持AVI、WMV/ASF、WMA、MP3、…...

Unity3D 创建一个人物,实现人物的移动

1&#xff0c;创建项目 首先打开我们的Unity Hub 在我们的编译器下面新建项目&#xff0c;选择3D模板&#xff0c;更改一下我们的项目名称&#xff0c;选择一下路径&#xff0c;然后点击创建项目 等待项目创建。。。。。。 我们在项目里先创建一个plane&#xff0c;这样有点视…...

【笔记】数据结构12

文章目录 2013年408应用题41方法一方法二 看到的社区的一个知识总结&#xff0c;这里记录一下。 知识点汇总 2013年408应用题41 解决方法&#xff1a; 方法一 &#xff08;1&#xff09;算法思想 算法的策略是从前向后扫描数组元素&#xff0c;标记出一个可能成为主元素的元…...

django的URL配置

1 django如何处理一个请求 首先Django要使用根URLconf模块&#xff0c;通过setting.py配置文件的ROOT_URLCONF来设置。 加载该模块后并查找变量 urlpatterns。这是一个Python的django.conf.urls.url()实例列表。 Django按顺序运行每个URL模式&#xff0c;并在匹配所请求的…...

精华帖分享 | 因子构建思考1

本文来源于量化小论坛股票量化板块精华帖&#xff0c;作者为z-coffee。 以下为精华帖正文&#xff1a; 一段时间没写帖子&#xff0c;其实一直在研究策略&#xff0c;只是从不同的角度去思考而已。熟悉我的老板其实清楚&#xff0c;我的炉子水平一般&#xff0c;基本不太依托…...

kubernetes笔记(四)

一、Pod调度策略 1.基于节点的调度 spec->nodeName [rootmaster ~]# vim myhttp.yaml --- kind: Pod apiVersion: v1 metadata:name: myhttp spec:nodeName: node-0001 # 基于节点名称进行调度containers:- name: apacheimage: myos:httpd[rootmaster ~]# kubectl a…...

通信工程学习:什么是SNMP简单网络管理协议

SNMP&#xff1a;简单网络管理协议 SNMP&#xff08;Simple Network Management Protocol&#xff0c;简单网络管理协议&#xff09;是一种用于在计算机网络中管理网络节点&#xff08;如服务器、工作站、路由器、交换机等&#xff09;的标准协议。它属于OSI模型的应用层&#…...

ubuntu20.04系统下,c++图形库Matplot++配置

linux下安装c图形库Matplot&#xff0c;使得c可以可视化编程&#xff1b;安装Matplot之前&#xff0c;需要先安装一个gnuplot&#xff0c;因为Matplot是依赖于此库 gnuplot下载链接&#xff1a; http://www.gnuplot.info/ 一、gnuplot下载与安装(可以跳过&#xff0c;下面源码…...

[激光原理与应用-126]:南京科耐激光-激光焊接 - 焊中无损检测技术 - 智能制程监测系统IPM介绍 - 26- 频域分析法

目录 一、什么是频域分析法 1、定义 2、基本原理 3、分析步骤 4、应用领域 5、优缺点 二、频域分析法在激光焊接故障监测中的应用 2.1 概述 1、应用背景 2、频域分析法的应用 3、应用优势 4、应用实例 2.2 激光焊接故障检测中光电信号的频谱特征 1、光电信号分类…...

深入理解 Solidity 修饰符(Modifier):功能、应用与最佳实践

1. 什么是修饰符&#xff08;Modifier&#xff09;&#xff1f; 1.1 修饰符的定义 在 Solidity 中&#xff0c;修饰符&#xff08;Modifier&#xff09;是一种用于更改函数行为的关键字。它们可以用于控制函数的执行条件、添加前置检查、简化重复逻辑等。修饰符在函数执行之前…...

YOLO11项目实战1:道路缺陷检测系统设计【Python源码+数据集+运行演示】

一、项目背景 随着城市化进程的加速和交通网络的不断扩展&#xff0c;道路维护成为城市管理中的一个重要环节。道路缺陷&#xff08;如裂缝、坑洞、路面破损等&#xff09;不仅影响行车安全&#xff0c;还会增加车辆的磨损和维修成本。传统的道路缺陷检测方法主要依赖人工巡检…...

怎么屏蔽统计系统统计到的虚假ip

屏蔽统计系统中的虚假IP是保护网站分析数据准确性的重要措施。以下是一些有效的策略和步骤&#xff0c;可以帮助您过滤掉虚假IP&#xff1a; 1. 识别虚假IP的特征 了解虚假IP的常见特征可以帮助您识别和屏蔽它们&#xff1a; 短时间内高频率访问&#xff1a;虚假IP可能会在短…...

前端开发设计模式——策略模式

目录 一、策略模式的定义和特点 1.定义&#xff1a; 2.特点&#xff1a; 二、策略模式的实现方式 1.定义策略接口&#xff1a; 2.创建具体策略类&#xff1a; 3.定义上下文类&#xff1a; 三、策略模式的应用场景 1.表单验证场景&#xff1a; 2.动画效果切换场景&…...

SysML案例-潜艇

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>>...

车辆重识别(2020NIPS去噪扩散概率模型)论文阅读2024/9/27

[2] Denoising Diffusion Probabilistic Models 作者&#xff1a;Jonathan Ho Ajay Jain Pieter Abbeel 单位&#xff1a;加州大学伯克利分校 摘要&#xff1a; 我们提出了高质量的图像合成结果使用扩散概率模型&#xff0c;一类潜变量模型从非平衡热力学的考虑启发。我们的最…...

基于深度学习的任务序列中的快速适应

基于深度学习的任务序列中的快速适应是指模型在接连处理不同任务时&#xff0c;能够迅速调整和优化自身以适应新任务的能力。这种能力在动态环境和多任务学习中尤为重要&#xff0c;旨在减少训练时间和资源需求。以下是这一主题的关键要素&#xff1a; 1. 快速适应的背景 动态…...

虚拟机三种网络模式详解

在电脑里开一台虚拟机&#xff0c;是再常见不过的操作了。无论是用虚拟机玩只有旧版本系统能运行的游戏&#xff0c;还是用来学习Linux、跑跑应用程序都是很好的。而这其中&#xff0c;虚拟机网络是绝对绕不过去的。本篇文章通俗易懂的介绍了常见的虚拟网络提供的三种网络链接模…...

[leetcode]674_最长连续递增序列

给定一个未经排序的整数数组&#xff0c;找到最长且 连续递增的子序列&#xff0c;并返回该序列的长度。 连续递增的子序列 可以由两个下标 l 和 r&#xff08;l < r&#xff09;确定&#xff0c;如果对于每个 l < i < r&#xff0c;都有 nums[i] < nums[i 1] &am…...

【无人机设计与技术】四旋翼无人机,UAV仿真,轨迹跟踪PID控制

摘要 本文探讨了四旋翼无人机&#xff08;UAV&#xff09;在轨迹跟踪中的PID控制仿真方法。通过设计三轴方向的PID控制器&#xff0c;调节无人机的姿态与位置&#xff0c;使其能够准确跟踪预设轨迹。本文使用MATLAB/Simulink进行了建模与仿真&#xff0c;验证了PID控制算法在无…...

举报企业网站用个人信息备案/网络推广员上班靠谱吗

软件架构是“体现在其组件中的系统的基本组织、它们之间的关系以及与环境的关系&#xff0c;以及指导其设计和发展的原则。” 软件架构识别主要系统部分并识别这些部分的输入和输出。在对架构的理解中&#xff0c;嵌入式开发人员要不断地修改他们的代码。尽管许多嵌入式产品正在…...

顺德外贸网站建设/热门推广软件

文末有福利深度学习神经网络、机器学习、Python入门全免赠送自从AI进入公众视野后&#xff0c;人们发现它越来越“跳”了。从开始的阿尔法狗战胜人类最强棋手&#xff0c;到新版阿尔法狗“自学”棋谱吊打前辈&#xff0c;再到索菲亚机器人获取公民身份&#xff0c;最后至阿里“…...

怎样做网站上更改文字/站长工具是什么

foreach (Control c in mForm.Controls) { } 存储的顺序是依据mForm上添加控件的顺序&#xff0c; m1.Parent myPanel; m3.Parent myPanel; m4.Parent myPanel; m2.Parent myPanel; 那么存储的顺序就是1 3 4 2 如果要存储界面上多个容器&#xff0c;可以进行递归 但是如果 …...

新乡企业建网站/网络推广的工作内容

c语言常用知识点&#xff1a; 知识点1:交换两个变量值的方法 采用第三方变量(最容易想到的方法)采用加减法进行值得交换&#xff08;面试时常用**&#xff09; 代码如下&#xff1a; b a - b; a a - b; b a b;采用按位异或的位方式 代码如下&#xff1a; a a^b; b …...

烟台网站建设联系电话/app拉新接单平台

防火墙历来都是保护PC用户安全的重要组成部分&#xff0c;尤其是在互联网威胁产生初期&#xff0c;防火墙的保护甚至要大于杀毒软件。后来在威胁的不断演变过程中&#xff0c;杀毒软件和HIPS日益重要&#xff0c;防火墙的作用却在下降&#xff0c;使防火墙几乎处于尴尬的 防火墙…...

招聘网站建设与开发要求/正规seo需要多少钱

【单选题】如果要回滚一个事务,则要使用( )语句【单选题】下列描述正确的是( )【单选题】以下哪项不属于数据模型【单选题】与文件系统阶段相比,关系数据库技术的数据管理方式具有许多特点,但不包括【填空题】输入矩阵 A[3,2,5;8,-5,7;-1,4,9] ,使用全下标方式用 A(2,2) 取出元…...