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

【操作系统】进程间通信方式

进程间通信方式

  • 前言 / 概述
  • 一、管道
    • 管道
    • 命名管道
  • 二、消息队列
  • 三、共享内存
  • 四、信号量
    • 信号量概述
    • 互斥访问
    • 条件同步
    • 信号
  • 五、socket
  • 总结

前言 / 概述

  每个进程的用户地址空间都是独立的,⼀般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。


Linux 内核提供了不少进程间通信(IPC,Inter-Process Communication)的机制:


  在实际学习面试中不仅需要熟练列出进程间通信的方式,这只是表面功夫,还需要进一步了解每种通信方式的优缺点及应用场景。

一、管道

管道

管道,通常指无名管道,是 UNIX 系统IPC最古老的形式。

1. 特点

  1. 它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端

  2. 它只能用于具有亲缘关系的进程之间的通信(父子进程或者兄弟进程之间)

  3. 基于内存文件的通信机制,可以看成是一种特殊的文件,但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。

缺点: 管道这种通信方式效率低,不适合进程间频繁地交换数据。

2. 原理

#include <unistd.h>
int pipe(int fd[2]);    // 返回值:若成功返回0,失败返回-1

当一个管道建立时,它会创建两个文件描述符:fd[0]为读而打开,fd[1]为写而打开。如下图:

要关闭管道只需将这两个文件描述符关闭即可。

  其实,所谓的管道,就是内核里面的一串缓存。从管道的一端写入的数据,实际上是缓存在内核中的,另一端读取,也就是从内核中读取这段数据。另外,管道传输的数据是无格式的流且大小受限。

怎么样才能使得管道是跨过两个进程的呢?

  使用 fork 创建子进程,创建的子进程会复制父进程的文件描述符,这样就做到了两个进程各有两个fd[0]fd[1],两个进程就可以通过各自的 fd 写入和读取同一个管道文件实现跨进程通信了。


  管道只能一端写入,另⼀端读出,所以上面这种模式容易造成混乱,因为父进程和子进程都可以同时写入,也都可以读出。那么,为了避免这种情况,通常的做法是:

  • 父进程关闭读取的 fd[0],只保留写入的 fd[1]
  • 子进程关闭写入的 fd[1],只保留读取的 fd[0]


所以说如果需要双向通信,则应该创建两个管道。

命名管道

FIFO,也称为命名管道,它是一种文件类型。

1、特点

  • FIFO可以在无关进程之间的交换数据,与无名管道不同,因为命名管道,提前创建了一个类型为管道的设备文件,在进程里只要使用这个设备文件,就可以相互通信。
  • FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中(缓存在内核中)。

2、原型

#include <sys/stat.h>
// 返回值:成功返回0,出错返回-1
int mkfifo(const char *pathname, mode_t mode);

其中的 mode 参数与open函数中的 mode 相同。一旦创建了一个 FIFO,就可以用一般的文件I/O函数操作它。

当 open 一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别:

  • 若没有指定O_NONBLOCK(默认),只读 open 要阻塞到某个其他进程为写而打开此 FIFO。类似的,只写 open 要阻塞到某个其他进程为读而打开它。
  • 若指定了O_NONBLOCK,则只读 open 立即返回。而只写 open 将出错返回 -1,如果没有进程已经为读而打开该 FIFO,其errno置ENXIO。

  不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循先进先出原则,不支持 lseek 之类的文件定位操作。

二、消息队列

  • 消息队列是由操作系统维护的以字节序列为基本单位的间接通信机制
  • 消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

特点

  • 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
  • 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
  • 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
  • 两大缺点:通信不及时、数据大小类型有限制

详细概述

  • 前面说到管道的通信方式是效率低的,因此管道不适合进程间频繁地交换数据。对于这个问题,消息队列的通信模式就可以解决。比如,A 进程要给 B 进程发送消息,A 进程把数据放在对应的消息队列后就可以正常返回了,B 进程需要的时候再去读取数据就可以了。同理,B 进程要给 A 进程发送消息也是如此。

  • 消息队列是保存在内核中的消息链表,在发送数据时,会分成一个一个独立的数据单元,也就是消息体(数据块),消息体是用户自定义的数据类型,消息的发送方和接收方要约定好消息体的数据类型所以每个消息体都是固定大小的存储块,不像管道是无格式的字节流数据。如果进程从消息队列中读取了消息体,内核就会把这个消息体删除。

  • 消息队列生命周期随内核,如果没有释放消息队列或者没有关闭操作系统,消息队列会一直存在,而前面匿名管道的生命周期是随进程的创建而建立,随进程的结束而销毁。

  • 消息这种模型,两个进程之间的通信就像平时发邮件一样,你来一封,我回一封,可以频繁沟通了。但邮件的通信方式存在不足的地方有两点,一是通信不及时,二是附件大小有限制,这同样也是消息队列通信不足的点。

  • 所以消息队列不适合比较大数据的传输,因为在内核中每个消息体都有一个最大长度的限制,同时所有队列所包含的全部消息体的总长度也是有上限。在 Linux 内核中,会有两个宏定义 MSGMAXMSGMNB ,它们以字节为单位,分别定义了⼀条消息的最大长度和一个队列的最大长度。

  • 消息队列通信过程中,存在用户态与内核态之间的数据拷贝开销,因为进程写⼊数据到内核中的消息队列时,会发生从用户态拷贝数据到内核态的过程,同理另一进程读取内核中的消息数据时,会发生从内核态拷贝数据到用户态的过程。

