嵌入式Linux学习笔记(5)-进程间常见通讯方式(c语言实现)
一、概述
进程间通信(IPC,InterProcess Communication)是指在多个进程之间进行数据传输和共享的机制。在操作系统中,进程是运行中的程序的实例,每个进程都有自己的内存空间和资源。
进程间通信可以用于在不同的进程之间传递数据、共享资源、进行协同工作等。常见的进程间通信方式有以下几种:
-
管道(Pipe):管道是一种半双工的通信方式,它是通过创建一个管道文件用于两个进程之间的通信。一个进程可以将数据写入管道,而另一个进程可以从管道中读取数据。
-
有名管道(Named Pipe):有名管道也是一种管道,不同之处在于它是一个带有名称的管道,可以用于多个进程之间的通信。
-
共享内存(Shared Memory):共享内存是一种进程间通信的高效方式,它允许多个进程访问同一块内存区域,从而实现数据共享。
-
消息队列(Message Queue):消息队列是一种按照先进先出(FIFO)原则进行数据传输的机制。进程可以将消息放入队列,而其他进程可以从队列中读取消息。
-
信号量(Semaphore):信号量是一个特殊的变量,用于控制多个进程之间的临界区访问。通过信号量可以实现进程的互斥和同步操作。
-
套接字(Socket):套接字是一种网络编程中常用的进程间通信方式,它可以在不同的主机之间进行数据传输和通信。
二、管道
1、用法
管道(pipe)是一种在进程间通信中非常常用的机制,它可以将一个进程的输出(stdout)直接作为另一个进程的输入(stdin)。
pipe()函数:创建管道使用,它的原型为:
int pipe(int pipefd[2]);
该函数需要传入一个整型的数组,数组的长度必须是2。该函数会创建一个管道,并将管道的读写句柄分别存储在pipefd[0]和pipefd[1]中。pipefd[0]用于读取管道中的数据,pipefd[1]用于写入管道。
常用函数有:
read()函数:从管道中读取数据。其原型为:
ssize_t read(int fd, void *buf, size_t count);
其中,fd是管道的读取句柄(即pipefd[0]),buf是存储读取数据的缓冲区,count是读取的最大字节数。该函数返回实际读取的字节数。如果从终端读取数据,fd 的值为 STDIN_FILENO。
write()函数:向管道中写入数据。其原型为:
ssize_t write(int fd, const void *buf, size_t count);
其中,fd是管道的写入句柄(即pipefd[1]),buf是待写入的数据的缓冲区,count是待写入的字节数。该函数返回实际写入的字节数。如果往终端写入数据,fd 的值为 STDOUT_FILENO。
close()函数:关闭管道的读取或写入端。其原型为:
int close(int fd);
其中,fd是待关闭的管道的句柄。
2、用例
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>int main(int argc, char const *argv[])
{pid_t pid;int pipefd[2];if (argc != 2){fprintf(stderr,"%s: 参数不够!\n",argv[0]);exit(EXIT_FAILURE);}//创建管道if (pipe(pipefd) == -1){perror("创建管道数据");exit(EXIT_FAILURE);}//创建子进程pid = fork();if (pid < 0){fprintf(stderr,"%s: 邀请新学员失败!\n",argv[0]);exit(EXIT_FAILURE);}else if (pid == 0){//读取管道数据并打印close(pipefd[1]);char str[100]={0};sprintf(str,"%d 读出数据",getpid());write(STDOUT_FILENO,&str,sizeof(str));char buf;while (read(pipefd[0],&buf,1)>0){write(STDOUT_FILENO,&buf,1);}write(STDOUT_FILENO,"\n",1);close(pipefd[0]);_exit(EXIT_SUCCESS);//直接退出不做任何操作}else{//写入管道数据,提供给子进程close(pipefd[0]);printf("%d 写入数据\n",getpid());write(pipefd[1],argv[1],strlen(argv[1]));close(pipefd[1]);waitpid(pid,NULL,0);}return 0;
}
这个用例创建了一个子进程。随后父进程写入数据,子进程读取数据。
三、有名管道
1、用法
有名管道(Named Pipe)是一种在操作系统中用于进程间通信的通道。它可以在不相关的进程之间传递数据。以下是对有名管道及常用函数的详细介绍。
有名管道是一种特殊的文件,它以文件名的形式存在于文件系统中。与普通文件不同的是,有名管道允许不相关的进程之间进行通信。有名管道是以FIFO(先进先出)的方式传递数据,即先进入管道的数据首先被读取出来。有名管道可以用于在父进程和子进程之间传递数据,也可以用于不同进程之间的通信。
mkfifo():创建一个新的有名管道。它的原型为:
int mkfifo(const char *pathname, mode_t mode)
其中,pathname是管道的路径名,mode定义了管道的权限。该函数成功时返回0,失败时返回-1。
open():打开有名管道以进行读取或写入操作。它的原型为:
int open(const char *pathname, int flags)
其中,pathname是管道的路径名,flags定义了打开的方式和权限。该函数成功时返回文件描述符,失败时返回-1。
其余函数如:read,write,close与管道用法一致。
有名管道提供了一种简单的进程间通信方式,但也有一些限制。首先,它只适用于在同一计算机上的进程间通信。其次,有名管道是阻塞式的,即读取操作会一直等待直到有数据可读,写入操作会一直等待直到有空间可写。因此,在使用有名管道时要注意避免进程间出现死锁的情况。
2、用例
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>int main(int argc, char const *argv[])
{int fd;//有名管道创建完可重复使用,但推荐每次用完删除,下次重新创建char *pipe_path = "/tmp/myfifo";if(mkfifo(pipe_path,0644) != 0){perror("mkfifo");if (errno != 17)//不是文件已存在{exit(EXIT_FAILURE);}}fd = open(pipe_path,O_WRONLY);if(fd == -1){perror("open");exit(EXIT_FAILURE);}char buf[100];ssize_t read_num;//从终端写入数据到管道中while ((read_num = read(STDIN_FILENO,buf,100)) > 0){write(fd,buf,read_num);}if (read_num < 0){perror("read");close(fd);exit(EXIT_FAILURE);}printf("发送数据到管道完成,进程终止\n");close(fd);//清除管道//清除对应特殊文件if (unlink(pipe_path) == -1){perror("unlink");}return 0;
}
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>int main(int argc, char const *argv[])
{int fd;char *pipe_path = "/tmp/myfifo";// if(mkfifo(pipe_path,0644) != 0){// perror("mkfifo");// exit(EXIT_FAILURE);// }fd = open(pipe_path,O_RDONLY);if(fd == -1){perror("open");exit(EXIT_FAILURE);}char buf[100];ssize_t read_num;//读取管道信息while ((read_num = read(fd,buf,100)) > 0){write(STDOUT_FILENO,buf,read_num);}if (read_num < 0){perror("read");close(fd);exit(EXIT_FAILURE);}printf("接收管道数据完成,进程终止\n");close(fd);return 0;
}
两个.c文件分别代表两个无关联的进程。一个从终端接收数据并将数据写入有名管道中,另一个从管道中接收数据并打印在终端。
四、共享内存
1、用法
在C语言中,进程间通信(IPC)是实现不同进程之间数据交换和共享的重要方式之一。共享内存是一种高效的IPC机制,可以实现不同进程之间的数据共享。
共享内存是一块由操作系统管理的内存区域,可以被多个进程同时访问。进程可以将共享内存映射到自己的地址空间中,从而可以直接读写该内存区域,实现数据共享。
shm_open():该函数用于创建或打开一个共享内存对象。它的原型如下:
int shm_open(const char *name, int oflag, mode_t mode);
参数:
name:共享内存对象的名称
oflag:打开标志,用于指定打开方式和操作权限
mode:权限位,用于指定该共享内存对象的操作权限
返回值:共享内存对象的文件描述符,若打开或创建失败则返回-1。
shm_unlink():该函数用于删除一个共享内存对象。它的原型如下:
int shm_unlink(const char *name);
参数:
name:共享内存对象的名称
返回值:成功返回0,失败返回-1。
mmap():该函数用于将共享内存映射到进程的地址空间中。它的原型如下:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数:
addr:指定映射的起始地址,通常设为NULL,让操作系统自动选择一个合适的地址。
length:映射的长度,单位为字节。
prot:映射内存区域的保护模式,如读、写、执行等。
flags:映射的标志,用于指定映射方式和映射类型。
fd:共享内存对象的文件描述符。
offset:共享内存对象中的偏移量。
返回值:映射成功时返回映射区域的起始地址,失败时返回MAP_FAILED。
munmap():函数用于释放由mmap函数映射的内存区域。它的原型如下:
int munmap(void *addr, size_t length);
参数:
addr:指向要释放的内存区域的起始地址。这个地址必须是mmap返回的地址,或者是页面大小的整数倍。
length:要释放的内存区域的大小。
返回值:成功时,返回0;失败时,返回-1,并设置errno。
2、用例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/types.h>int main(int argc, char const *argv[])
{char *share;// 1.创建共享内存对象char shm_name[100]={0};sprintf(shm_name,"/letter%d",getpid());int fd;fd = shm_open(shm_name,O_RDWR | O_CREAT,0644);if (fd < 0){perror("shm_open");exit(EXIT_FAILURE);}// 2.设置共享内存对象大小ftruncate(fd,1024);// 3.内存映射share = mmap(NULL,1024,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if (share == MAP_FAILED){perror("mmap");exit(EXIT_FAILURE);}// 映射后关闭fd,不是释放close(fd);// 4.使用内存映射实现进程间的通讯pid_t pid = fork();if (pid < 0){perror("fork");exit(EXIT_FAILURE);}else if (pid == 0){strcpy(share,"hello,my name is liuyuhui\n");printf("子进程%d:发送完毕!\n",getpid());}else{waitpid(pid,NULL,0);printf("父进程 %d 接收到了子进程 %d 发送的消息: %s\n",getpid(),pid,share);// 5.释放映射区int re = munmap(share,1024);if (re == -1){perror("munmap");exit(EXIT_FAILURE);}}// 6.释放共享内存对象shm_unlink(shm_name);return 0;
}
共享内存大致就分了这六步。这个例程实现的是父进程向共享内存中写入数据,子进程从共享内存中读出数据。
五、消息队列
1、用法
在C语言中,进程间通讯是指两个或多个进程之间进行数据交换或共享资源的过程。消息队列是一种进程间通讯的方式,允许进程通过发送和接收消息来交换数据。
mq_open():用于创建或打开一个消息队列。函数原型如下:
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
参数:
name:消息队列的名称。
oflag:打开标志。可以是O_CREAT(如果消息队列不存在,则创建)和O_EXCL(与O_CREAT一起使用,确保创建新的消息队列)。
mode:权限和创建文件时的权限位掩码(只有在创建消息队列时才使用)。attr:指向消息队列属性的指针。
mq_unlink():用于删除一个已经命名的消息队列。函数原型如下:
int mq_unlink(const char *name);
参数:
name:消息队列的名称。
clock_gettime():用于获取当前时间。函数原型如下:
int clock_gettime(clockid_t clk_id, struct timespec *tp);
clk_id:时钟ID,可以是CLOCK_REALTIME(系统实时时间)或CLOCK_MONOTONIC(运行时间)。
tp:保存时间的结构体指针。
mq_timedsend():用于向消息队列发送消息,并可以设置发送超时时间。函数原型如下:
int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
参数:
mqdes:消息队列描述符。
msg_ptr:指向发送消息的指针。
msg_len:发送消息的长度。
msg_prio:消息的优先级。
abs_timeout:绝对时间,若超过该时间则发送超时。
mq_timedreceive():用于从消息队列接收消息,并可以设置接收超时时间。函数原型如下:
ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abs_timeout);
参数:
mqdes:消息队列描述符。
msg_ptr:指向接收消息的指针。
msg_len:接收消息的最大长度。
msg_prio:接收到的消息的优先级。
abs_timeout:绝对时间,若超过该时间则接收超时
2、用例
①:父子进程间通讯
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{struct mq_attr attr;attr.mq_maxmsg=10;attr.mq_msgsize=100;attr.mq_flags=0;attr.mq_curmsgs=0;//创建消息队列char *mq_name = "/father_son"; mqd_t mqdes = mq_open(mq_name,O_RDWR|O_CREAT,0644,&attr);if (mqdes == -1){perror("mq_open");exit(EXIT_FAILURE);}//创建进程pid_t pid = fork();if (pid < 0){perror("fork");exit(EXIT_FAILURE);}else if (pid == 0){//子进程接收消息char read_buf[100];struct timespec time_info;//接受数据for (int i = 0; i < 10; i++){//清空并发送数据memset(read_buf,0,100);//设置等待时间clock_gettime(0,&time_info);time_info.tv_sec += 15;//接收消息if(mq_timedreceive(mqdes,read_buf,100,NULL,&time_info) == -1){perror("mq_timedreceive");}printf("子进程接收到消息:%s\n",read_buf);}}else{//父进程发送消息char send_buf[100];struct timespec time_info;for (int i = 0; i < 10; i++){//清空并发送数据memset(send_buf,0,100);sprintf(send_buf,"父进程发送的第 %d 条消息\n",(i+1));//获取当前时间clock_gettime(0,&time_info);time_info.tv_sec += 5;//发送消息if(mq_timedsend(mqdes,send_buf,strlen(send_buf),0,&time_info) == -1){perror("mq_timedsend");}printf("父进程休息1s\n");sleep(1);}} //释放两次消息队列的引用close(mqdes);//清除一次消息队列if (pid > 0){mq_unlink(mq_name);}return 0;
}
②:不同进程间通讯
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{struct mq_attr attr;attr.mq_maxmsg=10;attr.mq_msgsize=100;attr.mq_flags=0;attr.mq_curmsgs=0;//创建消息队列char *mq_name = "/p_c_mq"; mqd_t mqdes = mq_open(mq_name,O_RDWR|O_CREAT,0644,&attr);if (mqdes == -1){perror("mq_open");exit(EXIT_FAILURE);}char write_buf[100];struct timespec time_info;//不断接收控制台消息 发送到消息队列while (1){memset(write_buf,0,100);ssize_t read_count = read(STDIN_FILENO,write_buf,100);clock_gettime(0,&time_info);time_info.tv_sec += 5;if (read_count == -1){perror("read");continue;}else if (read_count == 0){//ctrl + d 退出时printf("EOF,exit...\n");char eof = EOF;if (mq_timedsend(mqdes,&eof,1,0,&time_info) == -1){perror("mq_timedsend");}break;}//正常发送if (mq_timedsend(mqdes,write_buf,strlen(write_buf),0,&time_info) == -1){perror("mq_timedsend");}printf("正常发送成功!\n");}//释放消息队列描述符close(mqdes);//清除消息队列 (消费者执行一次即可)// mq_unlink(mq_name);return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{struct mq_attr attr;attr.mq_maxmsg=10;attr.mq_msgsize=100;attr.mq_flags=0;attr.mq_curmsgs=0;//创建消息队列char *mq_name = "/p_c_mq"; mqd_t mqdes = mq_open(mq_name,O_RDWR|O_CREAT,0644,&attr);if (mqdes == -1){perror("mq_open");exit(EXIT_FAILURE);}char read_buf[100];struct timespec time_info;//不断接收控制台消息 发送到消息队列while (1){memset(read_buf,0,100);clock_gettime(0,&time_info);time_info.tv_sec += 15;//正常接收if (mq_timedreceive(mqdes,read_buf,100,NULL,&time_info) == -1){perror("mq_timedreceive");}//判断是否结束if (read_buf[0] == EOF){printf("收到结束信息,准备退出...\n");break;}printf("正常接收成功,信息为:%s\n",read_buf);}//释放消息队列描述符close(mqdes);//清除消息队列mq_unlink(mq_name);return 0;
}
需要注意的是因为公用同一片资源,所以在不同进程间通讯时接收方只需接收完消息后将消息队列清除掉即可,发送方不需要重复清除,也可避免接收方还没读取完消息队列的值就被发送方清除了消息队列。
相关文章:
嵌入式Linux学习笔记(5)-进程间常见通讯方式(c语言实现)
一、概述 进程间通信(IPC,InterProcess Communication)是指在多个进程之间进行数据传输和共享的机制。在操作系统中,进程是运行中的程序的实例,每个进程都有自己的内存空间和资源。 进程间通信可以用于在不同的进程之间…...
【移动端】菜单的自动展开与收回
前言 为了满足手机上菜单栏随用户移动,菜单的自动展示与隐藏,特此记录 基本原理 实现逻辑 window.addEventListener(‘scroll’, debouncedScrollHandler) – 监听文档视图滚动事件 document.querySelector(‘.header’) – 选择器匹配元素 创建show和h…...
Java获取Object中Value的方法
在Java中,获取对象(Object)中的值通常依赖于对象的类型以及我们希望访问的属性。由于Java是一种静态类型语言,直接从一个Object类型中访问属性是不可能的,因为Object是所有类的超类,但它本身不包含任何特定…...
集群聊天服务器项目【C++】(二)Json的简单使用
在上一章中,简单介绍了本项目的内容、技术栈、需求和目标等,详细介绍了环境配置,如果还没有配置成功,请参考我的上一篇博客环境配置 今天主要介绍Json库是什么以及简单的使用。 1.为什么要使用Json 我们在网络传输数据时&#…...
班迪录屏和这三款录屏工具,一键操作,太方便了!
嘿,小伙伴们!今天我要跟大家分享几款超棒的录屏工具,它们绝对是我们在工作和学习中不可或缺的好帮;这些工具功能强大且操作简单,下面就让我来详细介绍一下它们的使用体验和好用之处吧! 班迪录屏工具使用体…...
DAY60Bellman_ford 算法
队列优化算法 请找出从城市 1 到城市 n 的所有可能路径中,综合政府补贴后的最低运输成本。 如果能够从城市 1 到连通到城市 n, 请输出一个整数,表示运输成本。如果该整数是负数,则表示实现了盈利。如果从城市 1 没有路径可达城市…...
Dubbo SPI源码
文章目录 Dubbo SPI使用方式AOP功能源码剖析SPI注解1.获取加载器2.获取拓展实例对象3.创建拓展类的实例对象 Dubbo SPI Dubbo 的 SPI(Service Provider Interface)机制是一种强大的扩展机制,它允许开发者在运行时动态地替换或增加框架的功能。…...
《C++代码高度优化之双刃剑:避免过度优化引发的“暗雷”》
在 C编程的世界里,追求高效性能的代码是每个开发者的目标之一。高度优化的 C代码可以带来显著的性能提升,让程序在运行速度、内存占用等方面表现出色。然而,正如一把双刃剑,过度优化可能会引入难以察觉的错误,给程序带…...
javascript网页设计案例
设计一个具有良好用户体验的 JavaScript 网页涉及多个方面,如用户界面(UI)、用户体验(UX)、交互设计等。以下是一些示例案例,展示了如何使用 JavaScript 创建功能丰富且吸引人的网页设计。 1. 响应式导航菜…...
初阶数据结构【TOP】- 11.普通二叉树的介绍 - 1. (细致,保姆~~!)
文章目录 前言一、普通二叉树的链式结构二、 造树三、普通二叉树的遍历四、遍历完整代码五、总结 前言 本篇文章笔者将会对普通二叉树部分进行细致的讲解 , 本篇主要包括以下内容: 二叉树链式结构的介绍 ,二叉树的遍历. 笔者会一步一步分析带学者领略递归的美好~~ 一、普通二叉…...
【pyenv】pyenv安装版本超时的解决方案
目录 1、现象 2、分析现象 3、手动下载所需版本 4、存放到指定路径 5、重新安装 6、pip失败(做个记录,未找到原因) 7、方法二修改环境变量方法 7.1 设置环境变量 7.2 更新 7.3 安装即可 8、方法三修改XML文件 前言:研…...
【新片场-注册安全分析报告-无验证方式导致安全隐患】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…...
新160个crackme - 057-bbbs-crackme04
运行分析 因软件版本老旧,需使用windows XP虚拟机运行有个SystemID,值为12345678需破解User ID和Password PE分析 yC壳,32位 OD手动脱壳 使用windows XP虚拟机,将程序拖入OD按一下F8,ESP变红,根据ESP定律设…...
车机中 Android Audio 音频常见问题分析方法实践小结
文章目录 前言1. 无声2. 断音3. 杂音4. 延迟播放5. 焦点问题6. 无声问题(连上 BT )其他完善中…… 前言 本文主要总结了一下车机开发中遇到的 Audio 有关的问题,同时参考网上的一案例,由于Audio 模块出现音频问题的场景很多,对每一个出现的问…...
湘大 OJ 代码仓库
有时候不需要上传一些题解,想要上传一些纯代码就行,傻傻把代码上传到文章里面,感觉效率不是很高,还是建立一个代码仓库比较方便 需要会使用魔法可能才能访问,github代码仓库地址...
Ruoyi Cloud K8s 部署
本文视频版本:https://www.bilibili.com/video/BV1xF4Se3Esv 参考 https://blog.csdn.net/Equent/article/details/137779505 https://blog.csdn.net/weixin_48711696/article/details/138117392 https://zhuanlan.zhihu.com/p/470647732 https://gitee.com/y_project/Ruo…...
OpenGL Texture C++ Camera Filter滤镜
基于OpenGL Texture纹理的强大功能,在片段着色器(Shader)中编写GLSL代码,对YUV的数据进行数据转换从而实现视频编辑软件中的相机滤镜功能。 接上一篇OpenGL Texture C 预览Camera视频的功能实现,本篇来实现Camera滤镜效…...
基于Sobel算法的边缘检测设计与实现
1、边缘检测 针对的时灰度图像,顾名思义,检测图像的边缘,是针对图像像素点的一种计算,目的时标识数字图像中灰度变化明显的点,图像的边缘检测,在保留了图像的重要结构信息的同时,剔除了可以认为…...
java:练习
编写一个 Java 程序,计算并输出从 1 到用户指定的数字 n 中,所有“幸运数字”。幸运数字的定义如下:条件 1:数字的所有位数(如个位、十位)加起来的和是 7 的倍数。条件 2:数字本身是一个质数&am…...
大数据中一些常用的集群启停命令
文章目录 一、HDFS二、MapReduce && YARN三、Hive 一、HDFS 格式化namenode # 确保以hadoop用户执行 su - hadoop # 格式化namenode hadoop namenode -format启动 # 一键启动hdfs集群 start-dfs.sh # 一键关闭hdfs集群 stop-dfs.sh# 如果遇到命令未找到的错误&#…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
goreplay
1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具,可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长,测试它所需的工作量也会呈指数级增长。GoRepl…...
StarRocks 全面向量化执行引擎深度解析
StarRocks 全面向量化执行引擎深度解析 StarRocks 的向量化执行引擎是其高性能的核心设计,相比传统行式处理引擎(如MySQL),性能可提升 5-10倍。以下是分层拆解: 1. 向量化 vs 传统行式处理 维度行式处理向量化处理数…...
