【Linux】进程通信——共享内存+消息队列+信号量

news2024/11/23 21:16:01

在这里插入图片描述

欢迎来到Cefler的博客😁
🕌博客主页:折纸花满衣
🏠个人专栏:题目解析
🌎推荐文章:【LeetCode】winter vacation training

在这里插入图片描述


目录

  • 👉🏻共享内存
  • 👉🏻关于共享内存的接口函数
  • 👉🏻ipcs命令
  • 👉🏻ipcrm命令
  • 👉🏻共享内存实现进程间通信代码示例
  • 👉🏻消息队列
    • 概念
    • 进程之间的消息队列通信
  • 👉🏻信号量
    • semget,semop,semctl
  • 👉🏻IPC

👉🏻共享内存

共享内存(Shared Memory)是一种进程间通信(IPC)的机制,用于在不同进程之间共享数据。

在共享内存中,多个进程可以将相同的内存区域映射到它们各自的地址空间中这意味着这些进程可以直接访问相同的物理内存位置,而无需进行复制或通过消息传递来传递数据。这种直接的内存共享方式使得进程间的数据交换更加高效和快速。

在使用共享内存进行进程间通信时,需要注意以下几点

  1. 同步机制:由于多个进程可以同时访问共享内存,因此需要使用同步机制(如信号量、互斥锁)来协调进程之间对共享内存的访问,避免数据冲突和竞争条件。
  2. 内存管理:共享内存需要由操作系统进行管理和分配。在创建共享内存时,需要申请足够的内存空间,并在使用完毕后及时释放,以防止资源泄漏。
  3. 数据一致性:由于多个进程可以同时访问共享内存,需要确保数据的一致性。可以使用同步机制来保证数据的正确读写顺序,或者通过采用特定的算法和协议来处理并发访问产生的冲突。
    在这里插入图片描述
    共享内存的优势在于它可以实现高效的数据共享,避免了进程间频繁的数据拷贝;同时,由于数据直接存储在物理内存中,共享内存的访问速度也比其他进程间通信方式更快。
    共享内存就是在物理内中开辟好内存空间,将地址映射到页表中,再映射到进程地址空间中。

共享内存比管道通信快的原因主要有以下几个方面

  1. 数据传输方式:在共享内存中,数据直接存储在物理内存中,不需要经过内核空间,进程可以直接读写内存,因此速度较快。而在管道通信中,数据需要在内核空间和用户空间之间进行来回拷贝,增加了额外的开销和延迟。

  2. 数据复制次数:在共享内存中,数据只需要被复制到共享内存区域一次,之后各个进程可以直接访问这块内存,而在管道通信中,每次数据传输都需要进行一次复制,这增加了额外的开销。

  3. 同步机制开销:在管道通信中,由于数据传输是基于文件描述符的读写操作,需要使用系统调用来进行读写和同步,而共享内存的访问是直接基于内存地址的,避免了频繁的系统调用,因此同步机制的开销较小。

👉🏻关于共享内存的接口函数

共享内存是一种高效的进程间通信方式,Linux系统提供了一系列函数用于进行共享内存的创建、映射、卸载和控制。下面分别介绍这些函数的作用:

  1. shmget函数

shmget函数用于创建或打开一个共享内存段。它的原型为:

#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

其中,参数key是一个键值,用于标识共享内存段,size是共享内存段的大小,shmflg是一个位掩码,用于指定创建共享内存段时的权限和选项。函数返回值是一个共享内存的标识符,如果出错则返回-1。

