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

linux系统编程重点复习--进程的控制

目录

1 复习目标

2 进程相关概念

2.2 并行和并发

2.3 PCB-进程控制块 

2.4 进程状态(面试考)

 3 创建进程

3.2 ps命令和kill命令

3.3 getpid/getppid

3.4 练习题

 

4 exec函数族

        4.1 函数作用和函数介绍

4.1.1 execl函数

4.1.2 execlp函数

4.2 exec函数族原理介绍

4.3 exec函数练习

5 进程回收

5.1 为什么要进行进程资源的回收

5.2 孤儿进程

5.3 僵尸进程

5.4 进程回收函数

5.4.1 wait函数

5.4.2waitpid函数

6 作业

6.1 作业1

6.2 作业2

7 大纲


1 复习目标

  1. 了解进程相关的概念
  2. 掌握fork/getpid/getppid函数的使用
  3. 熟练掌握ps/kill命令的使用
  4. 熟练掌握execl/execlp函数的使用
  5. 说出什么是孤儿进程什么是僵尸进程
  6. 熟练掌握wait函数的使用
  7. 熟练掌握waitpid函数的使用

2 进程相关概念

  1. 程序,是指编译好的二进制文件,在磁盘上,占用磁盘空间, 是一个静态的概念.
  2. 进程,一个启动的程序, 进程占用的是系统资源,如:物理内存,CPU,终端等,是一个动态的概念
  3. 程序 → 剧本(纸)
  4. 进程 → 戏(舞台、演员、灯光、道具...)

同一个剧本可以在多个舞台同时上演。同样,同一个程序也可以加载为不同的进程(彼此之间互不影响)

2.2 并行和并发

  1. 并发,在一个时间段内, 是在同一个cpu上, 同时运行多个程序。

如:若将CPU的1S的时间分成1000个时间片,每个进程执行完一个时间片必须无条件让出CPU的使用权,这样1S中就可以执行1000个进程。

 

 

 

  1. 并行性指两个或两个以上的程序在同一时刻发生(需要有多颗)。

 

2.3 PCB-进程控制块 

每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。

/usr/src/linux-headers-4.4.0-96/include/linux/sched.h文件的1390行处可以查看struct task_struct 结构体定义。其内部成员有很多,我们重点掌握以下部分即可:

  • 进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非负整数。
  • 进程的状态,有就绪、运行、挂起、停止等状态。
  • 进程切换时需要保存和恢复的一些CPU寄存器。
  • 描述虚拟地址空间的信息。
  • 描述控制终端的信息。
  • 当前工作目录(Current Working Directory)。getcwd --pwd
  • umask掩码。
  • 文件描述符表,包含很多指向file结构体的指针。
  • 和信号相关的信息
  • 用户id和组id。
  • 会话(Session)和进程组。
  • 进程可以使用的资源上限(Resource Limit)。

        ulimit -a

2.4 进程状态(面试考)

  • 进程基本的状态有5种。分别为初始态,就绪态,运行态,挂起态与终止态。其中初始态为进程准备阶段,常与就绪态结合来看。

 3 创建进程

        

3.1 fork函数

函数作用:创建子进程

原型: pid_t fork(void);

函数参数:无

返回值:调用成功:父进程返回子进程的PID,子进程返回0;

        调用失败:返回-1,设置errno值。

 fork函数代码片段实例:

 

  • fork函数总结

fork函数的返回值?

 父进程返回子进程的PID,是一个大于0数;

 子进程返回0;

特别需要注意的是:不是fork函数在一个进程中返回2个值,而是在父子进程各自返回一个值。

子进程创建成功后,代码的执行位置?

   父进程执行到什么位置,子进程就从哪里执行

►如何区分父子进程

通过fork函数的返回值

►父子进程的执行顺序

  不一定,哪个进程先抢到CPU,哪个进程就先执行