三、共享内存

消息队列的读取和写入的过程,都会有发生用户态与内核态之间的消息拷贝过程。那共享内存的方式,就很好的解决了这⼀问题。

  • 共享内存是把同一个物理内存区域同时映射到多个进程的内存地址空间的通信机制。
  • 进程都有私有的地址空间,因此利用共享内存进行进程间通信,需要明确设置共享内存段。

优点:快速、方便的共享数据
缺点:必须用额外的同步机制来协调数据访问。

1. 特点

  • 共享内存是最快的一种 IPC,因为进程是直接对内存进行存取(直接通信、不通过内核)。

  • 因为多个进程可以同时操作,所以需要进行同步。

  • 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。

2. 内部实现机制

  共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写入的东西,另外一个进程马上就能看到了,都不需要拷贝来拷贝去,传来传去,大大提高了进程间通信的速度。

四、信号量

信号量概述

用了共享内存通信方式,带来新的问题,那就是如果多个进程同时修改同一个共享内存,很有可能就冲突了。例如两个进程都同时写一个地址,那先写的那个进程会发现内容被别人覆盖了。

为了防止多进程竞争共享资源,而造成的数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只能被一个进程访问。正好,信号量就实现了这一保护机制。

信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个整型的计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据

特点:

  • 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
  • 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
  • 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
  • 支持信号量组。

缺点: 传送的信息量小,只有一个信号类型

信号量表示资源的数量,控制信号量的方式有两种原子操作:

  • 一个是 P 操作,这个操作会把信号量减去 1,相减后如果信号量 < 0,则表明资源已被占用,进程需阻塞等待;相减后如果信号量 >= 0,则表明还有资源可使用,进程可正常继续执行

  • 另一个是 V 操作,这个操作会把信号量加上 1,相加后如果信号量 <= 0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行;相加后如果信号量 > 0,则表明当前没有阻塞中的进程;

P 操作是用在进入共享资源之前,V 操作是用在离开共享资源之后,这两个操作是必须成对出现的。

互斥访问

信号量的使用1:互斥访问

如果要使得两个进程互斥访问共享内存,我们可以初始化信号量为 1

具体的过程如下:

  • 进程 A 在访问共享内存前,先执行了 P 操作,由于信号量的初始值为 1,故在进程 A 执行 P 操作后信号量变为 0,表示共享资源可用,于是进程 A 就可以访问共享内存。
  • 若此时,进程 B 也想访问共享内存,执行了 P 操作,结果信号量变为了 -1,这就意味着临界资源已被占用,因此进程 B 被阻塞。
  • 直到进程 A 访问完共享内存,才会执行V 操作,使得信号量恢复为 0,接着就会唤醒阻塞中的线程B,使得进程 B 可以访问共享内存,最后完成共享内存的访问后,执行 V 操作,使信号量恢复到初始值 1。

可以发现,信号初始化为 1 ,就代表着是互斥信号量,它可以保证共享内存在任何时刻只有一个进程在访问,这就很好的保护了共享内存。

条件同步

信号量的使用2:条件同步

  在多进程里,每个进程并不一定是顺序执行的,但有时候我们又希望多个进程能密切合作,以实现一个共同的任务。例如,进程 A 是负责生产数据,而进程 B 是负责读取数据,这两个进程是相互合作、相互依赖的,进程 A必须先生产了数据,进程 B 才能读取到数据,所以执行是有前后顺序的

这时候,就可以用信号量来实现多进程同步的⽅式,我们可以初始化信号量为 0


具体过程:

  • 如果进程 B 比进程 A 先执行了,那么执行到 P 操作时,由于信号量初始值为 0,故信号量会变为-1,表示进程 A 还没生产数据,于是进程 B 就阻塞等待;
  • 接着,当进程 A 生产完数据后,执行了 V 操作,就会使得信号量变为 0,于是就会唤醒阻塞在 P 操作的进程 B;
  • 最后,进程 B 被唤醒后,意味着进程 A 已经生产了数据,于是进程 B 就可以正常读取数据了。

可以发现,信号初始化为 0 ,就代表着是同步信号量,它可以保证进程 A 应在进程 B 之前执行。

信号

上面说的进程间通信,都是常规状态下的工作模式。对于异常情况下的工作模式,就需要用「信号」的方式来通知进程。