🌛 以下是shmflg的选项:
shmflg是在使用System V共享内存函数时用于设置标志的参数。它是一个整数值,可以通过按位或(|)运算将多个选项组合在一起。

  1. IPC_CREAT:如果指定此选项,当共享内存不存在时将创建一个新的共享内存对象。如果共享内存已经存在,则忽略该选项。通常与IPC_EXCL选项结合使用。
  2. IPC_EXCL:如果指定此选项,只有在共享内存不存在时才创建新的共享内存对象(保证返回的共享内存内容一定是全新的)。如果共享内存已经存在,则返回错误。通常与IPC_CREAT选项结合使用
  3. SHM_RDONLY:以只读模式打开共享内存对象,只能读取共享内存中的数据,不能修改。
  4. SHM_RSHM_WSHM_RW:表示共享内存的权限。SHM_R表示只读权限,SHM_W表示可写权限,SHM_RW表示可读可写权限。
  5. SHM_LOCKSHM_UNLOCK:用于对共享内存进行锁定和解锁操作。锁定共享内存可以防止其被交换到磁盘上,提高访问效率。
  6. SHM_HUGETLB:使用大页面分配共享内存,可以提高性能和效率。

2 shmat函数

shmat函数用于将共享内存段映射到进程的地址空间中。它的原型为:

#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);

其中,参数shmid是共享内存的标识符,shmaddr是指定的映射地址,如果为NULL,则由系统自动分配一个地址;shmflg是一个位掩码,用于指定映射共享内存时的选项。函数返回值是映射后的共享内存地址,如果出错则返回-1

  1. shmdt函数

shmdt函数用于将共享内存段从进程的地址空间中卸载。它的原型为:

#include <sys/shm.h>

int shmdt(const void *shmaddr);

其中,参数shmaddr是共享内存的地址,即shmat函数的返回值。函数返回值为0表示成功,如果出错则返回-1。

  1. shmctl函数

shmctl函数用于对共享内存进行控制操作,例如删除共享内存段等。它的原型为:

#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

其中,参数shmid是共享内存的标识符,cmd是一个命令码,用于指定要执行的操作,buf是一个指向共享内存信息结构体的指针,用于传递相关参数和返回信息。函数返回值为0表示成功,如果出错则返回-1。

🌛 其中cmd参数表示要执行的操作类型,具体选项如下

  • IPC_STAT:获取共享内存的状态信息,并将其写入到共享内存区域的shmid_ds结构中。
  • IPC_SET:设置共享内存的状态信息,使用shmid_ds结构中的值对共享内存进行更新。
  • IPC_RMID:删除共享内存标识符所代表的共享内存段。如果在删除之前有进程仍然附加到该共享内存段,则它不会被删除,直到最后一个进程离开后才会被删除。
  • SHM_LOCK:锁定共享内存区域,防止被交换到磁盘上。
  • SHM_UNLOCK:解锁共享内存区域。
  • SHM_STAT:获取共享内存的状态信息,并将其写入到共享内存区域的shmid_ds结构中。与IPC_STAT功能相同。
  • SHM_INFO:获取系统中共享内存的统计信息,并将其写入到shminfo结构中。
  • SHM_STAT_ANY:与SHM_STAT功能相同,但不需要对共享内存区域具有所有者或创建者权限。

这些选项可用于对共享内存进行各种操作,例如获取共享内存的状态信息、设置共享内存的状态信息、删除共享内存、锁定共享内存区域等。具体使用哪个选项取决于需要执行的操作类型。

5.fotk函数
ftok函数是一个用于生成System V IPC(Inter-Process Communication,进程间通信)中的键值的函数。它的原型为:

key_t ftok(const char *pathname, int proj_id);

该函数接受一个路径名和一个项目ID作为参数,并返回一个用于标识System V IPC资源的键值

路径名指定了一个现有的文件的路径,通常选择一个存在于文件系统中的文件。该文件用于关联一个唯一的键值,以便不同进程可以通过该键值来访问同一个System V IPC资源。如果路径名对应的文件不存在或不可访问,ftok函数将返回-1。

项目ID是一个用户定义的整数,用于进一步区分不同的System V IPC资源。在使用ftok函数时,应确保不同的资源具有不同的项目ID,以避免冲突。

