【Linux】进程优先级 + 环境变量

news2024/12/28 21:21:21

文章目录

  • 📖 前言
  • 1. 进程优先级
    • 1.1 什么是优先级:
    • 1.2 如何修改优先级:
  • 2. 进程的其他概念
    • 2.1 竞争性与独立性:
    • 2.2 并行与并发:
    • 2.3 进程间优先级的体现:
    • 2.4 O(1) 调度算法:
    • 2.4 进程上下文:
  • 3. 环境变量
    • 3.1 环境变量的概念:
    • 3.2 查看环境变量:
    • 3.3 修改环境变量:
    • 3.4 和环境变量相关的命令:
    • 3.5 环境变量的获取:
      • 3.5 - 1 main函数可以带参数吗?可以带多少?
      • 3.5 - 2 传递参数的意义是什么
    • 3.6 进程获取环境变量的方法:
      • 方法一:main函数的第三个参数
      • 方法二:通过C语言全局变量
      • 方法三:用接口getenv()
    • 3.7 我为什么要获取环境变量:

📖 前言

在学完进程状态之后,本章我们将来学习一下环境变量,还有进程优先级等🙋🙋🙋……

本文实验系统:CentOS 7.6~


1. 进程优先级

1.1 什么是优先级:

  • 优先级是权限吗?

在之前我们讲解过什么是权限:👉 传送门

我们这里讲的优先级并不是权限,那么优先级到底是什么呢?

  • 如果我们说权限是能不能得问题的话
  • 那么优先级就是 — 能!但只不过是先还是后的问题
  • 优先级是进程获取资源的先后顺序
  • 为什么会存在优先级?
  • 排队的本质叫做确认优先级
  • 那么排队的最根本原因是 — 资源不够!

系统里面永远都是,进程占大多数,而资源是少数!所以,进程竞争资源是常态!一定需要确认先后!

Linux下的优先级的相关概念和操作(怎么办):

在这里插入图片描述

  • Linux优先级的构成:
  • priority + nice

我们可以根据自己的需求将进程的优先级进行修改:

  • 要更改进程优先级,需要更改不是pri,而是NI
  • nice:进程优先级的修正数据!

数字越小,代表优先级越高,数字越大,代表优先级越低。

1.2 如何修改优先级:

我们可以通过代码的方式来对优先级进行修改,但是我们只讲通过修改nice的方式来对进程优先级进行修改。

注意:

  • 虽然我们可以对Linux进程的优先级进行修改
  • 但是Linux不允许进程无节制的设置优先级

不建议随便改Liunx系统中的优先级,因为我们并不懂调度器的调度算法,随便的更改优先级就是变相的插队,可能让我们自己写的进程优先得到了某种资源,但是可能会打破调度系统的平衡。

每次设置优先级,这个old优先级都会被恢复成为80。

  • 修改方式:
  • top + r:改优先级。

在这里插入图片描述
一个进程的优先级不能被轻易修改,会打破调度器平衡,如果非得设置就必须具备超级用户的权限。

在这里插入图片描述
nice值的修改并不是无节制的,是有一定取值范围的:

  • nice [-20, 19]
  • prio [60,99]

如果nice修改的值超出了指定的修改范围,那么就会取其上、下限。


2. 进程的其他概念

2.1 竞争性与独立性:

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

进程在使用资源的时候是不允许别的进程来使用的。竞争方式一:排队。

当一个进程在使用资源的时候,是不允许别的进程也来使用该资源的基本上所有的外设和CPU都是这样子的。

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

进程运行具有独立性,不会因为一个进程挂掉或者异常,而导致其他进程出现问题!

使用STL将对象放到各种容器中,就像在Linux系统当中将PCB放来放去是一个道理。

2.2 并行与并发:

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

我的电脑是单CPU的,但是我的电脑中有各种进程都可以在跑,这是什么原因?

此时我们不得不清楚一个概念:

多个进程都在你的系统中运行 != 多个进程都在你的系统中同时运行

  • 不要以为进程一旦占有CPU, 就会一直执行到结束,才会释放CPU资源!
  • 我们遇到的大部分操作系统都是分时的!
    在这里插入图片描述
    操作系统会给每一个进程,在一次调度周期中,赋予一个时间片的概念!
  • 在一个时间段内,多个进程都会通过切换交叉的方式,让多个进程代码,在一段时间内都得到推进
  • 例如一个进程只能在CPU上执行10ms就要从CPU上扒下来,让其他的进程来执行
  • 这种现象,我们叫做并发!

这就是跑死循环不卡死的原因,可能会卡一点,因为存在进程的切换。