信号跟信号量虽然名字相似度 66.66%,但两者用途完全不一样,就好像 Java 和 JavaScript 的区别。

在 Linux 操作系统中, 为了响应各种各样的事件,提供了几十种信号,分别代表不同的意义。我们可以通过 kill -l 命令,查看所有的信号:


运行在 shell 终端的进程,我们可以通过键盘输入某些组合键的时候,给进程发送信号。

  • Ctrl+C 产生 SIGINT 信号,表示终止该进程;
  • Ctrl+Z 产生 SIGTSTP 信号,表示停止该进程,但还未结束;

如果进程在后台运行,可以通过 kill 命令的方式给进程发送信号,但前提需要知道运行中的进程 PID号,例如:

  • kill -9 1050 表示给 PID 为 1050 的进程发送 SIGKILL 信号,⽤来立即结束该进程;

所以,信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令)。

信号是进程间通信机制中唯一的异步通信机制,因为可以在任何时候发送信号给某一进程,一旦有信号产生,我们就有下面这几种,用户进程对信号的处理方式。

1. 执行默认操作。Linux 对每种信号都规定了默认操作,例如,上面列表中的 SIGTERM 信号,就是终止进程的意思。

2. 捕捉信号。我们可以为信号定义一个信号处理函数。当信号发生时,我们就执行相应的信号处理函数。

3. 忽略信号。当我们不希望处理某些信号的时候,就可以忽略该信号,不做任何处理。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILLSEGSTOP ,它们用于在任何时候中断或结束某一进程。

五、socket

前面提到的管道、消息队列、共享内存、信号量和信号都是在同一台主机上进行进程间通信,那要想跨网络络与不同主机上的进程之间通信,就需要 Socket 通信了。

实际上,Socket 通信不仅可以跨网络与不同主机的进程间通信,还可以在同主机上进程间通信。

创建 socket 的系统调用:

int socket(int domain, int type, int protocal)

三个参数分别代表:

  • domain 参数用来指定协议族,比如 AF_INET 用于 IPV4、AF_INET6 用于 IPV6、AF_LOCAL/AF_UNIX 用于本机;
  • type 参数用来指定通信特性,比如 SOCK_STREAM 表示的是字节流,对应 TCP、SOCK_DGRAM表示的是数据报,对应 UDP、SOCK_RAW 表示的是原始套接字;
  • protocal 参数原本是用来指定通信协议的,但现在基本废弃。因为协议已经通过前面两个参数指定完成,protocol 目前一般写成 0 即可;

根据创建 socket 类型的不同,通信的方式也就不同:

  • 实现 TCP 字节流通信: socket 类型是 AF_INETSOCK_STREAM
  • 实现 UDP 数据报通信:socket 类型是 AF_INETSOCK_DGRAM
  • 实现本地进程间通信: 「本地字节流 socket 」类型是 AF_LOCALSOCK_STREAM,「本地数据报 socket 」类型是 AF_LOCALSOCK_DGRAM。另外,AF_UNIX 和 AF_LOCAL 是等价的,所以AF_UNIX 也属于本地 socket;

1. 针对 TCP 协议通信的 socket 编程模型

  • 服务端和客户端初始化 socket ,得到文件描述符;

  • 服务端调用 bind ,将绑定在 IP 地址和端口;

  • 服务端调用 listen ,进行监听;

  • 服务端调用 accept ,等待客户端连接;

  • 客户端调用 connect ,向服务器端的地址和端口发起连接请求;

  • 服务端 accept 返回用 于传输的 socket 的文件描述符;

  • 客户端调用 write 写入数据;服务端调用 read 读取数据;

  • 客户端断开连接时,会调用 close ,那么服务端 read 读取数据的时候,就会读取到了 EOF ,待处理完数据后,服务端调用 close ,表示连接关闭。

  这里需要注意的是,服务端调用 accept 时,连接成功了会返回一个已完成连接的 socket的网络描述符,后续用来传输数据。所以,监听的 socket 和真正用来传送数据的 socket,是两个不同的socket,一个是服务器的网络描述符,一个是客户端的网络描述符,其具体程序设计参考如下所示:


成功连接建立之后,双方开始通过 readwrite 函数来读写数据,就像往一个文件流里面写东西一样。

2. 针对 UDP 协议通信的 socket 编程模型

  • UDP 是没有连接的,所以不需要三次握手,也就不需要像 TCP 调用 listen 和 connect,但是 UDP 的交互仍然需要 IP 地址和端口,因此也需要 bind

  • 对于 UDP 来说,不需要要维护连接,那么也就没有所谓的发送方和接收方,甚至都不存在客户端和服务端的概念,只要有一个 socket 多台机器就可以任意通信,因此每⼀个 UDP 的 socket 都需要 bind。

  • 另外,每次通信时,调用 sendtorecvfrom,都要传入目标主机的 IP 地址和端口。