ftok函数根据路径名和项目ID计算出一个32位的键值,并返回该键值。该键值可用于创建共享内存、消息队列和信号量等System V IPC对象。

👉🏻ipcs命令

ipcs命令是用于查看和管理System V IPC(Inter-Process Communication,进程间通信)对象的工具。它可以列出系统中当前存在的共享内存、消息队列和信号量等IPC对象的信息。

ipcs命令的基本语法如下:

ipcs [options]

常用的选项包括:

  • -m:列出所有共享内存对象的信息。
  • -q:列出所有消息队列的信息。
  • -s:列出所有信号量的信息。
  • -a:列出所有IPC对象(共享内存、消息队列和信号量)的信息。
  • -p:显示与每个IPC对象关联的进程ID和进程所有者的信息。
  • -l:显示System V IPC的限制和参数信息。

ipcs命令输出的信息包括对象的ID、键值、所有者、权限、大小等。通过查看ipcs的输出,可以了解系统中当前存在的IPC对象的状态、使用情况和其他相关信息。

对于管理员或有足够权限的用户,ipcs命令还可以用于删除或清理无用的IPC对象。例如,可以使用ipcrm命令结合ipcs的输出来删除某个特定的IPC对象。

👉🏻ipcrm命令

ipcrm命令用于删除System V IPC(Inter-Process Communication,进程间通信)对象,包括共享内存、消息队列和信号量等。

ipcrm命令的基本语法如下:

ipcrm [options] <shmid>

其中,<shmid>是要删除的IPC对象的标识符。标识符可以是IPC对象的ID、键值或名称,具体取决于IPC对象的类型。

常用的选项包括:

  • -m <id>:删除指定ID的共享内存对象。
  • -q <id>:删除指定ID的消息队列。
  • -s <id>:删除指定ID的信号量。

需要注意的是,使用ipcrm命令删除IPC对象需要具有足够的权限。通常只有管理员或创建IPC对象的用户才能删除它们。

在使用ipcs命令查看IPC对象信息后,可以得到IPC对象的ID,然后使用ipcrm命令删除指定的IPC对象。例如,通过以下命令可以删除一个共享内存对象:

ipcrm -m <ID>

请注意,在删除IPC对象之前,请确保没有进程正在使用该对象,否则可能会导致意外行为或数据丢失。

👉🏻共享内存实现进程间通信代码示例

以下是一个使用C++语言实现的简单进程间通信的例子,使用共享内存:

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>

#define SHM_SIZE 1024  // 共享内存大小

int main() {
    int shmid;
    char *shmaddr;
    key_t key = ftok(".", 'a');  // 生成key值

    // 创建共享内存
    if ((shmid = shmget(key, SHM_SIZE, IPC_CREAT|0666)) == -1) {
        perror("shmget error");
        exit(1);
    }

    // 将共享内存映射到进程地址空间
    if ((shmaddr = (char *)shmat(shmid, NULL, 0)) == (char *)-1) {
        perror("shmat error");
        exit(1);
    }

    // 写入数据到共享内存
    std::string message = "Hello, shared memory!";
    strncpy(shmaddr, message.c_str(), SHM_SIZE);

    // 创建子进程
    pid_t pid = fork();

    if (pid < 0) {  // fork失败
        perror("fork error");
        exit(1);
    } else if (pid == 0) {  // 子进程
        // 从共享内存中读取数据
        std::cout << "Child get message: " << shmaddr << std::endl;

        // 解除共享内存映射
        if (shmdt(shmaddr) == -1) {
            perror("shmdt error");
            exit(1);
        }
    } else {  // 父进程
        // 等待子进程结束
        wait(NULL);

        // 解除共享内存映射
        if (shmdt(shmaddr) == -1) {
            perror("shmdt error");
            exit(1);
        }

        // 删除共享内存
        if (shmctl(shmid, IPC_RMID, NULL) == -1) {
            perror("shmctl error");
            exit(1);
        }
    }

    return 0;
}

👉🏻消息队列