操作系统中的一个软件叫调度器帮我们做的将进程放在CPU再扒下来,赋予执行的时长,为什么是这么长时间等等…

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

在这里插入图片描述
如果存在多个CPU的情况,在任何一个时刻,都有可能有两个进程在同时被运行(就是在CPU上运行)

2.3 进程间优先级的体现:

操作系统,就是简单的根据队列来进行先后调度的吗??有没有可能突然来了一个优先级更高的进程??

当代计算机都具有的一种机制:抢占式内核!

正在运行的低优先级进程,但如果来个优先级更高的进程,我们的调度器会直接把进程从CPU上剥离,放上优先级更高的进程,进程抢占。

进程抢占:

有可能进程正在跑,突然来了个优先级更高的进程,操作系统直接就把这个进程扒下来了,让优先级更高的进程来跑。

2.4 O(1) 调度算法:

这里我们就简单介绍一下:

  • 允许不同优先级的进程存在
  • 相同优先级的进程,是可能存在多个的!

而我们之前学习过数据结构,我们知道队列是先进先出的,是不允许随意插入的,那么优先级如何体现出来呢?

操作系统采用的是哈希的数据结构,哈希复习:传送门
在这里插入图片描述
根据不同的优先级,将特定的进程放入不同的队列中!

同时操作系统还做了另外的结构优化,因为存在大量不同优先级的进程,如果遍历哈希表的话就是线性探测,这里则是运用位图来判断所需进程在不在,位图复习:传送门

在这里插入图片描述
操作系统会把活跃的进程放在一起,旧的进程放在一起,最后再交换指向两个哈希表的指针,就将两个哈希表交换了。

  • swap(active, old) ;

2.4 进程上下文:

CPU一定具有把数据暂时保存起来的能力。
CPU内的寄存器更多是用来保存一些临时数据。
CPU内的寄存器是:可以临时的存储数据,非常少,但是非常重要。

在这里插入图片描述

int func()
{
	int a = 10 + 20;

	return a;
}

int main()
{
	int ret = func();

	return 0;
}

把a的值放到了寄存器eax里面,用寄存器的方式来充当返回值,把寄存器里面的值mv到ret变量里,也就是把数据从CPU放到了内存里面。

  • 当进程再被执行的过程中,一定会存在大量的临时数据,会暂存在CPU内的寄存器中!

我们把进程在运行中产生的各种寄存器数据,我们叫做进程的硬件上下文数据。

  • 当进程被剥离:需要保存上下文数据
  • 当进程恢复的时候:需要将曾经保存的上下文数据恢复到寄存器中

上下文在哪里保存呢?—— task struct

3. 环境变量

3.1 环境变量的概念:

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。

环境变量的用途:

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

在这里插入图片描述

我们之前学习的各种指令,工具,和可执行文件:

  • 都是可执行程序,我们可以将自己写的可执行程序叫指令,系统的指令叫命令程序二进制文件
  • 其实大家都可以既叫做指令,又叫做工具, 又叫做可执行程序,都可以
  • 其实是一码事…

3.2 查看环境变量:

Linux查看环境变量的方法:

在这里插入图片描述

  • 而我们自己写的可执行程序为什么要带上路径才能执行,而系统中的命令则是不需要带路径??
  • 系统中是存在相关的环境变量,保存了程序的搜索路径的!
  • 系统中搜索可执行程序的环境变量叫做PATH!

在这里插入图片描述
解释:

环境变量PATH里面有多种变量,中间用冒号:分割开,其中我们在执行某个程序时:例如在执行Is时, 当识别到有Is输入时, 会在上面的路径中一个一个的搜索,只要在特定路径下找到了Is,就会执行特定路径下的Is,执行完就停止搜索不再往后走了,换言之PATH就提供了可执行程序搜索的路径。Is或者是很多指令在PATH里面是可以被找到的。

那我们自己写的程序,生成的可执行程序之后,我们也想不通过带路径的方式像指令一样执行它,我们有两种方式:

3.3 修改环境变量:

直接mytest当做指令用,直接将可执行程序执行起来,不带路径:

方法一:直接将可执行程序拷贝到系统当中

一开始不做任何处理:
在这里插入图片描述
在这里插入图片描述
不建议自己安装,更不建议将自己的指令拷贝到Linux系统的目录下,因为会污染Linux系统的命令池。
在这里插入图片描述
第二种:将mytest的所处路径也添加到环境变量里

命令行变量分两种:

  1. 普通变量
  2. 环境变重(全局)

定义变量可不仅仅只能在C/C++中,Linux命令行或者系统中也是可以直接定义变量的。

