进程间通信方式---消息队列(System V IPC)
进程间通信方式—消息队列(System V IPC)
文章目录
- 进程间通信方式---消息队列(System V IPC)
- 消息队列
- 1.消息队列进程间通信原理
- 2.msgget 系统调用
- 3.msgsnd 系统调用
- 4.msgrcv 系统调用
- 5.msgctl 系统调用
- 6.函数使用案例
- 7.实现生产者消费者模型
- 运行结果:
- 8.无血缘关系进程通信
消息队列
1.消息队列进程间通信原理
System V IPC 消息队列是一种进程间通信(IPC)机制,它允许不同进程通过发送和接收消息来进行通信。消息队列就像是一个邮箱系统,进程可以将消息(信件)发送到队列(邮箱)中,其他进程可以从这个队列中接收消息。
消息队列是在两个进程间传递二进制数据块的方式,每个数据块都有一个特定类型,接收方可以根据类型来有选择地接收数据,而不一定像管道和命名管道那样必须以先进先出的方式接收数据。
原理:
多个进程通过共享消息队列的标识符(msqid
)来访问同一个消息队列。发送进程将消息放入消息队列后,消息队列会按照一定的规则(如先进先出)存储这些消息。接收进程可以根据消息类型等条件从消息队列中取出消息。这样,不同进程之间就可以通过消息队列进行数据传输和通信,实现进程间的同步和信息共享。例如,在生产者 - 消费者模型中,生产者进程将生产的数据作为消息发送到消息队列,消费者进程从消息队列中接收消息并进行消费,通过消息类型等机制可以确保消息的正确发送和接收,从而实现生产者和消费者之间的协调工作。
Linux消息队列的API都定义在sys/msg.h
头文件中,包括4个系统调用:msgget
、msgsnd
、msgrcv
、msgctl
。
2.msgget 系统调用
msgget
系统调用创建一个消息队列,或获取一个已有的消息队列:
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
- 参数:
key_t key
:- 这是一个键值,用于标识一个全局唯一的消息队列。可以通过
ftok
函数生成一个唯一的key
值,或者使用IPC_PRIVATE
来创建一个私有消息队列(通常用于具有亲缘关系的进程,如父子进程)。
- 这是一个键值,用于标识一个全局唯一的消息队列。可以通过
int msgflg
:- 用于控制消息队列的创建和访问权限,它由以下几种标志组成:
IPC_CREAT
:如果消息队列不存在,则创建它。如果和IPC_EXCL
一起使用(IPC_CREAT | IPC_EXCL
),则只有在消息队列不存在时才创建,若已存在则msgget
函数返回 - 1 并设置errno
为EEXIST
。权限标志
:如0666
等,用于指定消息队列的访问权限,格式与文件权限相同(用户、组、其他用户的读、写、执行权限)。
- 用于控制消息队列的创建和访问权限,它由以下几种标志组成:
- 返回值:
- 成功时,返回一个非负整数,即消息队列的标识符(
msqid
)。 - 失败时,函数返回 - 1,并设置
errno
变量来指示错误原因,例如EEXIST
(当IPC_CREAT | IPC_EXCL
且队列已存在时)、ENOENT
(当没有IPC_CREAT
且队列不存在时)等。
- 成功时,返回一个非负整数,即消息队列的标识符(
如果它用于创建消息队列的话,与之相关的内核数据结构msqid_ds将被创建并初始化。
struct msqid_ds
{struct ipc_perm msg_perm; // 消息队列的操作权限time_t msg_stime; // 最后一次调用msgsnd的时间time_t msg_rtime; // 最后一次调用msgrcv的时间time_t msg_ctime; // 最后一次被修改的时间unsigned long msg_cbytes; // 消息队列中已有的字节数msgqnum_t msg_qnum; // 消息队列中已有的消息数msglen_t msg_qbytes; // 消息队列允许的最大字节数pid_t msg_lspid; // 最后执行msgsnd的进程的PIDpid_t msg_lrpid; // 最后执行msgrcv的进程的PID
};
3.msgsnd 系统调用
msgsnd
系统调用将一条消息添加到消息队列中:
#include <sys/msg.h>
int msgsnd(int msqid, const void* msg_ptr, size_t msg_sz, int msgflg);struct msgbuf{long mtype;//消息类型char mtext[512];//消息数据
};
参数:
int msqid
:
-
消息队列的标识符,由
msgget
函数返回。 -
const void* msg_ptr
:-
指向要发送消息的指针。消息的结构必须以一个长整型成员变量开始,这个长整型变量用于存放消息类型,后面可以跟随消息的实际数据。
msg_ptr
参数指向一个准备发送的消息,消息被定义为如下类型:struct msgbuf{long mtype; /* 消息类型 */char mtext[512]; /* 消息数据 */ };
-
-
size_t msg_sz
:- 这是消息数据部分的大小,不包括消息类型的长整型变量所占的字节数。
-
int msgflg
:- 控制消息发送的行为,和semget的flag一样的,常用的标志有:
0
:表示阻塞发送,如果消息队列已满,则发送进程会阻塞,直到有空间可以发送消息。IPC_NOWAIT
:表示非阻塞发送,如果消息队列已满,则msgsnd
函数立即返回 - 1,并设置errno
为EAGAIN
。
- 控制消息发送的行为,和semget的flag一样的,常用的标志有:
返回值:
- 成功时,返回
0
。 - 失败时,返回 - 1,并设置
errno
来指示错误原因,如EAGAIN
(非阻塞发送时队列已满)、EINVAL
(参数无效)、EIDRM
(消息队列已被删除)等。
处于阻塞状态的msgsnd调用可能被如下两种异常情况所中断:
-
消息队列被移除。此时msgsnd调用将立即返回并设置errno为EIDRM。
-
程序接收到信号。此时msgsnd调用将立即返回并设置errno为EINTR。
msgsnd成功时将修改内核数据结构msqid_ds的部分字段,如下所示:
-
将msg_qnum加1。
-
将msg_lspid设置为调用进程的PID。
-
将msg_stime设置为当前的时间。
4.msgrcv 系统调用
msgrcv
系统调用从消息队列中获取消息:
#include <sys/msg.h>
int msgrcv(int msqid, void* msg_ptr, size_t msg_sz, long int msgtype, int msgflg);
参数:
int msqid
:- 消息队列的标识符。
void* msg_ptr
:- 一个指向接收消息缓冲区的指针。与
msgsnd
类似,缓冲区的结构应以一个长整型开始用于存放接收到的消息类型,后面是存放消息数据的空间。
- 一个指向接收消息缓冲区的指针。与
size_t msg_sz
:- 这是接收消息缓冲区中数据部分的大小。
long int msgtype
:- 指定要接收的消息类型,可以有以下几种取值:
0
:接收(读取)消息队列中的第一条消息,不考虑消息类型。> 0
:接收第一个消息类型等于msgtype
的消息。(除非指定了标志MSG_EXCEPT,见后文)< 0
:接收(读取)消息队列中第一个类型值比msgtype的绝对值小的消息。
- 指定要接收的消息类型,可以有以下几种取值:
int msgflg
:- 控制消息接收的行为,常用标志有:
0
:表示阻塞接收,如果消息队列中没有符合条件的消息,则接收进程会阻塞,直到有符合条件的消息到达。IPC_NOWAIT
:表示非阻塞接收,如果消息队列中没有符合条件的消息,则msgrcv
函数立即返回 - 1,并设置errno
为ENOMSG
。MSG_EXCEPT
。如果msgtype大于0,则接收消息队列中第一个非msgtype类型的消息。MSG_NOERROR
。如果消息数据部分的长度超过了msg_sz,就将它截断。
- 控制消息接收的行为,常用标志有:
返回值:
- 成功时,返回接收到的消息数据部分的字节数。
- 失败时,返回 - 1,并设置
errno
来指示错误原因,如ENOMSG
(非阻塞接收时没有符合条件的消息)、EINVAL
(参数无效)、EIDRM
(消息队列已被删除)等。
处于阻塞状态的msgrcv调用还可能被如下两种异常情况所中断:
-
消息队列被移除。此时msgrcv调用将立即返回并设置errno为EIDRM。
-
程序接收到信号。此时msgrcv调用将立即返回并设置errno为EINTR。
msgrcv成功时将修改内核数据结构msqid_ds的部分字段,如下所示:
-
将msg_qnum减1。
-
将msg_lrpid设置为调用进程的PID。
-
将msg_rtime设置为当前的时间。
5.msgctl 系统调用
msgctl
系统调用,用于对消息队列进行控制操作(控制消息队列某些属性),如获取消息队列的状态信息、设置消息队列的属性、删除消息队列等。
#incldue <sys/msg.h>
int msgctl(int msqid, int command, struct msqid_ds* buf);
参数:
int msqid
:- 消息队列的标识符。
int command
:- 这是一个控制命令,用于指定对消息队列进行何种操作(见下表),常见的命令有:
IPC_STAT
:获取消息队列的状态信息,并将其存储到buf
所指向的struct msqid_ds
结构体中。这个结构体包含了消息队列的各种属性,如操作权限、当前消息数量等。IPC_SET
:根据buf
所指向的struct msqid_ds
结构体中的信息来设置消息队列的属性。例如,可以修改消息队列的操作权限等。IPC_RMID
:删除由msqid
标识的消息队列。这是一个非常重要且具有危险性的操作,一旦执行,消息队列及其所包含的消息将被永久删除。
- 这是一个控制命令,用于指定对消息队列进行何种操作(见下表),常见的命令有:
struct msqid_ds* buf
:- 这是一个指向struct msqid_ds结构体的指针,其作用取决于command参数的值:
- 当
command
为IPC_STAT
时,buf
用于存储获取到的消息队列的状态信息。 - 当
command
为IPC_SET
时,buf
指向的结构体中的信息将被用于设置消息队列的属性。 - 如果
command
不涉及IPC_STAT
或IPC_SET
操作(如IPC_RMID
),buf
通常可以设置为NULL
。
- 当
- 这是一个指向struct msqid_ds结构体的指针,其作用取决于command参数的值:
返回值:
- 成功时,取决于command(见下表)。
- 失败时,返回 - 1,并设置
errno
来指示错误原因,如EINVAL
(msqid
无效,或者command
参数无效,或者buf
指向的结构体无效(在IPC_STAT
或IPC_SET
操作时))、EPERM
(调用进程没有足够的权限来执行请求的操作)等。
6.函数使用案例
以下是使用 System V IPC 消息队列相关函数(msgget
、msgsnd
、msgrcv
和msgctl
)的一个简单 C 语言案例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>// 消息结构体
struct msgbuf {long mtype;char mtext[100];
};int main() {// 创建消息队列int msqid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);if (msqid == -1) {perror("msgget");return 1;}// 发送消息struct msgbuf send_msg;send_msg.mtype = 1;strcpy(send_msg.mtext, "Hello, World!");if (msgsnd(msqid, &send_msg, sizeof(send_msg.mtext), 0) == -1) {perror("msgsnd");return 1;}// 接收消息 struct msgbuf recv_msg;if (msgrcv(msqid, &recv_msg, sizeof(recv_msg.mtext), 1, 0) == -1) {perror("msgrcv");return 1;}printf("Received message: %s\n", recv_msg.mtext);// 获取消息队列状态 buf存储消息队列的信息struct msqid_ds buf;if (msgctl(msqid, IPC_STAT, &buf) == -1) {perror("msgctl - IPC_STAT");return 1;}printf("Messages in queue: %ld\n", buf.msg_qnum);// 删除消息队列if (msgctl(msqid, IPC_RMID, NULL) == -1) {perror("msgctl - IPC_RMID");return 1;}return 0;
}
代码解释:
消息结构体定义
- 定义了
struct msgbuf
结构体,它包含一个长整型mtype
(用于表示消息类型)和一个字符数组mtext
(用于存储消息内容)。
创建消息队列(msgget
)
- 使用
IPC_PRIVATE
作为key
来创建一个新的私有消息队列,权限设置为0666
(用户、组和其他用户都有读写权限)。如果msgget
调用成功,返回消息队列标识符msqid
;否则,打印错误信息并返回。
发送消息(msgsnd
)
- 初始化
send_msg
结构体,设置mtype
为1
,并将消息内容设置为"Hello, World!"
。 - 使用
msgsnd
函数将消息发送到消息队列中。msgsnd
函数的参数包括消息队列标识符msqid
、消息结构体指针&send_msg
、消息数据部分大小sizeof(send_msg.mtext)
和标志0
(表示阻塞发送,如果队列满则等待)。如果发送失败,打印错误信息并返回。
接收消息(msgrcv
)
- 初始化
recv_msg
结构体。 - 使用
msgrcv
函数从消息队列中接收消息。msgrcv
函数的参数包括消息队列标识符msqid
、接收消息结构体指针&recv_msg
、接收消息数据部分大小sizeof(recv_msg.mtext)
、要接收的消息类型1
和标志0
(表示阻塞接收,如果没有符合条件的消息则等待)。如果接收失败,打印错误信息并返回。 - 接收到消息后,打印出消息内容。
获取消息队列状态(msgctl
)
- 定义
struct msqid_ds
类型的变量buf
。 - 使用
msgctl
函数的IPC_STAT
命令获取消息队列的状态信息,并将其存储在buf
中。如果获取状态失败,打印错误信息并返回。 - 打印出消息队列中的消息数量(
buf.msg_qnum
)。
删除消息队列(msgctl
)
- 使用
msgctl
函数的IPC_RMID
命令删除消息队列。如果删除失败,打印错误信息并返回。
7.实现生产者消费者模型
**消息队列并不能实现互斥。**以下是使用上述消息队列函数实现的生产者 - 消费者模型的 C 代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <time.h>
#include <unistd.h>#define MAX_MSG_SIZE 100// 消息结构体
struct msgbuf {long mtype;char mtext[MAX_MSG_SIZE];
};// 生产者函数
void producer(int msqid) {struct msgbuf msg;msg.mtype = 1; // 消息类型设为1srand(time(NULL));while (1) {int num = rand() % 100;sprintf(msg.mtext, "%d", num);if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) == -1) {perror("msgsnd");exit(1);}printf("Producer sent: %s\n", msg.mtext);sleep(1);}
}// 消费者函数
void consumer(int msqid) {struct msgbuf msg;while (1) {if (msgrcv(msqid, &msg, sizeof(msg.mtext), 1, 0) == -1) {perror("msgrcv");exit(1);}printf("Consumer received: %s\n", msg.mtext);sleep(2);}
}int main() {// 创建消息队列int msqid = msgget(IPC_PRIVATE, IPC_CREAT | 0666);if (msqid == -1) {perror("msgget");return 1;}pid_t pid = fork();if (pid < 0) {perror("fork");return 1;} else if (pid == 0) {// 子进程为消费者consumer(msqid);} else {// 父进程为生产者producer(msqid);}// 等待子进程结束(这里只是简单等待,实际可能需要更完善的机制)wait(NULL);// 删除消息队列if (msgctl(msqid, IPC_RMID, NULL) == -1) {perror("msgctl");return 1;}return 0;
}
代码解释:
消息结构体定义:
- 定义了
struct msgbuf
结构体,包含一个长整型的mtype
(消息类型)和一个字符数组mtext
(用于存放消息数据)。
生产者函数:
- 生成一个随机数,将其转换为字符串后放入消息结构体的
mtext
中,然后使用msgsnd
将消息发送到消息队列中,发送的消息类型为1
,发送操作是阻塞的(msgflg
为0
)。
消费者函数:
- 使用
msgrcv
从消息队列中接收消息类型为1
的消息,接收操作是阻塞的(msgflg
为0
),接收到消息后打印出消息内容。
主函数:
- 使用
msgget
创建一个私有消息队列。 - 通过
fork
创建子进程,子进程作为消费者,父进程作为生产者。 - 最后等待子进程结束,并使用
msgctl
删除消息队列。
并不能够实现互斥,只是能够通信。
运行结果:
8.无血缘关系进程通信
ftok
函数的定义和功能- 函数原型:
key_t ftok(const char *pathname, int proj_id);
- 功能:
ftok
函数用于生成一个唯一的key
(键值),这个key
通常用于 System V IPC(进程间通信)机制中,如创建共享内存、消息队列和信号量集等。它将一个文件路径名(pathname
)和一个项目标识符(proj_id
)组合起来,生成一个适合作为 System V IPC 资源标识符的key
值。
- 函数原型:
- 参数解释
const char *pathname
:- 这是一个指向文件路径名的指针。这个文件路径必须是一个已经存在的文件的有效路径,通常使用当前目录(
."
)或者一个程序相关的配置文件路径等。ftok
函数会使用文件的inode
(索引节点)信息作为生成key
的一部分。 - 注意,如果文件被删除然后重新创建,即使文件名相同,
inode
可能会改变,这会导致ftok
生成不同的key
值。
- 这是一个指向文件路径名的指针。这个文件路径必须是一个已经存在的文件的有效路径,通常使用当前目录(
int proj_id
:- 这是一个
0 - 255
之间的整数,作为项目标识符。它和文件路径的inode
信息一起组合生成key
。不同的项目可以使用不同的proj_id
来区分,这样即使基于同一个文件路径,不同的项目也能生成不同的key
值用于各自的 IPC 资源。例如,一个程序中有两个不同的模块需要使用消息队列进行通信,它们可以使用相同的文件路径但不同的proj_id
来生成不同的key
,以创建两个独立的消息队列。
- 这是一个
- 返回值
- 成功时,
ftok
函数返回一个key_t
类型的非负整数,这个整数可以作为shmget
、msgget
、semget
等 System V IPC 函数的key
参数来创建或获取对应的 IPC 资源。 - 失败时,返回-1,并且会设置errno来指示错误原因。常见的错误原因包括:
EACCESS
:没有权限访问pathname
指定的文件。ENOENT
:pathname
指定的文件不存在。
- 成功时,
发送端
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>// 消息结构体
struct msgbuf {long mtype;char mtext[100];
};int main() {// 通过ftok生成keykey_t key = ftok(".", 'c');if (key == -1) {perror("ftok");return 1;}// 创建消息队列int msqid = msgget(key, IPC_CREAT | 0666);if (msqid == -1) {perror("msgget");return 1;}// 准备发送消息的结构体struct msgbuf send_msg;send_msg.mtype = 1;strcpy(send_msg.mtext, "Hello from sender!");if (msgsnd(msqid, &send_msg, sizeof(send_msg.mtext), 0) == -1) {perror("msgsnd");return 1;}printf("Sender sent message...\n");sleep(10);// 删除消息队列if (msgctl(msqid, IPC_RMID, NULL) == -1) {perror("msgctl for delete");return 1;}return 0;
}
接收端
#include <stdio.h>
#include <stdlib.combined
#include <sys/types.combined
#include <sys/ipc.combined
#include <sys/msg.combined
#include <string.combined// 消息结构体
struct msgbuf {long mtype;char mtext[100];
};int main() {// 通过ftok生成keykey_t key = ftok(".", 'c');if (key == -1) {perror("ftok");return 1;}// 获取消息队列int msqid = msgget(key, 0666);if (msqid == -1) {perror("msgget")return 1;}// 准备接收消息的结构体struct msgbuf recv_msg;if (msgrcv(msqid, &recv_msg, sizeof(recv_msg.mtext), 1, 0) == -1) {perror("msgrcv")return 1;}printf("Receiver received message: %s\n", recv_msg.mtext);return 0;
}
运行结果:
相关文章:
进程间通信方式---消息队列(System V IPC)
进程间通信方式—消息队列(System V IPC) 文章目录 进程间通信方式---消息队列(System V IPC)消息队列1.消息队列进程间通信原理2.msgget 系统调用3.msgsnd 系统调用4.msgrcv 系统调用5.msgctl 系统调用6.函数使用案例7.实现生产者…...
【笔记】深度学习模型评估指标
推荐链接: (0)多分类器的评价指标 (1)泛化误差的评价方法:【机器学习】模型评估与选择(留出法、交叉验证法、查全率、查准率、偏差、方差) (2)机器学习&…...
Python语法之列表(包含检测练习)
看完后有没有学会呢?主页有一个列表知识小检测^V^ 关注我更新更多初学实例 主页还有字典的,这个系列会持续更新 列表 列表中的查找数据(index,count,len) 一 列表的格式 【数据1,数据2, 】 index():返回指定数据…...
气象与旅游之间的关系,如果借助高精度预测提高旅游的质量
气象与旅游之间存在密切的关系,天气条件直接影响旅游者的出行决策、旅游体验和安全保障。通过高精度气象预测技术,可以有效提升旅游质量,为游客和旅游行业带来显著的优势。 1. 提高游客出行决策效率 个性化天气服务:基于高精度气象预测,旅游平台可以提供个性化的天气预报服…...
JVM(Java虚拟机)分区详情
JVM(Java虚拟机)运行时数据区是Java虚拟机的内存管理模型,它包括了多个关键的内存区域,这些区域各自承担着不同的职责,共同支持着Java程序的运行。以下是JVM运行时数据区的详细介绍: 一、整体概述 JVM运行时数据区按照线程占用的情况可以分为两类:线程共享和线程独享。…...
计算机组成原理的学习笔记(2)--数据表示与运算·其二 逻辑门和加减乘
学习笔记 前言 本文主要是对于b站尚硅谷的计算机组成原理的学习笔记,仅用于学习交流。 1. 逻辑门 逻辑门是数字电路中用于执行基本逻辑运算的组件。每种逻辑门都有独特的功能和特性: 与门(AND Gate): 符号࿱…...
数据科学与SQL:如何利用本福特法则识别财务数据造假?
目录 0 本福特法则介绍 1 数据准备 2 问题分析 步骤1:提取首位数: 步骤2:计算首位数字的实际频率分布 <...
Mapbox-GL 的源码解读的一般步骤
Mapbox-GL 是一个非常优秀的二三维地理引擎,随着智能驾驶时代的到来,应用也会越来越广泛,关于mapbox-gl和其他地理引擎的详细对比(比如CesiumJS),后续有时间会加更。地理首先理解 Mapbox-GL 的源码是一项复…...
常见网络命令
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 常见网络命令 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 Ping 命令 …...
Ubuntu上如何部署Nginx?
环境: Unbuntu 22.04 问题描述: Ubuntu上如何部署Nginx? 解决方案: 在Ubuntu上部署Nginx是一个相对简单的过程,以下是详细的步骤指南。我们将涵盖安装Nginx、启动服务、配置防火墙以及验证安装是否成功。 1. 更新…...
微店商品详情API:获取商品信息的高效途径
引言 在电商领域,获取商品详情是开发者和商家进行数据分析、精准营销和店铺管理的重要一环。微店作为知名的电商平台,提供了丰富的API接口供开发者使用,其中商品详情API接口尤为关键。本文将详细介绍如何使用微店API接口获取商品详情&#x…...
编程语言注释的方式
Python 单行注释 # 这是一个单行注释多行注释(本质上是跨行字符串) 这是一个多行注释的示例。它可以跨越多行。 """这是一个多行注释的示例。它可以跨越多行。 """ C 单行注释 // 这是一个单行注释 多行注释 /*这是…...
抓住节假日的机会调整ASO优化策略
节日季和全年的特殊活动为提高应用程序的知名度和下载量提供了独特的机会。忽略节假日意味着错过这些有限的扩大用户群的机会。相反,调整您的应用商店优化 (ASO) 策略以适应这些高流量时段至关重要。以下是如何在假期期间最大限度地提高应用程序的性能。 一、为什么…...
AOI外观缺陷检测机
主要功能: 快速检测产品装配缺陷,包括螺丝、元器件、端子排线、二维码、一维条码、识别读码、产品外观 Logo缺陷以及产品标签、字符缺陷检测等产品的缺陷检测。 设备优势:1.采用轻型可移动支架,可以快速对接产线工艺工序&am…...
BERT模型
目录 1.BERT介绍2.BERT框架2.1 Embedding2.2 Transformer Encoder 3.BERT可视化4.注意力六种模式4.1 模式1:注意下一个词4.2 模式2:注意前一个词4.3 模式3:注意相同或相关的单词4.4 模式4:注意“其他”句子中相同或相关词4.5 模式…...
Ubuntu22.04上安装esp-idf
一、安装准备# 建议使用Ubuntu 20.04 或 Ubuntu 22.04 操作系统 为了在 Ubuntu 22.04 中使用 esp-idf,需要安装一些依赖包 sudo apt-get install git wget flex bison gperf python3\python3-pip python3-venv cmake ninja-build ccache\libffi-dev libssl-dev dfu…...
Synchronous Serial Port 协议详解
1、简介 Synchronous Serial Port (SSP) ,基于下图文档的设计标准 1.1、包含3种数据帧格式: a Motorola SPI-compatible interface(以下简称SPI)a Texas Instruments synchronous serial interface(简写SSIÿ…...
BSM和BMS什么区别?
BSM BSM(Battery System Manager)是指用于管理和控制电动车辆的电池系统的设备,其功能包括监测电池状态、控制充放电过程、保护电池安全等。 BMS BMS(Battery Management System)是指用于监测、控制和保护电池组的设…...
基于海思soc的智能产品开发(巧用mcu芯片)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于开发车规级嵌入式软件的同学来说,socmcu这样的组合,他们并不陌生。但是传统的工业领域,比如发动机、医疗或…...
R语言混合模型回归GBTM群组轨迹模型绘图可视化研究
全文链接:https://tecdat.cn/?p38581 在回归分析的广袤领域中,面对具有多条未知函数线的复杂数据时,传统方法常常捉襟见肘。混合模型作为一种强有力的分析手段应运而生,其在处理此类复杂情境时展现出独特的优势与潜力(…...
Flink2.0未来趋势中需要注意的一些问题
手机打字,篇幅不长,主要讲一下FFA中关于Flink2.0的未来趋势,直接看重点。 Flink Forward Asia 2024主会场有一场关于Flink2.0的演讲,很精彩,官方也发布了一些关于Flink2.0的展望和要解决的问题。 1.0时代和2.0时代避免…...
android recycleview 中倒计时数据错乱
原因 recyceleview 当页面划出屏幕外后,默认会有两条进入缓存区,这些item的结构会被保存,数据被清除,方便其他新进入屏幕的数据复用item,超过两条外的item会进入缓存池被完全销毁重用。 如果我们的页面上有editText 或…...
康冠科技嵌入式面试题及参考答案
LCD 驱动你自己做了哪些内容? 在 LCD 驱动开发中,首先是硬件层面的理解。需要仔细研究 LCD 的数据手册,明确其引脚定义,包括电源引脚、数据引脚、控制引脚等。比如,对于常见的 RGB 接口 LCD,要清楚哪几个引脚是用于传输红、绿、蓝三种颜色的数据,以及像 VSYNC(垂直同步…...
FreeRTOS的任务调度
1.启动任务调度器 vTaskStartScheduler void vTaskStartScheduler( void ) { BaseType_t xReturn;/* Add the idle task at the lowest priority. */#if ( INCLUDE_xTaskGetIdleTaskHandle 1 ){/* Create the idle task, storing its handle in xIdleTaskHandle so it canbe …...
scala中模式匹配的应用
package test34object test6 {case class Person(name:String)case class Student(name:String, className:String)// match case 能根据 类名和属性的信息,匹配到对应的类// 注意:// 1 匹配的时候,case class的属性个数要对上// 2 属性名不需…...
基于Springboot人口老龄化社区服务与管理平台【附源码】
基于Springboot人口老龄化社区服务与管理平台 效果如下: 系统登陆页面 系统主页面 社区信息页面 社区文件页面 活动报名页面 走访任务管理页面 社区资讯页面 老人信息管理页面 研究背景 随着社会老龄化的加剧,老年人口比例逐渐增加,对老年…...
前端生成docx文档、excel表格、图片、pdf文件
一、前端将页面某区域内容下载为word文档:html-to-docx、file-saver插件组合使用 import HTMLtoDOCX from html-to-docx; import { saveAs } from file-saver;const exportTest async () > {const fileBuffer await HTMLtoDOCX(<h2>文件标题</h2>&…...
Ubantu22系统安装Miniconda3
1、Anaconda和Miniconda异同 清华源镜像的Miniconda3和Anaconda都是用于管理Python环境和软件包的工具,但它们之间存在一些关键的不同之处。下面将分别介绍它们的特点以及使用清华源镜像的差异。 相同点: (1)功能相似:…...
详细解读TISAX认证的意义
详细解读TISAX认证的意义,犹如揭开信息安全领域的一颗璀璨明珠,它不仅代表了企业在信息安全管理方面的卓越成就,更是通往全球汽车供应链信任桥梁的关键一环。TISAX,即“Trusted Information Security Assessment Exchange”&#…...
kubeadm_k8s_v1.31高可用部署教程
kubeadm_k8s_v1.31高可用部署教程 实验环境部署拓扑图**部署署架构****Load Balance****Control plane node****Worker node****资源分配(8台虚拟机)**集群列表 前置准备关闭swap开启ipv4转发更多设置 1、Verify the MAC address and product_uuid are u…...
MyBatis写法汇总
Mybatis写法汇总 1. 批量操作 1.1 批量插入 <insert id"batchInsert" parameterType"java.util.List">INSERT INTO user (username, password, create_time) VALUES<foreach collection"list" item"item" separator"…...
【C++】优先级队列以及仿函数
本篇我们来介绍一下优先级队列 priority_queue 。优先级队列的底层是数据结构中的堆,在C中它是一个容器适配器,这个容器适配器比之前的栈和队列更复杂。 1.priority_queue的介绍 1.1 优先级队列的底层 因为优先级队列就是堆,堆的底层是数组…...
【VUE】13、安装nrm管理多个npm源
nrm(npm registry manager)是一个 npm 源管理器,它允许用户快速地在不同的 npm 源之间进行切换,以提高包管理的速度和效率。以下是对 nrm 使用的详细介绍: 1、安装nrm 在使用 nrm 之前,需要先确保已经安装…...
selenium工作原理
原文链接:https://blog.csdn.net/weixin_67603503/article/details/143226557 启动浏览器和绑定端口 当你创建一个 WebDriver 实例(如 webdriver.Chrome())时,Selenium 会启动一个新的浏览器实例,并为其分配一个特定的…...
Reactor 响应式编程(第三篇:R2DBC)
系列文章目录 Reactor 响应式编程(第一篇:Reactor核心) Reactor 响应式编程(第二篇:Spring Webflux) Reactor 响应式编程(第三篇:R2DBC) Reactor 响应式编程(…...
从零开始掌握 React 前端框架:入门指南与实战案例
🚀 从零开始掌握 React 前端框架:入门指南与实战案例 📖 前言 React 是由 Facebook 推出的前端框架,用于构建高效、可复用的用户界面(UI)。本文将手把手教你如何从零开始掌握 React,内容覆盖 …...
【日常笔记】Spring boot:编写 Content type = ‘text/plain‘ 接口
一、项目场景: 接口:Context-Type:text/plain 方式:POST 项目场景:硬件回调接口 二、实战 PostMapping(value "/xx/xxx", consumes "text/plain" ) 2.1、接口 /*** return String* time 202…...
探索 Seaborn Palette 的奥秘:为数据可视化增色添彩
一、引言 在数据科学的世界里,视觉传达是不可或缺的一环。一个好的数据可视化不仅能传递信息,还能引发共鸣。Seaborn 是 Python 中一款广受欢迎的可视化库,而它的调色板(palette)功能,则为我们提供了调配绚…...
多智能体/多机器人网络中的图论法
一、引言 1、网络科学至今受到广泛关注的原因: (1)大量的学科(尤其生物及材料科学)需要对元素间相互作用在多层级系统中所扮演的角色有更深层次的理解; (2)科技的发展促进了综合网…...
【中标麒麟服务器操作系统实例分享】java应用DNS解析异常分析及处理
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn 情况描述 中标麒麟服务器操作系统V7运行在 ARM虚…...
设计模式12:状态模式
系列总链接:《大话设计模式》学习记录_net 大话设计-CSDN博客 参考:设计模式之状态模式 (C 实现)_设计模式的状态模式实现-CSDN博客 1.概述 状态模式允许一个对象在其内部状态改变时改变其行为。对象看起来像是改变了其类。使用状态模式可以将状态的相…...
AI @国际象棋世界冠军赛: 从棋盘到科研创新之路
点击屏末 | 阅读原文 | 在小红书和 Google 谷歌回顾 WCC...
LeetCode刷题day29——动态规划(完全背包)
LeetCode刷题day29——动态规划(完全背包) 377. 组合总和 Ⅳ分析: 57. 爬楼梯(第八期模拟笔试)题目描述输入描述输出描述输入示例输出示例提示信息 分析: 322. 零钱兑换分析: 279. 完全平方数分…...
C++对象数组对象指针对象指针数组
一、对象数组 对象数组中的每一个元素都是同类的对象; 例1 对象数组成员的初始化 #include<iostream> using namespace std;class Student { public:Student( ){ };Student(int n,string nam,char s):num(n),name(nam),sex(s){};void display(){cout<&l…...
主曲率为常数时曲面分类
主曲率为常数 ⇔ K , H \Leftrightarrow K,H ⇔K,H 为常数,曲面分类: 1.若 k 1 k 2 0 k_1k_20 k1k20,则 S S S为全脐点曲面——平面的一部分; 2.若 k 1 k 2 ≠ 0 k_1k_2\neq0 k1k20,则 S S S为全脐点曲面——球面的一部分&…...
单片机:实现HC-SR04超声波测距(附带源码)
使用单片机实现 HC-SR04 超声波测距模块 的功能,通常用于测量物体与超声波传感器之间的距离。HC-SR04 模块通过发射超声波信号并测量其返回时间来计算距离。单片机(如 STM32、51 系列、Arduino 等)可用来控制该模块的工作,并处理返…...
分布式全文检索引擎ElasticSearch-数据的写入存储底层原理
一、数据写入的核心流程 当向 ES 索引写入数据时,整体流程如下: 1、客户端发送写入请求 客户端向 ES 集群的任意节点(称为协调节点,Coordinating Node)发送一个写入请求,比如 index(插入或更…...
mfc140u.dll是什么文件?如何解决mfc140u.dll丢失的相关问题
遇到“mfc140u.dll文件丢失”的错误通常影响应用程序的运行,这个问题主要出现在使用Microsoft Visual C环境开发的软件中。mfc140u.dll是一个重要的系统文件,如果它丢失或损坏,会导致相关程序无法启动。本文将简要介绍几种快速有效的方法来恢…...
ChatGPT生成接口测试用例(一)
用ChatGPT做软件测试 接口测试在软件开发生命周期中扮演着至关重要的角色,有助于验证不同模块之间的交互是否正确。若协议消息被恶意修改,系统是否能够恰当处理,以确保系统的功能正常运行,不会出现宕机或者安全问题。 5.1 ChatGP…...
Jenkins 中 写 shell 命令执行失败,检测失败问题
由于项目的 依赖复杂,随着版本的增多,人工操作,手误几率太大,我们选取kenins 来自动化发布、更新。 这里主要解决,发布 的 每个阶段,确保每个阶段执行成功。 比如: js 运行,…...