3.2 ps命令和kill命令

  1. ps aux | grep "xxx"
  2. ps ajx | grep "xxx"
  • -a:(all)当前系统所有用户的进程
  • -u:查看进程所有者及其他一些信息
  • -x:显示没有控制终端的进程 -- 不能与用户进行交互的进程【输入、输出】
  • -j: 列出与作业控制相关的信息
  1. kill -l 查看系统有哪些信号
  2. kill -9 pid 杀死某个线程

3.3 getpid/getppid

getpid - 得到当前进程的PID

pid_t getpid(void);

getppid - 得到当前进程的父进程的PID

pid_t getppid(void);

//fork函数测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>int main()
{printf("before fork, pid:[%d]\n", getpid());//创建子进程//pid_t fork(void);pid_t pid = fork();if(pid<0) //fork失败的情况{perror("fork error");return -1;}else if(pid>0)//父进程{printf("father: [%d], pid==[%d], fpid==[%d]\n", pid, getpid(),getppid());//sleep(1);}else if(pid==0) //子进程{printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());}printf("after fork, pid:[%d]\n", getpid());return 0;
}

3.4 练习题

1编写程序,循环创建多个子进程,要求如下:

多个子进程是兄弟关系。

判断子进程是第几个子进程

画图讲解创建多个子进程遇到的问题

注意:若让多个子进程都是兄弟进程,必须不能让子进程再去创建新的子进程。

//fork函数测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int g_var = 99;int main()
{//创建子进程pid_t pid = fork();if(pid<0) //fork失败的情况{perror("fork error");return -1;}else if(pid>0)//父进程{printf("father: [%d], pid==[%d], fpid==[%d]\n", pid, getpid(),getppid());g_var++;printf("[%p]", &g_var);}else if(pid==0) //子进程{sleep(1); //为了避免父进程还没有执行, 子进程已经结束了printf("[%p]", &g_var);printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());printf("child: g_var==[%d]\n", g_var);}return 0;
}

2.编写程序,测试父子进程是否能够共享全局变量

重点通过这个案例讲解读时共享,写时复制

 