3. 针对本地进程间通信的 socket 编程模型

本地 socket 被用于在同一台主机上进程间通信的场景:

  • 本地 socket 的编程接⼝和 IPv4 、IPv6 套接字编程接⼝是⼀致的,可以支持「字节流」和「数据报」两种协议;

  • 本地 socket 的实现效率大大高于 IPv4 和 IPv6 的字节流、数据报 socket 实现;

  • 对于本地字节流 socket,其 socket 类型是 AF_LOCALSOCK_STREAM

  • 对于本地数据报 socket,其 socket 类型是 AF_LOCALSOCK_DGRAM

  本地字节流 socket 和 本地数据报 socket 在 bind 的时候,不像 TCP 和 UDP 要绑定 IP 地址和端口,而是绑定一个本地文件,这也就是它们之间的最大区别。

总结

由于每个进程的用户空间都是独立的,不能相互访问,这时就需要借助内核空间来实现进程间通信,原因很简单,每个进程都是共享一个内核空间。

Linux 内核提供了不少进程间通信的方式,其中最简单的方式就是管道,管道分为「匿名管道」和「命名管道」。

1. 匿名管道:顾名思义,它没有名字标识。

  • 匿名管道是特殊文件只存在于内存,没有存在于文件系统中
  • shell命令中的「 | 」竖线就是匿名管道,通信的数据是无格式的流并且大小受限
  • 通信的方式是单向的,数据只能在一个方向上流动,如果要双向通信,需要创建两个管道
  • 再来匿名管道是只能用于存在父子关系的进程间通信
  • 匿名管道的生命周期随着进程创建而建立,随着进程终止而消失。

2. 命名管道 突破了匿名管道只能在亲缘关系进程间的通信限制,因为使用命名管道的前提,需要在文件系统创建一个类型为 p 的设备文件,那么毫无关系的进程就可以通过这个设备文件进程通信。

  • 不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取
  • 同时通信数据都遵循先进先出原则,不支持 lseek 之类的文件定位操作。

3. 消息队列 克服了管道通信的数据是无格式的字节流的问题,消息队列实际上是保存在内核的「消息链表」,消息队列的消息体是可以用户自定义的数据类型,发送数据时,会被分成一个一个独立的消息体,当然接收数据时,也要与发送方发送的消息体的数据类型保持一致,这样才能保证读取的数据是正确的。但消息队列通信的速度不是最及时的,并且数据块也有一定的大小限制毕竟每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。

4. 共享内存 可以解决消息队列通信中用户态与内核态之间数据拷贝过程带来的开销

  • 它直接分配一个共享空间,每个进程都可以直接访问 ,就像访问进程自己的空间一样快捷方便,不需要陷入内核态或者系统调用,大大提高了通信的速度,享有最快的进程间通信方式之名。
  • 但是便捷高效的共享内存通信,带来新的问题,多进程竞争同个共享资源会造成数据的错乱。

5. 信号量 解决了共享资源造成的数据错乱

  • 做到了对共享资源的保护,以确保任何时刻只能有一个进程访问共享资源 ,这种方式就是互斥访问。
  • 信号量不仅可以实现访问的互斥性,还可以实现进程间的同步
  • 信号量其实是一个计数器,表示的是资源个数,其值可以通过两个原子操作来控制,分别是 P 操作和 V 操作

6. 信号 虽然与信号量名字十分相似,但功能一点儿都不⼀样。

  • 信号是进程间通信机制中唯一的异步通信机制,信号可以在应用进程和内核之间直接交互,内核也可以利用信号来通知用户空间的进程发生了哪些系统事件
  • 信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令)
  • 一旦有信号生,进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。
  • 有两个信号是应用进程无法捕捉和忽略的,即 SIGKILLSEGSTOP ,这是为了方便我们能在任何时候结束或停止某个进程。

7. 前面说到的通信机制,都是工作于同一台主机,如果要与不同主机的进程间通信,那么就需要 Socket 通信了 。Socket 实际上不仅用于不同的主机进程间通信,还可以用于本地主机进程间通信。可根据创建Socket 的类型不同,分为三种常见的通信方式,一个是基于TCP 协议的通信方式,一个是基于 UDP 协议的通信方式,一个是本地进程间通信方式。

以上,就是进程间通信的主要机制了

整理自【清华大学】操作系统 + 【小林Coding】图解系统
参考博文:进程间的五种通信方式介绍

相关文章:

【操作系统】进程间通信方式

进程间通信方式 前言 / 概述一、管道管道命名管道 二、消息队列三、共享内存四、信号量信号量概述互斥访问条件同步信号 五、socket总结 前言 / 概述 每个进程的用户地址空间都是独立的&#xff0c;⼀般而言是不能互相访问的&#xff0c;但内核空间是每个进程都共享的&#xff…...

Flutter 打包 ipa出现错误问题 exportArchive