概念

消息队列是一种在分布式系统中常用的通信模式,它允许应用程序之间通过异步方式传递消息。简单来说,消息队列就是一个存储消息的容器,生产者将消息发送到队列中,而消费者则从队列中获取消息进行处理。

消息队列的设计基于生产者-消费者模型。生产者负责产生消息并将其发送到队列中,而消费者则从队列中读取消息并进行相应的处理。这种模型解耦了消息的发送方和接收方,使得系统更加灵活、可扩展和可靠。

使用消息队列有多个优点。首先,它实现了异步通信,生产者和消费者之间不需要实时交互,可以独立进行处理。这对于处理高并发和处理延迟敏感任务非常有帮助。

其次,消息队列提供了解耦的能力。生产者只需将消息发送到队列中,而不需要关心具体的消费者是谁以及何时处理消息。消费者可以根据自己的需求从队列中获取消息,并且可以根据处理速度调整消费的速率

此外,消息队列还具备削峰填谷的功能。当系统面临突发的请求压力时,消息队列可以缓冲请求,并根据系统的处理能力逐渐消化积压的消息,避免系统过载。

常见的消息队列系统有 RabbitMQ、Apache Kafka、ActiveMQ 等。它们提供了丰富的功能和灵活的配置选项,可以根据不同的场景选择合适的消息队列系统。

总结起来,消息队列是一种重要的分布式通信机制,通过解耦、异步和削峰填谷等特性,它能够帮助构建高性能、可扩展和可靠的系统。在现代应用开发中,消息队列被广泛应用于日志处理、任务调度、实时消息推送等各种场景。

进程之间的消息队列通信

在进程之间,可以使用消息队列实现通信。每个进程都可以创建一个或多个消息队列,用来存放发送和接收的消息。

在 Linux 系统中,系统调用 msgget() 可以用来创建或获取一个消息队列的标识符。创建消息队列时需要指定一些参数,如消息队列的权限、大小等。创建完成后,进程可以使用 msgsnd() 向消息队列中添加消息,使用 msgrcv() 从消息队列中读取消息。

在发送消息时,需要指定消息类型、消息正文和消息长度。消息类型是一个正整数,用于区分不同的消息。当接收消息时,也需要指定要接收的消息类型。如果消息队列中有匹配的消息,则将其从队列中删除并返回给接收进程。

使用消息队列进行进程间通信的好处是它允许异步通信,并且可以通过消息队列来解耦发送方和接收方的耦合关系。同时,由于消息队列是基于内核实现的,因此可以跨越不同的进程,甚至可以跨越不同的机器。

但是使用消息队列进行进程间通信也存在一些问题。例如,消息队列的容量有限,如果消息队列已满,则无法再向其中添加消息。此外,消息队列的消息类型只能是正整数,这种限制可能无法满足某些特定的需求。


🍬msgget
msgget 是一个系统调用函数,用于创建一个消息队列或获取一个已存在的消息队列的标识符。

函数原型如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);

参数说明:

  • key:消息队列的键值,可以使用 ftok() 函数生成。这个键值在系统中必须是唯一的,不同进程通过相同的键值可以访问同一个消息队列。
  • msgflg:消息队列的标志位,用于指定消息队列的创建和访问权限。常见的标志位包括 IPC_CREAT(创建消息队列)和 IPC_EXCL(与 IPC_CREAT 配合使用,如果消息队列已经存在则报错)。

返回值:

  • 成功时,返回消息队列的标识符(非负整数),可以用于后续操作;
  • 失败时,返回 -1,并设置 errno 错误码。

以下是一个示例代码,演示如何使用 msgget 创建或获取一个消息队列:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int main() {
    key_t key;
    int msgid;

    // 生成一个消息队列的键值
    key = ftok("path/to/a/file", 'A');
    if (key == -1) {
        perror("ftok");
        exit(1);
    }

    // 创建或获取消息队列
    msgid = msgget(key, IPC_CREAT | 0666);
    if (msgid == -1) {
        perror("msgget");
        exit(1);
    }

    printf("Message queue created or obtained with ID: %d\n", msgid);

    return 0;
}