//循环创建n个子进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>int main()
{int i = 0;for(i=0; i<3; i++){//创建子进程pid_t pid = fork();if(pid<0) //fork失败的情况{perror("fork error");return -1;}else if(pid>0)//父进程{printf("father: pid==[%d], fpid==[%d]\n", getpid(),getppid());//sleep(1);}else if(pid==0) //子进程{printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());break;}}//第1个子进程if(i==0){printf("[%d]--[%d]: child\n", i, getpid());	}//第2个子进程if(i==1){printf("[%d]--[%d]: child\n", i, getpid());	}//第3个子进程if(i==2){printf("[%d]--[%d]: child\n", i, getpid());	}//父进程if(i==3){printf("[%d]--[%d]: child\n", i, getpid());	}sleep(10);return 0;
}

4 exec函数族

        4.1 函数作用和函数介绍

  有的时候需要在一个进程里面执行其他的命令或者是用户自定义的应用程序,此时就用到了exec函数族当中的函数。使用方法一般都是在父进程里面调用fork创建处子进程,然后在子进程里面调用exec函数。

4.1.1 execl函数

函数原型: int execl(const char *path, const char *arg, ... /* (char  *) NULL */);

参数介绍:

  • path: 要执行的程序的绝对路径
  • 变参arg: 要执行的程序的需要的参数
  • arg:占位,通常写应用程序的名字
  • arg后面的: 命令的参数
  • 参数写完之后: NULL

返回值:若是成功,则不返回,不会再执行exec函数后面的代码;若是失败,会执行execl后面的代码,可以用perror打印错误原因。

execl函数一般执行自己写的程序。

4.1.2 execlp函数

函数原型: int execlp(const char *file, const char *arg, .../* (char  *) NULL */);

参数介绍:

  • file: 执行命令的名字, 根据PATH环境变量来搜索该命令
  • arg:占位
  • arg后面的: 命令的参数
  • 参数写完之后: NULL

返回值:若是成功,则不返回,不会再执行exec函数后面的代码;若是失败,会执行exec后面的代码,可以用perror打印错误原因。

execlp函数一般是执行系统自带的程序或者是命令.

4.2 exec函数族原理介绍

exec族函数的实现原理图:

 如:execlp(“ls”, “ls”, “-l”, NULL)

 

总结:

exec函数是用一个新程序替换了当前进程的代码段、数据段、堆和栈;原有的进程空间没有发生变化,并没有创建新的进程,进程PID没有发生变化。

4.3 exec函数练习

  1. 使用execl函数执行一个用户自定义的应用程序
  2. 使用execlp函数执行一个linux系统命令

注意:当execl和execlp函数执行成功后,不返回,并且不会执行execl后面的代码逻辑,原因是调用execl函数成功以后,exec函数指定的代码段已经将原有的代码段替换了。

5 进程回收

5.1 为什么要进行进程资源的回收

   当一个进程退出之后,进程能够回收自己的用户区的资源,但是不能回收内核空间的PCB资源,必须由它的父进程调用wait或者waitpid函数完成对子进程的回收,避免造成系统资源的浪费。

5.2 孤儿进程

  1. 孤儿进程的概念:

若子进程的父进程已经死掉,而子进程还存活着,这个进程就成了孤儿进程。

  1. 为了保证每个进程都有一个父进程,孤儿进程会被init进程领养,init进程成为了孤儿进程的养父进程,当孤儿进程退出之后,由init进程完成对孤儿进程的回收。
  2. 模拟孤儿进程的案例

编写模拟孤儿进程的代码讲解孤儿进程,验证孤儿进程的父进程是否由原来的父进程变成了init进程。

//孤儿进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>int main()
{//创建子进程pid_t pid = fork();if(pid<0) //fork失败的情况{perror("fork error");return -1;}else if(pid>0)//父进程{sleep(5);printf("father: [%d], pid==[%d], fpid==[%d]\n", pid, getpid(),getppid());}else if(pid==0) //子进程{printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());sleep(20);printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());}return 0;
}

5.3 僵尸进程

  1. 僵尸进程的概念:

若子进程死了,父进程还活着, 但是父进程没有调用wait或waitpid函数完成对子进程的回收,则该子进程就成了僵尸进程。

        如何解决僵尸进程

  • 由于僵尸进程是一个已经死亡的进程,所以不能使用kill命令将其杀死
  • 通过杀死其父进程的方法可以消除僵尸进程。

杀死其父进程后,这个僵尸进程会被init进程领养,由init进程完成对僵尸进程的回收。

  1. 模拟僵尸进程的案例

编写模拟僵尸进程的代码讲解僵尸进程, 验证若子进程先于父进程退出, 而父进程没有调用wait或者waitpid函数进行回收, 从而使子进程成为了僵尸进程.

//僵尸进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>int main()
{//创建子进程pid_t pid = fork();if(pid<0) //fork失败的情况{perror("fork error");return -1;}else if(pid>0)//父进程{sleep(100);printf("father: [%d], pid==[%d], fpid==[%d]\n", pid, getpid(),getppid());}else if(pid==0) //子进程{printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());}return 0;
}

5.4 进程回收函数

5.4.1 wait函数

  • 函数原型:

pid_t wait(int *status);

  • 函数作用:
  • 阻塞并等待子进程退出
  • 回收子进程残留资源
  • 获取子进程结束状态(退出原因)
  • 返回值:
  • 成功:清理掉的子进程ID;
  • 失败:-1 (没有子进程)
  • status参数:子进程的退出状态 -- 传出参数
  • WIFEXITED(status):为非0         进程正常结束

                WEXITSTATUS(status):获取进程退出状态

  • WIFSIGNALED(status):为非0  进程异常终止

                WTERMSIG(status):取得进程终止的信号编号。

  wait函数练习

使用wait函数完成父进程对子进程的回收。

//父进程调用wait函数完成对子进程的回收
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>int main()
{//创建子进程pid_t pid = fork();if(pid<0) //fork失败的情况{perror("fork error");return -1;}else if(pid>0)//父进程{printf("father: [%d], pid==[%d], fpid==[%d]\n", pid, getpid(),getppid());int status;pid_t wpid = wait(&status);printf("wpid==[%d]\n", wpid);if(WIFEXITED(status)) //正常退出{printf("child normal exit, status==[%d]\n", WEXITSTATUS(status));}else if(WIFSIGNALED(status)) //被信号杀死{printf("child killed by signal, signo==[%d]\n", WTERMSIG(status));}}else if(pid==0) //子进程{printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());sleep(20);return 9;}return 0;
}

 

5.4.2waitpid函数

  • 函数原型:

pid_t waitpid(pid_t pid, int *status, in options);

  • 函数作用

同wait函数

  • 函数参数

参数:

pid

pid = -1 等待任一子进程。与wait等效。

pid > 0 等待其进程ID与pid相等的子进程。

pid = 0 等待进程组ID与目前进程相同的任何子进程,也就是说任何和调用

waitpid()函数的进程在同一个进程组的进程。

pid < -1 等待其组ID等于pid的绝对值的任一子进程。(适用于子进程在其他组的情况)

status: 子进程的退出状态,用法同wait函数。

options:设置为WNOHANG,函数非阻塞,设置为0,函数阻塞。

  • 函数返回值

>0:返回回收掉的子进程ID;

-1:无子进程

=0:参3为WNOHANG,且子进程正在运行。

waitpid函数练习

使用waitpid函数完成对子进程的回收

6 作业

6.1 作业1

测试父子进程之间是否共享文件

6.2 作业2

父进程fork三个子进程:

其中一个调用ps命令;

一个调用自定义应用程序;

一个调用会出现段错误的程序。

父进程回收三个子进程(waitpid),并且打印三个子进程的退出状态。

 

=== 段错误 ===

1>. 访问了非法内存

2>. 访问了不可写的区域进行写操作

3>. 栈空间溢出

char* p = “hello,world”        

p0=a’;

7 大纲

程序和进程的概念:
    程序: 是编译好的二进制文件, 存放在磁盘上, 占用的是磁盘空间, 是一个静态的概念.
    进程: 一个启动的程序, 需要占用系统资源: 如 内存, cpu 终端 等
    剧本--->程序
    进程--->唱戏(舞台, 灯光, 道具, 人等资源)
    同一个程序可以在多个终端执行, 类似与同一台戏可以在多个舞台演出.
    没启动一个程序都会有一个进程PID, 即使是相同的程序多次启动也会有个不同的PID.
并行和并发的概念:
    并发: 在一个时间段内, 一个CPU上, 有多个程序在执行.
    并行: 在一个时间片内, 有多个程序在执行(前提是有多个cpu)
    cpu会将一个大的时间段分成多个小的时间片, 让进程轮流使用CPU的时间片.


父子进程不能共享全局变量.

如果想在一个进程内部执行系统命令或者是应用程序, 优先应该想到如下方式:
先fork(), 然后在子进程里面执行execl拉起可执行程序或者命令.
pid = fork();
if(pid==0)
{
    execl(...);
}

execl: 一般用于执行用户自定义的应用程序.
execp: 一般用于执行系统命令

孤儿进程: 父进程先退出, 子进程就变成了孤儿进程, 此时被init进程领养,
          当孤儿进程退出之后, 就会被init进程回收.
          
僵尸进程: 子进程先退出, 父进程没有完成对子进程的回收, 此时子进程就变成了僵尸进程.
如何解决僵尸进程:
    不能使用kill -9杀死僵尸进程, 原因是僵尸进程是一个死掉的进程;
    应该使用杀死僵尸进程父进程的方法来解决僵尸进程;
    原因是: 杀死其父进程可以让init进程领养僵尸进程,最后由init进程回收僵尸进程.
    
wait函数:
    pid_t wait(int *status);
    返回值:
        >0: 回收的子进程的PID
        -1: 没有子进程
    参数:
        status: 子进程的退出状态
            if(WIFEXITED(status))
            {
                WEXITSTATUS(status)
            }
            else if(WIFSIGNALED(status))
            {
                WTERMSIG(status)
            }

相关文章:

linux系统编程重点复习--进程的控制

目录 1 复习目标 2 进程相关概念 2.2 并行和并发 2.3 PCB-进程控制块 2.4 进程状态(面试考) 3 创建进程 3.2 ps命令和kill命令 3.3 getpid/getppid 3.4 练习题 4 exec函数族 4.1 函数作用和函数介绍 4.1.1 execl函数 4.1.2 execlp函数 4.2 exec函数族原理介绍 4.3 …...

12-1_Qt 5.9 C++开发指南_自定义插件和库-自定义Widget组件(提升法(promotion)创建自定义定制化组件)

当UI设计器提供的界面组件不满足实际设计需求时&#xff0c;可以从 QWidget 继承自定义界面组件。 有两种方法使用自定义界面组件&#xff1a; 一种是提升法(promotion)&#xff0c;例如在8.3 节将一个QGraphicsView组件提升为自定义的 QWGraphicsView 类&#xff0c;提升法用…...

【软件测试学习】—软件测试的基本认识(一)

【软件测试学习】—软件测试的基本认识&#xff08;一&#xff09; 文章目录 【软件测试学习】—软件测试的基本认识&#xff08;一&#xff09;一、什么是软件测试二、软件测试的目的三、测试的原则四、测试的标准五、测试的基本要求六、bug的由来七、测试的流程八、开发模式九…...

Unity AI项目笔记

一、创建虚拟环境 在开始进行Unity AI项目之前&#xff0c;首先需要设置一个适当的虚拟环境。以下步骤将会指导你如何创建&#xff1a; 下载Python 3.7。下载Anaconda 2020.11。可以在清华大学开源软件镜像站找到镜像资源&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/a…...

如何在地图上寻找峨眉山零公里的龙洞湖

爬峨眉山的需要&#xff0c;住在零公里附近。 据说这附近有个好玩的地方叫龙洞湖&#xff0c;我们住得远&#xff0c;想步行去看看。拿出地图&#xff0c;搜龙洞湖&#xff0c;尴尬了。搜不到具体位置。细想&#xff0c;人家整个村就叫龙洞村&#xff0c;地图上居然没有标识&a…...

cloudstack平台host加入后,显示CPU speed为0GHz

一、环境说明 操作系统&#xff1a;openEuler 22.03CPU&#xff1a;Kunpeng-920&#xff0c;arm v8cloudstack&#xff1a;4.18libvirtd&#xff1a;6.2.0 二、问题描述 cloudstack平台初始化完成后&#xff0c;第一次加入host&#xff0c;系统虚拟机一直无法正常创建&#…...

创新技术应用,提升企业图文档管理水平的新思路

信息爆炸和数字化发展的时代&#xff0c;企业图文档管理显得尤为重要。传统的纸质文件管理方式已经无法满足企业高效、安全、便捷管理的需求。因此&#xff0c;创新技术的应用成为了提升企业图文档管理水平的必然选择。PDM&#xff08;产品数据管理&#xff09;与BOM&#xff0…...

网络安全 Day22-mariadb数据库用户管理

数据库用户管理 1. mariadb数据库用户管理2. mariadb数据库用户授权3. 用户回收授权4. 使客户端连接数据库 1. mariadb数据库用户管理 用户的格式: 用户主机范围 合起来才算一个用户授权主机范围 只能从本机访问: localhost或127.0.0.1或10.0.0.166(指定IP)授权整个网段: 授权…...

SERDES关键技术

目录 一、SERDES介绍 二、SERDES关键技术 2.1 多重相位技术 2.2 线路编解码技术 2.2.1 8B/10B编解码 2.2.2 控制字符&#xff08;Control Characters&#xff09; 2.2.3 Comma检测 2.2.4 扰码&#xff08;Scrambling&#xff09; 2.2.5 4B/5B与64B/66B编解码技术 2.3 包传…...

小程序如何上传商品图片

了解如何在小程序商城中上传商品图片是非常重要的&#xff0c;因为商品图片的质量和展示效果直接影响到用户对商品的购买决策。下面&#xff0c;我将介绍怎么在小程序上传产品图片的方法和注意事项。 1. 图片准备&#xff1a;在上传商品图片之前&#xff0c;首先要准备好商品图…...

vue中人员导出功能实现

大纲&#xff1a; 1、导出定义的export.js文件 代码展示 import axios from axios //导出一 export const exportExcel (url, params, name, type post) > {// url url路径 params 查询参数 name 文件名 type 请求方式axios[type](url, params, {responseType: blob,}).t…...

【微信小程序】引入第三方库poke对GZIP压缩数据进行解压

使用 npm 包管理工具&#xff1a; 首先&#xff0c;在小程序的根目录下执行 npm init 初始化项目&#xff0c;生成 package.json 文件。然后&#xff0c;通过 npm 安装 pako&#xff1a;npm install pako。接下来&#xff0c;在小程序的根目录下创建一个名为 miniprogram_npm 的…...

Pandas操作Excel

Pandas 是 Python 语言的一个扩展程序库&#xff0c;用于数据分析。 菜鸟教程&#xff1a;https://www.runoob.com/pandas/pandas-tutorial.html 读取Excel pd.read_excel(path,sheet_name,header) path&#xff1a;excel文件路径sheet_name&#xff1a;读取的sheet&#xff0…...

leetcode 712. Minimum ASCII Delete Sum for Two Strings(字符串删除字母的ASCII码之和)

两个字符串s1, s2, 删除其中的字母使s1和s2相等。 问删除字母的最小ASCII码之和是多少。 思路&#xff1a; DP 先考虑极端的情况&#xff0c;s1为空&#xff0c;那么要想达到s2和s1相等&#xff0c;就要把s2中的字母删完&#xff0c; ASCII码之和就是s2中所有字母的ASCII码之…...

Springboot -- 按照模板生成docx、pdf文件,docx转pdf格式

使用 poi-tl 根据模板生成 word 文件。 使用 xdocreport 将 docx 文件转换为 pdf 文件。 xdocreport 也支持根据模板导出 word &#xff0c;但是 poi-tl 的功能更齐全&#xff0c;操作更简单&#xff0c;文档清晰。 poi-tl 、xdocreport 内部均依赖了 poi &#xff0c;要注意两…...

UE5.1.1 创建C++项目失败

因一直使用Unity开发环境&#xff0c;安装Unreal后&#xff0c;并未详细配置过其开发环境&#xff0c;默认创建蓝图工程无异常&#xff0c;但创建UE C项目时总共遇到两个错误&#xff1a; 错误一 Running /Epic/UE/UE_5.1/Engine/Build/BatchFiles/Build.bat -projectfiles -…...

windows进行端口映射

windows进行端口映射 1. 查询端口映射情况 netsh interface portproxy show v4tov42. 查询某一个IP的所有端口映射情况 netsh interface portproxy show v4tov4 | find "[IP]" # 例&#xff1a; netsh interface portproxy show v4tov4 | find "192.168.1.1&quo…...

Python 异常处理

Python 异常处理 python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误。你可以使用该功能来调试python程序。 异常处理: 本站Python教程会具体介绍。断言(Assertions):本站Python教程会具体介绍。 python标准异常 异常名称描述BaseException所有异常的…...

C++ 类的静态成员

在结构化程序设计中程序模块的基本单位是函数&#xff0c;因此模块间对内存中数据的共享是通过函数与和函数之间的数据共享来实现的&#xff0c;其中包括两个途径——参数传递和全局变量。 面向对象的程序设计方法兼顾数据的共享和保护&#xff0c;将数据与操作数据的函数封装…...

360T7路由器进行WiFi无线中继教程

360T7路由器进行WiFi中继教程 1. 概述2. 360T7路由器进行WiFi中继实现教程2.1 登录路由器管理界面2.2 选择上网方式2.3 搜索WiFi2.4 连接WiFi2.5 点击确认2.6 在主页面查看网络 1. 概述 中继路由系统由一组中继路由器组成&#xff0c;为不能交换路由信息的路由域提供中继路由。…...

主成分分析

主成分分析 相关概念方差协方差协方差矩阵特征值和特征向量 主成分分析数据降维主成分分析原理主成分分析过程sklearn库中的PCA主成分分析实现案例 相关概念 方差 方差是一个用来衡量一组数据离散程度的统计量&#xff0c;它是各样本与样本均值的差的平方和的平均值。方差越大…...

笙默考试管理系统-MyExamTest(26)

笙默考试管理系统-MyExamTest&#xff08;26&#xff09; 目录 一、 笙默考试管理系统-MyExamTest 二、 笙默考试管理系统-MyExamTest 三、 笙默考试管理系统-MyExamTest 四、 笙默考试管理系统-MyExamTest 五、 笙默考试管理系统-MyExamTest 笙默考试管理系统-MyEx…...

重新理解 RocketMQ Commit Log 存储协议

最近突然感觉&#xff1a;很多软件、硬件在设计上是有 root reason 的&#xff0c;不是 by desgin 如此&#xff0c;而是解决了那时、那个场景的那个需求。一旦了解后&#xff0c;就会感觉在和设计者对话&#xff0c;了解他们的思路&#xff0c;学习他们的方法&#xff0c;思维…...

ES6基础知识十:你是怎么理解ES6中 Decorator 的?使用场景?

一、介绍 Decorator&#xff0c;即装饰器&#xff0c;从名字上很容易让我们联想到装饰者模式 简单来讲&#xff0c;装饰者模式就是一种在不改变原类和使用继承的情况下&#xff0c;动态地扩展对象功能的设计理论。 ES6中Decorator功能亦如此&#xff0c;其本质也不是什么高大…...

接口/Web自动化测试如何做?框架如何搭建封装?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化测试怎么做…...

Linux怎么从网络上下载文件

wget命令用于从网络上下载文件 下载文件&#xff1a; wget [URL]使用wget命令加上要下载的文件的URL&#xff0c;可以将文件下载到当前目录。 指定保存的文件名&#xff1a; wget -O [保存的文件名] [URL]使用-O选项后跟保存的文件名&#xff0c;可以指定下载的文件保存的名称…...

Flutter携带JSON参数post请求

在Flutter中发送带有JSON参数的网络请求&#xff0c;你可以使用HTTP库&#xff08;如http或dio&#xff09;来实现。以下是使用http库发送网络请求并携带JSON参数的示例&#xff1a; import package:http/http.dart as http; import dart:convert;// 创建参数Map Map<Strin…...

【vue】vue-image-lazy图片懒加载使用与介绍【超详细+npm包源代码】

简介 当前插件是基于vue3&#xff0c;写的一个图片懒加载&#xff0c;文章最下方是npm包的源码&#xff0c;你可以自己拿去研究和修改&#xff0c;如有更好的想法可以留言&#xff0c;如果对你有帮助&#xff0c;可以点赞收藏和关注&#xff0c;谢谢。 后续会添加图片放大和切…...

MFC第二十四天 使用GDI对象画笔和画刷来开发控件(分页控件选择态的算法分析、使用CToolTipCtrl开发动静态提示)

文章目录 GDI对象画笔和画刷来开发控件梯形边框的按钮控件CMainDlg.hCMainDlg.cppCLadderCtrl.hCLadderCtrl.cpp 矩形边框的三态按钮控件 CToolTipCtrl开发动静态提示CMainDlg.hCMainDlg.cppCLadderCtrl.hCLadderCtrl.cpp: 实现文件 矩形边框的三态按钮控件 CToolTipCtrl开发动…...

【NLP-新工具】语音转文本与OpenAI的用途

一、说明 OpenAI最近2022发布了一个名为Whisper的新语音识别模型。与DALLE-2和GPT-3不同&#xff0c;Whisper是一个免费的开源模型。它的主要功能就是将语音翻译成文本。本文将介绍如何使用这个重要应用库。 二、 Whisper概念 2.1 Whisper是啥&#xff1f; Whisper 是一种自动…...