一、错误信息: Encountered error while creating the IPA: error: exportArchive: "Runner.app" requires a provisioning profile with the Push Notifications feature. Try distributing the app in Xcode: open /project/your_app/build/ios/archive/Runner.…...

Ubutu20.04安装docker与docker-compose

系统&#xff1a;20.04.6 LTS (Focal Fossa)" 1.配置apt源(在/etc/apt/sources.list中输入以下内容) # deb cdrom:[Ubuntu 20.04.6 LTS _Focal Fossa_ - Release amd64 (20230316)]/ focal main restricted deb http://mirrors.aliyun.com/ubuntu/ focal main restricted …...

Java 反射机制

Java 反射机制 Java 反射机制1. 反射机制简介2. 反射的核心类3. 反射的基本步骤3.1 加载类&#xff0c;获取类的字节码&#xff1a;Class 对象3.2 获取类的构造器&#xff1a;Constructor 对象3.3 获取类的成员变量&#xff1a;Field 对象3.4 获取类的成员方法&#xff1a;Meth…...

前端流式输出实现详解:从原理到实践

前端流式输出实现详解&#xff1a;从原理到实践 前言一、流式输出核心原理1.1 什么是流式输出&#xff1f;1.2 技术优势对比1.3 关键技术支撑 二、原生JavaScript实现方案2.1 使用Fetch API流式处理关键点解析&#xff1a; 2.2 处理SSE&#xff08;Server-Sent Events&#xff…...

CTF题目《easy_tornado》(护网杯 2018)Write Up

题目背景与信息收集 初始访问 题目提供三个文件链接&#xff1a; /flag.txt&#xff1a;提示flag位于/fllllllllllllag文件/welcome.txt&#xff1a;关键词render&#xff0c;暗示模板渲染漏洞&#xff08;SSTI&#xff09;/hints.txt&#xff1a;提示签名算法md5(cookie_secre…...

暗光增强技术研究进展与产品落地综合分析(2023-2025)

一、引言 暗光增强技术作为计算机视觉与移动影像领域的核心研究方向之一,近年来在算法创新、硬件适配及产品落地方面取得了显著进展。本文从技术研究与产业应用两个维度,系统梳理近三年(2023-2025)该领域的关键突破,并对比分析主流手机厂商的影像技术优劣势。 二、暗光增…...

CAM350-14.6学习笔记-1:导入Gerber文件

CAM350-14.6学习笔记-1:导入Gerber文件 使用自动导入器导入Gerber1&#xff1a;导航栏Home下面的Import——Automatic Import——选择文件路径——Next2&#xff1a;设置每层的类型&#xff1a;3&#xff1a;设置叠层4&#xff1a;弹出层别显示框及Gerber显示 按照Allegro输出的…...

【Zephyr】【二】学习笔记【RTOS系统架构】

Zephyr RTOS 系统架构 整体架构 #mermaid-svg-MENZa2zm9JlGktYP {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-MENZa2zm9JlGktYP .error-icon{fill:#552222;}#mermaid-svg-MENZa2zm9JlGktYP .error-text{fill:#55…...

Web-Machine-N7靶机通关攻略

获取靶机ip arp-scan -l 端口扫描 nmap xxxx 访问80端口发现没用 扫描目录 gobuster dir -u http:/192.168.117.160 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium,txt -x php,html,txt ,zip 打开exploit.html 点击F12&#xff0c;修改localhost为靶机ip&#…...

CSS 用于图片的样式属性

CSS 设置图像样式 CSS中用于图片的样式属性主要包括以下几个方面&#xff1a; ‌边框和背景‌&#xff1a; ‌border‌&#xff1a;可以设置图片的边框样式、宽度和颜色。例如&#xff0c;img { border: 1px solid #ddd; } 会给图片添加1像素的实线边框&#xff0c;颜色为灰色…...

【工具分享】vscode+deepseek的接入与使用

目录 第一章 前言 第二章 获取Deepseek APIKEY 2.1 登录与充值 2.2 创建API key 第三章 vscode接入deepseek并使用 3.1 vscode接入deepseek 3.2 vscode使用deepseek 第一章 前言 deepseek刚出来时有一段时间余额无法充值&#xff0c;导致小编没法给大家发完整的流程&…...

《Java核心三问:字符串、equals()、hashCode()的隐藏雷区与完美避坑手册》

目录 一.String、StringBuffer、StringBuilder的区别&#xff1f;1. 核心区别总结2. 具体实例演示示例1&#xff1a;不可变性 vs 可变性示例2&#xff1a;线程安全验证 2. 线程安全的关键&#xff1a;synchronized3. 对比StringBuilder的非线程安全4. 可视化执行流程5. 进一步验…...

【Java】TCP网络编程:从可靠传输到Socket实战