在上述示例中,我们通过 ftok() 函数生成一个键值,该键值与指定的文件路径和标识字符 ‘A’ 相关联。然后使用 msgget 创建或获取一个消息队列,并将其标识符存储在 msgid 变量中。最后,打印出消息队列的标识符。

需要注意的是,在实际应用中,需要确保不同进程使用相同的键值来创建或获取同一个消息队列

👉🏻信号量

信号量是一种用于进程间同步和互斥的机制。它主要用于解决多个进程或线程之间共享资源的并发访问问题。

由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种
关系为进程的互斥

信号量的基本原理是在共享资源上设置一个计数器用于记录可用资源的数量。当进程需要使用共享资源时,首先检查信号量的计数器。如果计数器大于零,则表示有可用的资源,进程可以继续执行并将计数器减一。如果计数器为零,则表示没有可用的资源,进程需要等待,直到其他进程释放资源并增加计数器。

在 Linux 系统中,信号量通常使用 semget()semop()semctl() 等系统调用函数来创建、操作和控制。

  • semget():用于创建或获取一个信号量集的标识符。
  • semop():用于对信号量进行操作,如增加、减少等。
  • semctl():用于控制信号量,如获取当前计数器的值、设置计数器的值、删除信号量等。

信号量的操作主要包括 P 操作(等待信号量)和 V 操作(释放信号量):

  • P 操作(等待信号量):如果信号量的计数器大于零,则将计数器减一,进程继续执行;否则,进程进入等待状态。
  • V 操作(释放信号量):将信号量的计数器加一,唤醒等待该信号量的其他进程。

通过合理地使用 P 操作和 V 操作,可以实现对共享资源的互斥访问和进程间的同步。

以下是一个示例代码,演示如何使用信号量进行进程间互斥访问:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define SEM_KEY 1234

void P(int semid) {
    struct sembuf sb;
    sb.sem_num = 0;  // 信号量集中的第一个信号量
    sb.sem_op = -1;  // 执行 P 操作
    sb.sem_flg = 0;
    semop(semid, &sb, 1);
}

void V(int semid) {
    struct sembuf sb;
    sb.sem_num = 0;  // 信号量集中的第一个信号量
    sb.sem_op = 1;  // 执行 V 操作
    sb.sem_flg = 0;
    semop(semid, &sb, 1);
}

int main() {
    key_t key;
    int semid;

    // 创建或获取信号量集的标识符
    key = ftok("path/to/a/file", SEM_KEY);
    if (key == -1) {
        perror("ftok");
        exit(1);
    }
    semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1) {
        perror("semget");
        exit(1);
    }

    // 对信号量进行操作
    P(semid);  // 进入临界区,执行互斥操作
    printf("Critical section\n");
    V(semid);  // 离开临界区,释放资源

    // 删除信号量集
    semctl(semid, 0, IPC_RMID);

    return 0;
}

semget,semop,semctl

semget、semop和semctl是Linux系统中用于控制信号量的三个关键函数。

  1. semget:该函数用于创建或获取一个信号量集。其原型如下:

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    
    int semget(key_t key, int nsems, int semflg);
    
    • key:用于标识信号量集的键值,通常通过ftok函数生成。
    • nsems:指定需要创建的信号量集中的信号量数量。
    • semflg:设置信号量集的访问权限和其他标志位。
  2. semop:该函数用于对信号量进行操作,例如等待信号量、释放信号量等。其原型如下:

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    
    int semop(int semid, struct sembuf *sops, size_t nsops);
    
    • semid:信号量集的标识符,由semget函数返回。
    • sops:指向一个sembuf结构体数组,每个sembuf结构体表示对一个信号量的操作。
    • nsops:指定sops数组中sembuf结构体的数量。
  3. semctl:该函数用于对信号量进行控制操作,例如获取信号量的值、设置信号量的值等。其原型如下:

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    
    int semctl(int semid, int semnum, int cmd, ...);
    
    • semid:信号量集的标识符,由semget函数返回。
    • semnum:指定操作的信号量在信号量集中的索引,一般为0表示第一个信号量。
    • cmd:指定要执行的控制命令。
    • …:可选参数,根据不同的控制命令可能需要提供额外参数。