在这里插入图片描述
但是定义的是普通变量,通过查看环境变量的方式查看不了。

export导出环境变量,就可以在系统中可以查看的环境变量。

在这里插入图片描述
所以我们就可以通过export将环境变量中的PATH给改了,就可以实现不用路径直接执行可执行程序了。
在这里插入图片描述
但是不能通过上述方式,因为这样改的话就将全部的PATH给改了,那么其他的指令也就用不成了。

不过我们也不用过于担心,我们在命令行上设置的环境变量具有临时性的,将终端关掉重启就恢复了。

环境变量本身就在内存中存着呢,并不是以文件的方式存在的,改了也不影响,下次登录的时候会重新读取系统的配置文件,重新生成环境变量,如果想让配置的环境变量永久有效的话,是需要更改配置文件的。

  • 登录程序会自动执行Linux上的程序,帮我们在bash的上下文当中导出一些变量,这些变量是从文件中来的。
  • 可以理解成,就相当于在启动的时候读取配置文件,跟我们写程序一样,将数据读到内存里,然后在内存里env就能查看到对应的环境变量了。

系统中相关配置文件一般在:

在这里插入图片描述
正确修改环境变量:
在这里插入图片描述
备注:

环境变量轻易不要修改,非要改最好是新增,不要做覆盖。

which是通过环境变量来查找可执行程序的路径。
在这里插入图片描述

3.4 和环境变量相关的命令:

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

前几个我们已经讲的差不多了,我们来介绍后几个:

  • unset:

在这里插入图片描述

  • set:

在这里插入图片描述
aa叫局部变量查不到,可以通过export直接倒成环境变量,此时再查就能查到了。

查看本地变量:

在这里插入图片描述

set的环境变量和本地变量都能查到。

3.5 环境变量的获取:

3.5 - 1 main函数可以带参数吗?可以带多少?

我们先来看main函数带两个参数:

#include <stdio.h>

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

将命令行传递给命令行参数:

在这里插入图片描述

  • char* argv[]是个指针数组,而int argc则是指针数组中元素的个数。
  • 可执行程序和选项都是字符串,最后都以指针数组的方案存在了指针数组中。
  • 指针数组中存的是字符串的起始地址
  • 最后以NULL结尾

我们给main函数传递的argc,char* argv[]是命令行参数,传递的是:命令行中输入的程序名和选项!!

具体是哪个字符串的起始地址呢?
在这里插入图片描述

这样就传递命令行参数了。

3.5 - 2 传递参数的意义是什么

命令行计算器:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    if(argc != 4)
    {
        printf("Usage: %s [-a|-s|-m|-d] one_data two_data\n", argv[0]);
        return 0;
    }

    int x = atoi(argv[2]);
    int y = atoi(argv[3]);

    if(strcmp("-a", argv[1]) == 0)
    {
        printf("%d+%d=%d\n",x, y, x + y);
    }
    else if(strcmp("-s", argv[1]) == 0)
    {
        printf("%d-%d=%d\n",x, y, x - y);
    }
    else if(strcmp("-m", argv[1]) == 0)
    {
        printf("%d*%d=%d\n",x, y, x * y);
    }
    else if(strcmp("-d", argv[1]) == 0 && y != 0)
    {
        printf("%d/%d=%d\n",x, y, x / y);
    }
    else
    {
        printf("Usage: %s [-a|-s|-m|-d] one_data two_data\n", argv[0]);
    }

    return 0;
}

运行结果:

在这里插入图片描述
意义:

  • 同一个程序,通过传递不同的参数,让同一个程序有不同的执行逻辑,执行结果。
  • Linux系统中,会根据不通的选项,让不同的命令,可以有不同的表现!指令中那么多选项的由来和起作用的方式!!
  • ls -a -l -i不同的选项代表的含义不一样。

那么命令行参数是怎么传递给main函数的呢??

  • 进程控制讲

3.6 进程获取环境变量的方法:

方法一:main函数的第三个参数

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

void func(void)
{
    printf("hehe\n");
}

int main(int argc, char* argv[], char* env[])
{
    //func(1, 1);
    int i = 0;
    for(i = 0; env[i]; i++)
    {
        printf("env[%d]: %s\n", i, env[i]);
    }

    return 0;
}

打印出来的就是各种环境变量了:

在这里插入图片描述

  • char* env[]也是个指针数组
  • 数组里的每个元素都是指向一个字符串
  • 每个字符串就是一个环境变量
  • 最后以NULL结尾

一个进程是会被传入环境变量参数的,每个进程都是的!!