活动发起人小虚竹 想对你说&#xff1a; 这是一个以写作博客为目的的创作活动&#xff0c;旨在鼓励大学生博主们挖掘自己的创作潜能&#xff0c;展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴&#xff0c;那么&#xff0c;快来参加吧&#xff01…...

背包问题——多重背包(C语言)

代码如下&#xff1a; #include<stdio.h>int knapsack(int weight[], int value[], int count[], int n, int capacity) {int* dp (int*)malloc(sizeof(int) * (capacity 1));for (int i 0; i < capacity; i){dp[i] 0;}for (int i 0; i < n; i)//核心代码{fo…...

微服务》》Kubernetes (K8S) 集群配置网络》》Calico

嘻嘻嘻 以Calico 为例子 Calico官网 官网上有安装Calico插件的步骤 步骤 要在主节点 主节点 主节点 执行 kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml kubectl get pod --all-namespaces kubec…...

寄存器(内部访问)

内存中字的储存 我们之前提到过&#xff0c;字由两个字节组成&#xff0c;当我们用16位寄存器来储存时&#xff0c;把字分别储存在连续的两个内存单元中&#xff0c;高位字节放在高地址单元中&#xff0c;低位字节则放在低位地址单元中。 例如上图&#xff0c;0、1两个单元存放…...

Vue2 watch侦听器(监听器)

watch侦听器&#xff08;监听器&#xff09;功能是监听数据变化&#xff0c;执行一些业务逻辑 或 异步操作。 核心选项 ‌handler‌ 监听函数&#xff0c;接收 (newVal, oldVal) 作为参数。‌deep: true 深度监听对象/数组内部变化。‌immediate: true‌ 在组件创建时…...

【PCB工艺】基础:电子元器件

电子原理图&#xff08;Schematic Diagram&#xff09;是电路设计的基础&#xff0c;理解电子元器件和集成电路&#xff08;IC&#xff09;的作用&#xff0c;是画好原理图的关键。 本专栏将系统讲解 电子元器件分类、常见 IC、电路设计技巧&#xff0c;帮助你快速掌握电子电路…...

linux性能监控的分布式集群 prometheus + grafana 监控体系搭建

prometheusgrafana分布式集群资源监控体系搭建 前言一、安装 prometheus二、在要监控的服务器上安装监听器三、prometheus服务器配置四、grafana配置大屏五、创建Linux监控看板五、监控windows服务器注意事项 前言 Prometheus 是一个开源的 ​分布式监控系统 和 ​时间序列数据…...

Ubuntu AX200 iwlwifi-cc-46.3cfab8da.0.tgz无法下载的解决办法

文章目录 前言一、检查网卡是否被识别二、确认内核模块是否可用1.AX200 wifi 要求内核5.12.检查 iwlwifi.ko 是否存在&#xff1a;3.如果未找到&#xff0c;可能是内核模块未正确生成。尝试安装 linux-modules-extra&#xff1a;4.再次检查 iwlwifi.ko 是否存在&#xff1a;5.确…...

LinkedList与链表

ArrayList的缺陷 在上一篇博客中&#xff0c;小编已经较为详细得给大家介绍了ArrayList这个结构了。但是ArrayList存在一些缺陷&#xff1a;由于其底层是一段连续空间&#xff0c;当在ArrayList任意位置插入或者删除元素时&#xff0c;就需要将后序元素整体往前或者往后搬移&am…...

CCF 编程能力认证 C++ 四级宝典

CCF编程能力等级认证&#xff08;以下简称GESP&#xff09;2025年四次认证时间分别为&#xff1a;3月22日、6月28日、9月27日、12月20日&#xff0c;认证方式为线下机考&#xff0c;认证语言包括&#xff1a;C、Python和Scratch三种语言&#xff0c;其中Scratch认证为一到四级&…...

信创系统极速文件查找:locate 命令详解

原文链接&#xff1a;信创系统极速文件查找&#xff1a;locate 命令详解 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇信创终端操作系统上 locate 命令详解的文章。在 Linux 及信创终端操作系统&#xff08;如 统信 UOS、麒麟 KOS&#xff09;中&#xff0c;查找…...

数据集获取

sklearn数据集 sklearn有四部分数据。其中sklearn的数据集有两部分真实的数据,一部分嵌入到了sklearn库中,即安装好sklearn后就自带了一部分数据,这些数据的规模比较小称为small toy datasets ,还有一部分数据是需要在网上下载的,sklearn提供了下载的api接口,这些数据规…...

三格电子PLC数据采集网关-工业互联的智能枢纽

在工业自动化领域&#xff0c;设备间的数据互通与协议兼容是核心挑战之一。三格电子推出的PLC据采集网关SG-PLC-Private&#xff0c;凭借其多协议兼容、高稳定性和灵活配置能力&#xff0c;成为工业物联网&#xff08;IIoT&#xff09;中实现设备互联的关键设备。本文将从产品功…...

【sgFloatDialog】自定义组件:浮动弹窗,支持修改尺寸、拖拽位置、最大化、还原、最小化、复位