这些函数允许进程间通过信号量进行同步与互斥操作,确保资源的正确共享和访问。通过semget函数创建或获取信号量集,使用semop函数进行信号量的操作,使用semctl函数进行信号量的控制。


🌍 semctl函数的cmd选项
semctl函数的cmd选项用于指定对信号量进行的控制命令。下面是一些常用的cmd选项:

  • IPC_RMID:删除信号量集。该命令将删除指定的信号量集以及相关的数据结构。

    semctl(semid, semnum, IPC_RMID);
    
  • SETVAL:设置信号量的值。该命令将指定的信号量设置为给定的值。

    union semun {
      int val;               // value for SETVAL
      struct semid_ds *buf;  // buffer for IPC_STAT, IPC_SET
      unsigned short *array; // array for GETALL, SETALL
      struct seminfo *__buf; // buffer for IPC_INFO (Linux-specific)
    };
    
    union semun arg;
    arg.val = 5; // 设置信号量的值为5
    semctl(semid, semnum, SETVAL, arg);
    
  • GETVAL:获取信号量的值。该命令将返回指定信号量的当前值。

    int value = semctl(semid, semnum, GETVAL);
    
  • SETALL:设置所有信号量的值。该命令将指定信号量集中所有信号量的值设置为给定的数组。

    unsigned short values[3] = {2, 4, 6};
    semctl(semid, 0, SETALL, values);
    
  • GETALL:获取所有信号量的值。该命令将返回指定信号量集中所有信号量的当前值。

    unsigned short values[3];
    semctl(semid, 0, GETALL, values);
    
  • IPC_STAT:获取信号量集的状态信息。该命令将返回一个semid_ds结构体,包含有关信号量集的详细信息。

    struct semid_ds buf;
    semctl(semid, 0, IPC_STAT, &buf);
    

👉🏻IPC

IPC(Inter-Process Communication)资源是指在操作系统中用于进程间通信的各种资源。它们是为了满足不同进程之间的信息交换、同步和互斥等需求而提供的机制和数据结构

常见的IPC资源包括:

  1. 信号量(Semaphore):用于多个进程或线程之间进行同步和互斥操作的计数器。

  2. 共享内存(Shared Memory):允许多个进程共享同一块物理内存区域,使得进程可以直接读写该内存区域,实现高效的数据交换。

  3. 消息队列(Message Queue):进程通过将消息发送到队列中,实现进程间的异步通信。

  4. 管道(Pipe):一种半双工的通信方式,可以在两个相关进程之间传输数据。

  5. 套接字(Socket):用于在网络中进行进程间通信的接口。

  6. 信号(Signal):用于通知进程发生了某个事件,例如中断信号、异常信号等。

这些IPC资源提供了不同的通信方式和机制,可以满足不同场景下进程间通信的需求。通过使用这些资源,进程可以进行数据的共享、同步操作、消息的传递以及事件的通知等,从而实现了进程间的有效交互和协作。


如上便是本期的所有内容了,如果喜欢并觉得有帮助的话,希望可以博个点赞+收藏+关注🌹🌹🌹❤️ 🧡 💛,学海无涯苦作舟,愿与君一起共勉成长

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

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

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

相关文章

亚马逊要怎么运营?亚马逊运营主要运营内容有哪些?