在这里插入图片描述
我们自己的程序跑起来变成进程,这个进程就被调用方传入了环境变量了。

如果一个C语言函数在声明中没有带参数,但是我们强制给其带参的话并不报错。
而且强行传的参数,依旧压栈,依旧形成临时变量,只不过后面没有使用罢了。
给函数定义的时候形参带上void的话,强制传参才会报错。

进程想获得环境变量的第一种方法,那就是main函数的第三个参数,传进来的值就是一个指针数组,就可以通过指针数组的方案来遍历。

方法二:通过C语言全局变量

int main()
{
	extern char** environ;

	for (int i = 0; environ[i]; i++)
	{
		printf("%d: %s\n", i, environ[i]);
	}

	return 0;
}

方法三:用接口getenv()

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* val = getenv("PATH");
    printf("%s\n", val);

    return 0;
}

3.7 我为什么要获取环境变量:

以后有用途,万一有用途~

我们写一个智能自己运行的程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    //让程序只能自己执行
    char* id = getenv("USER");

    //忽略大小写
    if(strcasecmp(id, "Zh_Ser") != 0)
    {
        printf("权限拒绝!\n");
        return 0;
    }
    printf("成功执行...\n");

    char *val = getenv("PATH");
    printf("%s\n", val);
    
    return 0;
}

在这里插入图片描述
就算是root用户也不能执行!

环境变量是谁给我的呢??目前谈不清,但是我们可以观察到!

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

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

相关文章

C语言进阶——数据在内存中的存储,你知道吗?

今天我们深度剖析数据在内存中的存储&#xff1a; 重点知识&#xff1a; 1、数据类型详细介绍 2、整形在内存中的存储&#xff1a;原码、反码、补码 3、大小端字节序介绍及判断 4、浮点型在内存中的存储解析 之前我们涉及关于这一部分的知识只是大致的进行讲解&#xff0…

网络编程:UDP socket

文章目录 阅读前导 服务端定义日志框架成员属性服务端框架 初始化服务器创建套接字绑定 运行服务端读取数据参数解读 处理数据向客户端发送响应数据关闭文件描述符 客户端定义创建套接字绑定发送数据接收服务器的响应数据关闭文件描述符 测试1本地环回作用 本地测试netstat 指令…

继续科普:ChatGPT 最新写论文使用方法

这两天发现了几个国内就能用的ChatGPT,不需要魔法! 给大家推荐两种方法,大家自行选择: 1、电脑端安装VSCode软件,使用GPT插件: 优点: 无需魔法、无需付费、软件简单易用(稍懂电脑就会用) 缺点: ① 只支持电脑端,不支持手机:软件安装虽简单,但不一定所有人都…

行业常识_RFID

文章目录 1 RF2 RFID2.1 RFID的应用场景2.2 RFID工作原理 1 RF RF&#xff0c;是Radio Frequency的缩写&#xff0c; Radio&#xff0c;n. 收音机&#xff1b;无线电通讯&#xff1b; v. 用无线电通讯&#xff08;或发送消息&#xff09; Frequency&#xff0c;n. 频率 RF中文…

electron+vue3全家桶+vite项目搭建【16】electron多窗口,pinia状态无法同步更新问题解决

文章目录 引入实现效果展示问题展示解决方案思路整理1.主进程添加handle2.编写pinia插件3.完善pinia插件4.最终实现效果 引入 pinia是vue3官方支持的全局状态管理工具&#xff0c;简单易用&#xff0c;但是electron的多窗口虽然加载的页面是单个路由&#xff0c;但其实已经是另…

【全网首发开源教程】【Labview机器人仿真与控制】Labview与Solidworks多路支配关系-四足爬行机器人仿真与控制

&#x1f389;欢迎来到Labview专栏~四足爬行机器人仿真与控制 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Labview-3D虚拟平台 文章作者技术和水平有限&#xff0c;如果文中出现错误&#…

【python】keras包:深度学习

Part 0. 环境配置 与 学习数据下载 keras包 与 tensorflow包 WinR &#xff0c;输入指令&#xff1a; pip install tensorflow pip install keras 推荐镜像&#xff1a;-i https://pypi.tuna.tsinghua.edu.cn/simple/ 关于包 keras包相当于是 tensflow 包的前端 tensflow包…

15 | Qt的自定义信号

1 前提 Qt 5.14.2 2 具体操作 2.1 自定义信号 2.1.1 UI界面设置 2.1.1.1 widget.ui 2.1.1.2 setdialog.ui 2.1.2 headers 2.1.2.1 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui {class Widget; } QT_END_NAMESP…