sgFloatDialog <template><div :class"$options.name" v-if"visible" :size"size" :style"style"><!-- 托盘头部 --><div class"header" ref"header" dblclick.stop.prevent"dblclic…...

conda 常用命令

常用 Conda 命令整理环境管理 conda create --name 环境名 &#xff1a;创建新环境 conda activate 环境名 &#xff1a;激活环境 conda deactivate&#xff1a;退出环境 conda env list&#xff1a;列出所有环境 conda remove --name 环境名 --all &#xff1a;删除环…...

神聖的綫性代數速成例題10. N維矢量綫性運算、矢量由矢量組綫性表示、N個N維矢量相關性質

N 維矢量綫性運算&#xff1a; 設&#xff0c;是維矢量&#xff0c;是數。加法&#xff1a;。數乘&#xff1a;。 矢量由矢量組綫性表示&#xff1a; 設是n維矢量&#xff0c;若存在一組數&#xff0c;使得&#xff0c;則稱矢量可由矢量組綫性表示。 N 個 N 維矢量相關性質&…...

力扣977. 有序数组的平方(双指针技巧)

Problem: 977. 有序数组的平方 文章目录 题目描述思路Code 题目描述 思路 由于数组是非递减且包含正、负数&#xff0c;则假如我们将数组中的每一个元素取平方并且将其从原始的某一个位置分开成两个数组来看待&#xff08;一个数组从前往后看&#xff0c;一个数组从后往前看&am…...

单片机flash存储也做磨损均衡

最近在做一个项目&#xff0c;需要保存设置数据&#xff0c;掉电不丢失。那么首先想到的是加个24c02&#xff0c;是一个eeprom&#xff0c;但是客户板太小&#xff0c;没有办法进行扩展。后面就找了一个带ee的OTP单片机&#xff0c;发现擦写次数有限&#xff0c;只有1000次&…...

第7章 类与面向对象

6-1 二维平面上的点操作&#xff08;Python3&#xff09; 题目描述 设计一个表示二维平面上点的类 Point。该类应该包含以下功能&#xff1a; 两个私有属性 _x 和 _y&#xff0c;分别表示点的横坐标和纵坐标。 一个构造函数 __init__&#xff0c;用于初始化点的坐标。 一个…...

【算法】力扣 713题:乘积小于 K 的子数组之深入思考

文章目录 前言题目&#xff1a;乘积小于 K 的子数组参考思路方法一&#xff1a;滑动窗口方法二&#xff1a;二分查找 参考题解方法一&#xff1a;滑动窗口解法方法二&#xff1a;二分查找解法 深入思考浮点精度&#xff1f;right - left 1&#xff1f;二分法&#xff1f;哈希优…...

Milvus vs. ElasticSearch:向量库检索性能测试

目录 1. 构建检索库2. 测试条件3. 测试结果4. 性能分析5. 结论 1. 构建检索库 构建通用场景库总计约2万张。构建车辆数据库总计约12万张。构建公共数据库&#xff0c;包括Flickr30k、COCO、nlvr2、vqa等数据集约43万张。 2. 测试条件 环境说明&#xff1a;分别单机部署Milvu…...

高级数据结构应用:并查集、跳表、布隆过滤器与缓存结构

高级数据结构应用:并查集、跳表、布隆过滤器与缓存结构 在解决复杂问题时,选择合适的数据结构往往是成功的关键。本文将深入探讨四种强大而实用的高级数据结构:并查集、跳表、布隆过滤器和高效缓存结构(LRU和LFU),包括它们的原理、实现、复杂度分析和实际应用场景。 1.…...

CVPR2025 | 蚂蚁浙大提出MP-GUI算法:全方位增强MLLM的GUI理解能力

近日&#xff0c;计算机视觉和模式识别领域国际顶会CVPR 2025公布了论文录用结果&#xff0c;蚂蚁集团与浙江大学EAGLE实验室合作的论文 “MP-GUI: Modality Perception with MLLMs for GUI Understanding” 被成功录用。 IEEE国际计算机视觉与模式识别会议&#xff08;CVPR&a…...

过河卒cpp动态规划

题目如下 思路 利用二维数组存储棋盘的各个点的位置&#xff0c;首先初始化所有位置为0&#xff0c;然后记马的位置为1&#xff0c;将m&#xff0c;n同时加2&#xff0c;避免马的位置溢出&#xff0c;然后对二维数组进行递推算出dp[n][m] 代码及解析如下 谢谢观看&#xff01;…...

春天咋会像冬天一样

2025年3月20日&#xff0c;阴&#xff0c;天寒 遇见的事&#xff1a;21&#xff5e;24号去曲靖招生&#xff0c;打电话给我说换一下&#xff0c;换了后又没有车了&#xff0c;这么坑。 感受到的情绪&#xff1a;你知道么&#xff0c;换的前提是有车。开车不给报销&#xff0c;…...