一个店铺的成长发展少不了运营&#xff0c;而店铺的运营必须要有相关运营经验&#xff0c;才能将店铺做好&#xff0c;近几年亚马逊电商平台在不断的发展&#xff0c;亚马逊的运营模式非常独特&#xff0c;它借助于多种技术解决方案来提供最佳的客户体验。那么亚马逊要怎么运营…

Java基础学习:System类和Static方法的实际使用

一、System类 1.在程序开发中&#xff0c;我们需要对这个运行的结果进行检验跟我们预判的结果是否一致&#xff0c;就会用到打印结果在控制台中显示出来使用到了System类。System类定义了一些和系统相关的属性和方法&#xff0c;它的属性和方法都是属于静态的&#xff0c;想使用…

备战蓝桥杯---数据结构与STL应用(入门4)

本专题主要是关于利用优先队列解决贪心选择上的“反悔”问题 话不多说&#xff0c;直接看题&#xff1a; 下面为分析&#xff1a; 很显然&#xff0c;我们在整体上以s[i]为基准&#xff0c;先把士兵按s[i]排好。然后&#xff0c;我们先求s[i]大的开始&#xff0c;即规定选人数…

事件驱动架构:使用Flask实现MinIO事件通知Webhooks

MinIO的事件通知可能一开始看起来并不激动人心&#xff0c;但一旦掌握了它们的力量&#xff0c;它们就能照亮您存储桶内的动态。事件通知是一个全面、高效的对象存储系统中的关键组件。Webhooks是我个人最喜欢的工具&#xff0c;用于与MinIO集成。它们在事件的世界中就像一把瑞…

三轴 MEMS 加速度传感器

一、功能概述 1.1 设备简介 本模块为了对电机、风机、水泵等旋转设备进行预测性运维而开发&#xff0c;只需一 个模块&#xff0c;就可以采集电机的 3 路振动加速度信号&#xff08;XYZ 轴&#xff09;和一路温度信号&#xff0c; 防护等级 IP67 &#xff0c;能够适应恶劣的工…

aspose-words基础功能演示

我们在Aspose.Words中使用术语“渲染”来描述将文档转换为文件格式或分页或具有页面概念的介质的过程。我们正在讨论将文档呈现为页面。下图显示了 Aspose.Words 中的渲染情况。 Aspose.Words 的渲染功能使您能够执行以下操作&#xff1a; 将文档或选定页面转换为 PDF、XPS、H…

C++ 单一附合导线平差程序

一、以下图附合导线为例&#xff0c;图形如下&#xff1a; 二、第一步&#xff0c;读取测量数据&#xff0c;读取界面设计如下&#xff1a; 读取数据文本文件格式如下&#xff1a; &#xff08;1&#xff09;已知点坐标数据格式&#xff1a; &#xff08;2&#xff09;角度观测…

中仕公考:公务员和事业单位哪个更难?

公务员有稳定的职位和福利待遇&#xff0c;一直是众多求职者的选择&#xff0c;事业单位招聘也吸引着大量求职者&#xff0c;许多人都在纠结于公务员和事业单位考试应该怎么选择。 先来看看公务员考试&#xff0c;公务员考试主要包括国家公务员考试和省级公务员考试。国家公务…

vue3动态循环引入本地静态图片资源

解决方法一 根据官网的提示&#xff0c;我找到了最简单的方法&#xff0c;就是在将asset 前面加上src。 解决方法二 关于第二个方法&#xff0c;官网说&#xff1a;“实际上&#xff0c;Vite 并不需要在开发阶段处理这些代码&#xff01;在生产构建时&#xff0c;Vite 才会进行…

Git命令窗口:创建一个.bashrc文件,别名实现git log (代替冗余的指令)查询提交修改日志功能

在我们的用户下创建一个.bashrc文件&#xff0c;然后添加如下代码。即可实现我们命令窗口由于每次想要看到好的效果而输入几条指令的问题。 这里我们就只需要使用 git-log 代替我们的git log。这样在命令窗口看到的效果就清晰明了。