105-Linux_Libevent库的安装与使用

文章目录 一.Libevent 概述1.Libevent的特点2.Libevent使用模型3.Libevent 支持的事件类型 二.Libevent的安装三.Libevent简单使用实例 一.Libevent 概述 Libevent 是开源社区的一款高性能的 I/O 框架库&#xff0c;使用 Libevent 的著名案例有&#xff1a;高性能的分布式内存…

操作系统之死锁处理策略

概念 一、什么是死锁 哲学家进程问题中&#xff0c;都在等待另外的哲学家放弃另一只筷子&#xff0c;造成了都不能用餐的现象&#xff0c;互相等待对方的资源 二、死锁、饥饿、死循环区别 三、死锁产生的条件 1、互斥条件 只有对互斥使用的资源的争抢才能导致死锁&#xff0…

shell编程、makefile学习笔记

windows :\r\n linux:\n 1.shell介绍 1.1、shell是操作系统的终端命令行 (1)shell可以理解为软件系统提供给用户操作的命令行界面&#xff0c;可以说它是人机交互的一种方式。 (2)我们可以使用shell和操作系统、uboot等软件系统进行交互。具体来说就是我们通过shell给软件…

【SpringBoot 应用打包与部署】

SpringBoot 应用打包与部署 笔记记录 1. Jar包方式打包与部署1.1 添加maven打包插件1.2 双击package打包成功1.3 IDEA中运行jar文件 2. War包方式打包与部署2.1 声明打包方式为War包2.2 双击package2.3 将打包好的war包放在Tomcat的webapps目录下 1. Jar包方式打包与部署 1.1 …

嵌入式开发--无刷电机学习4--SVPWM

SVPWM空间矢量脉宽调节 这张图是基于α和β坐标系&#xff0c;也就是定子磁场坐标系&#xff0c;图中的Uout就是定子磁场的空间矢量&#xff0c;它的角度表示定子线圈产生磁场的方向&#xff0c;长度表示磁场的强度&#xff0c;以电机匀速旋转为例&#xff0c;FOC控制的目标就是…

【Java】抽象类接口Object类

目录 1.抽象类 2.接口 2.1实现多个接口 2.2接口之间的关系 2.3接口使用实例 2.3.1Comparable接口 2.3.2Comparator接口 2.3.2Clone接口 2.4抽象类与接口的区别 3.Object类 3.1getClass方法 3.2equals方法 3.3hashcode方法 1.抽象类 定义&#xff1a;抽象方法&…

[Cursor Tool] 面向编程的ChatGPT工具的入门使用指南

文章目录 0. 面向编程的ChatGPT工具的入门使用指南1. Cursor的下载和安装2. Cursor的基本功能的使用2.1 关于Cursor的Chat模式2.2 关于Cursor的Edit模式 3 关于Cursor的项目级应用4 使用Cursor帮助我们从项目的设计出发来为我们提供建议 0. 面向编程的ChatGPT工具的入门使用指南…

车载软件架构——闲聊几句AUTOSAR BSW(三)

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 我特别喜欢一个老话,来都来了。我觉得这就是松弛感,既然来了,就开心起来吧!松弛感来自于专注,焦虑不是靠克服的,是靠忘记的,当你很专注做一件事的时候…

剪枝与重参:课程总结

目录 课程总结前言1. 基础快速入门2. 基于VGG的模型剪枝3. 英伟达2-4剪枝方案4. YOLOv8剪枝5. ACNet、DBB、RepVGG重参个人总结 课程总结 前言 手写AI推出的全新模型剪枝与重参课程。记录下个人学习笔记&#xff0c;仅供自己参考。 本次课程主要是课程总结&#xff0c;对之前学…

设计模式之代理模式(静态代理动态代理)

目录 1、什么是代理模式 2、代理模式的结构 3、代理模式的实现 3.1 静态代理和动态代理概念 3.2 静态代理 3.3 动态搭理 3.3.1 代码实现 3.3.2 Proxy类讲解 4、动态代理VS静态代理 5、代理模式优缺点 1、什么是代理模式 由于某些原因需要给某对象提供一个代理以控制对…

【开发工具】 Adobe 2022 最详细的安装方法 就是这么简单 绿色 安全方便

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

vulnhub靶场之Black-Widow-final

1.信息收集 探测存活主机&#xff0c;发现192.168.239.177存活 对目标主机192.168.239.177进行端口扫描&#xff0c;发现存活22、80、111、2049、3128等端口 在浏览器中访问http://192.168.239.177&#xff0c;并查看源码&#xff0c;未发现有用的信息 对http://192.168.23…