DooTask在Linux的离线部署教程

DooTask在Linux的离线部署教程 下载安装包 从网盘中将安装包下载到本地&#xff0c;下载地址 通过网盘分享的文件&#xff1a;DooTask项目管理工具 链接: https://pan.baidu.com/s/1hGmLXonT4c8hLiDP1QBr8w?pwdgdp6 提取码: gdp6 通过网盘分享的文件&#xff1a;DooTask项目…...

分享下web3j 常见用法

转账 fun sendEthTransaction(privateKey: String,toAddress: String,amount: BigDecimal) {//chainIdval chainId:Long 1//url 可以从https://chainlist.org/里面获取可用节点//eth转账&#xff0c;bnb同理&#xff0c;但需发送到bnb对应节点val url "https://xxx"…...

跨域问题确认及处理

背景如下&#xff1a; 近期在做的项目中&#xff0c;有个奇怪的需求&#xff0c;需要在JSP项目中嵌套一个VUE项目&#xff0c;原因是&#xff1a;JSP项目是在运且不大方便重构的一个项目&#xff0c;新需求又想为了未来着想做一套单独的项目&#xff0c;无奈只能嵌套。 当项目开…...

PyCharm如何添加已有的conda环境

1、点击文件中的设置 2、在右侧选中项目下的Python解释器 3、在右侧解释器一栏找到添加解释器选项 4、选择本地解释器 5、填写信息 环境&#xff1a;选择现有 类型&#xff1a;conda conda路径&#xff1a;...\Anaconda\Scripts\conda.exe 环境&#xff08;python路径&…...

揭开最大子段和问题的神秘面纱:从暴力法到极致优化的算法之旅

最大子段和问题&#xff1a;从暴力法到优化的算法解析 题目链接 题目描述 给出一个长度为 nn 的序列 aa&#xff0c;选出其中连续且非空的一段使得这段和最大。 输入格式 第一行是一个整数&#xff0c;表示序列的长度 n。第二行有 n 个整数&#xff0c;第 i 个整数表示序列的…...

MySQL原理:逻辑架构

目的&#xff1a;了解 SQL执行流程 以及 MySQL 内部架构&#xff0c;每个零件具体负责做什么 理解整体架构分别有什么模块每个模块具体做什么 目录 1 服务器处理客户端请求 1.1 MySQL 服务器端逻辑架构说明 2 Connectors 3 第一层&#xff1a;连接层 3.1 数据库连接池(Conn…...

提升模型性能:数据增强与调优实战

‌一、为什么需要数据增强&#xff1f; 数据增强通过对训练图像进行‌随机变换‌&#xff0c;能够有效&#xff1a; 增加数据多样性&#xff0c;防止过拟合提升模型对不同视角、光照条件的鲁棒性在数据量不足时显著提升模型性能 二、MNIST手写数字识别实战‌ ‌1. 加载数据…...

Emacs 折腾日记(十八)——改变Emacs的样貌

截止到上一篇文章为止&#xff0c;之前教程 的内容都看完了&#xff0c;虽然它的后记部分提供了一些后续进阶的内容需要我们自己读手册。但是我不太想继续在elisp上死磕了。看着自己学了那么久的elisp&#xff0c;但是自己的emacs仍然没有半点改变&#xff0c;这个时候各位读者…...

VNA操作使用学习-14 再测晶振特性

再测一下4Mhz晶振&#xff0c;看看特性曲线&#xff0c;熟悉一下vna使用。 s11模式&#xff0c;找遍了各种format都无法显示&#xff0c;只有这一种&#xff08;s11&#xff0c;Resistance&#xff09;稍微显示出一个谐振&#xff0c;但是只有一个点。 s21模式 这是201p&#…...

CentOS7 离线下载安装 GitLab CE

依赖下载 https://vault.centos.org/7.9.2009/os/x86_64/Packages/policycoreutils-python-2.5-34.el7.x86_64.rpm 依赖安装 rpm -ivh policycoreutils-python-2.5-34.el7.x86_64.rpm 查看是否安装依赖 rpm -qa | grep policycoreutils-pythongitlab下载 https://packag…...

LeetCode 热题 100_跳跃游戏 II(79_45_中等_C++)(贪心算法)

LeetCode 热题 100_跳跃游戏 II&#xff08;79_45&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;贪心选择&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;贪心算法&#xff09;…...

《Linux系统编程篇》Linux Socket 网络编程01 API介绍(Linux 进程间通信(IPC))——基础篇

文章目录 引言1. **创建Socket**2. **绑定Socket**3. **监听Socket**4. **接受客户端连接**5. **连接服务器**6. **发送数据**7. **接收数据**8. **发送数据&#xff08;UDP&#xff09;**9. **接收数据&#xff08;UDP&#xff09;**10. **关闭Socket**11. **设置/获取Socket选…...