在Android Studio中配置OpenCV

在Android Studio中配置OpenCV 1 下载OpenCV2 导入OpenCV模块3 修改配置4 增加依赖5 拷贝libopencv_java.so6 Activity中加入代码1 下载OpenCV 下载OpenCV的Android包并解压。 2 导入OpenCV模块 在Android应用中,导入OpenCV模块。 导入目录时选择Opencv Android中的sdk目…

铁轨语义分割(Unet结合resnet系列)

数据介绍 一类是图片&#xff0c;一类是图像标签。 引入库&#xff0c;处理数据 import torch.nn as nn import torch import torch.nn.functional as F import os from PIL import Image import torch from torch.utils.data import Dataset import torchvision.transfor…

分布式事务(二)—— CAP和Base理论

系列目录&#xff1a; 《分布式事务&#xff08;一&#xff09;—— 事务的基本概念》 一、CAP理论 cap理论是分布式系统的理论基石 1、Consistency[一致性] 即操作成功并返回客户端后&#xff0c;所有节点在同一时间的数据完全一致&#xff0c;这就是分布式的一致性。一致…

分享个前端工具-取色调色工具

这里虽然贴了两个&#xff0c;但推荐 Pipette. PipetteWin22.10.22.zip: https://download.csdn.net/download/rainyspring4540/88799632 图标&#xff1a; 界面&#xff1a; ColorPix https://download.csdn.net/download/rainyspring4540/88799642 图标&#xff1a; 界面…

在Windows11的WSL上运行Llama2-7b-chat 后记

往期的Llama2-7b-chat中我们试用了官方的demo&#xff0c;但是那个demo只能在代码中传入固定的对话&#xff0c;我稍微修改了一下&#xff0c;使其能在命令行中不间断对话&#xff08;不具备记忆功能&#xff09; 代码 import os import torch os.environ[PL_TORCH_DISTRIBUT…

基于 LLM+LlamaIndex+NebulaGraph,构建大模型知识图谱的检索(RAG)方法

最近&#xff0c;围绕着利用 LLM&#xff08;Language Model&#xff09;和知识图谱&#xff08;KG&#xff0c;Knowledge Graphs&#xff09;构建RAG&#xff08;Retrieval Augmented Generation&#xff09;流程引起了很多关注。 在本文中&#xff0c;让我们通过利用 LlamaI…

Linux部署DataEase数据分析工具并结合内网穿透实现任意设备远程查看数据

文章目录 前言1. 安装DataEase2. 本地访问测试3. 安装 cpolar内网穿透软件4. 配置DataEase公网访问地址5. 公网远程访问Data Ease6. 固定Data Ease公网地址 前言 DataEase 是开源的数据可视化分析工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务…

DolphinScheduler管理数仓任务规范

目录 一、DolphinScheduler调度数仓任务现状分析 2.1 一个任务流构建数仓所有的逻辑节点 2.2 每个逻辑节点构建一个任务流 二、数仓任务管理调度需求分析 三、DolphinScheduler数仓开发任务管理规范 四、结语 前言&#xff1a;大数据领域对多种任务都有调度需求&#xff…

modbus协议和示例

协议 主机读写 从站地址&#xff08;8bit&#xff09;功能码 &#xff08;8bit&#xff09;起始地址&#xff08;16bit&#xff09;数量&#xff08;16bit&#xff09;CRC&#xff08;16bit&#xff09; 从机对主机读取的回复 从站地址&#xff08;8bit&#xff09;功能码 …

并网逆变器学习笔记8---平衡桥(独立中线模块)控制

参考文献&#xff1a;《带独立中线模块的三相四线制逆变器中线电压脉动抑制方法》---赵文心 一、独立中线模块的三相四线拓扑 独立中线模块是控制中线电压恒为母线一半&#xff0c;同时为零序电流ineu提供通路。不平衡负载的零序电流会导致中线电压脉动&#xff0c;因此需要控制…