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

Linux-进程间通信(IPC)

进程间通信(IPC)介绍

进程间通信(IPC,InterProcess Communication)是指在不同的进程之间传播或交换信息。IPC 的方式包括管道(无名管道和命名管道)、消息队列、信号量、共享内存、Socket、Streams 等。其中 Socket 和 Streams 支持不同主机上的两个进程间通信。

1. 管道

1.1 无名管道

1.1.1 特点
  • 它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
  • 它只能用于父子进程之间的通信。
  • 管道是创建在内存中,进程结束空间释放,管道不复存在。对于它的读写可以使用普通的 readwrite 等函数。
1.1.2 函数原型
#include <unistd.h>
int pipe(int pipefd[2]);
1.1.3 返回值

成功返回 0,失败返回 -1。当一个管道建立时,它会创建两个文件描述符:fd[0] 为读而打开,fd[1] 为写而打开。

1.1.4 无名管道代码示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main() {int fd[2];int pid;char buf[128];if (pipe(fd) == -1) {printf("create pipe fail\n");}pid = fork();if (pid < 0) {printf("create child fail\n");} else if (pid > 0) {sleep(3);printf("this is father\n");close(fd[0]);write(fd[1], "hello from father", strlen("hello from father"));wait(NULL);} else {printf("this is child\n");close(fd[1]);read(fd[0], buf, 128);printf("read = %s \n", buf);exit(0);}return 0;
}

注意:管道的特性:管道里没有数据时会阻塞。

1.2 命名管道

1.2.1 特点
  • 命名管道可以在无关的进程之间交换数据,与无名管道不同。
  • 命名管道有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。
1.2.2 函数原型
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
1.2.3 命名管道代码示例

read.c

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fd;char buf[128] = {0};if (mkfifo("./file", 0600) == -1 && errno != EEXIST) {printf("mkfifo fail\n");perror("why");}fd = open("./file", O_RDONLY);printf("read open success\n");while (1) {int n_read = read(fd, buf, 128);printf("read %d byte, context = %s \n", n_read, buf);}close(fd);return 0;
}

write.c

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fd;char *str = "message from fifo";fd = open("./file", O_WRONLY);printf("write open success\n");while (1) {write(fd, str, strlen(str));sleep(1);}close(fd);return 0;
}

2. 消息队列

消息队列是信息的链接表,存放在内核中。一个消息队列由一个标识符(即队列 ID)来标识。

2.1 特点

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

2.2 函数原型

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

2.3 消息队列代码示例

send.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>struct msgbuf {long mtype;char mtext[128];
};int main() {struct msgbuf sendBuf = {888, "this is msg from queue"};struct msgbuf readBuf;key_t key = ftok(".", 1);printf("key=%d\n", key);int msgId = msgget(key, IPC_CREAT | 0777);if (msgId == -1) {perror("why:");}while (1) {msgsnd(msgId, &sendBuf, strlen(sendBuf.mtext), 0);sleep(1);printf("write success\n");msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 988, 0);sleep(1);printf("read from queue: %s\n", readBuf.mtext);}msgctl(msgId, IPC_RMID, NULL);return 0;
}

read.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>struct msgbuf {long mtype;char mtext[128];
};int main() {struct msgbuf readBuf;struct msgbuf sendBuf = {988, "this is msg from father"};key_t key = ftok(".", 1);printf("key=%d\n", key);int msgId = msgget(key, IPC_CREAT | 0777);if (msgId == -1) {perror("why:");}while (1) {msgrcv(msgId, &readBuf, sizeof(readBuf.mtext), 888, 0);sleep(1);printf("read from queue: %s\n", readBuf.mtext);msgsnd(msgId, &sendBuf, strlen(sendBuf.mtext), 0);sleep(1);printf("write success\n");}msgctl(msgId, IPC_RMID, NULL);return 0;
}

3. 信号

3.1 信号的处理

信号的处理有三种方法:忽略、捕捉和默认动作。具体的信号默认动作可以使用 man 7 signal 来查看系统的具体定义。

3.2 信号处理函数的注册

信号处理函数的注册可以分为入门版和高级版:

  • 入门版:signal 函数
  • 高级版:sigaction 函数

3.3 信号处理发送函数

信号发送函数也分为入门版和高级版:

  • 入门版:kill
  • 高级版:sigqueue

3.4 signal 函数原型及示例

#include <signal.h>typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

示例

#include <signal.h>
#include <stdio.h>void handler(int signum) {printf("get signum = %d\n", signum);switch (signum) {case SIGINT:printf("SIGINT\n");break;case SIGKILL:printf("SIGKILL\n");break;case SIGUSR1:printf("SIGUSR1\n");break;}
}int main() {signal(SIGINT, handler);signal(SIGKILL, handler);signal(SIGUSR1, handler);while (1);return 0;
}

3.5 kill 函数原型及示例

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>int main(int argc, char **argv) {int signum = atoi(argv[1]);int pid = atoi(argv[2]);printf("signum = %d , pid = %d \n", signum, pid);kill(pid, signum);printf("send signal ok\n");return 0;
}

4. 信号量

信号量(semaphore)是一个计数器,用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

4.1 特点

  • 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
  • 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
  • 支持信号量组。

4.2 函数原型

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semctl(int semid, int semnum, int cmd, ...);

4.3 信号量代码示例

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>//联合体,用于 semctl 初始化
union semun {int val;struct semid_ds *buf;unsigned short *array;
};void pGetKey(int id) {struct sembuf set;set.sem_num = 0;set.sem_op = -1;set.sem_flg = SEM_UNDO;semop(id, &set, 1);printf("get key\n");
}void pPutBackKey(int id) {struct sembuf set;set.sem_num = 0;set.sem_op = 1;set.sem_flg = SEM_UNDO;semop(id, &set, 1);printf("put back the key\n");
}int main() {int semid;key_t key = ftok(".", 2);//1. 获取或创建信号量semid = semget(key, 1, IPC_CREAT | 0666);union semun initsem;initsem.val = 0;//2. 初始化信号量semctl(semid, 0, SETVAL, initsem);int pid = fork();if (pid > 0) {//4. 拿锁pGetKey(semid);printf("this is father\n");//5. 还锁pPutBackKey(semid);//6. 销毁锁semctl(semid, 0, IPC_RMID);} else if (pid == 0) {printf("this is child\n");//3. 放锁pPutBackKey(semid);} else {printf("fork error\n");}return 0;
}

5. 共享内存

共享内存(shared memory)指两个或多个进程共享一个给定的存储区。

5.1 特点

  • 共享内存是最快的一种 IPC,因为进程是直接对内存进行存储,而不需要任何数据的拷贝。
  • 只能单独一个进程写或读,如果 A 和 B 进程同时写,会造成数据的混乱(需要搭配信号量来使用)。

5.2 函数原型

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

5.3 共享内存代码示例

shm_write.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main() {int shmid;char *shmaddr;key_t key = ftok(".", 1);// 创建共享内存shmid = shmget(key, 1024 * 4, IPC_CREAT | 0600);if (shmid == -1) {printf("create shm fail\n");exit(-1);}// 连接映射共享内存shmaddr = shmat(shmid, 0, 0);printf("shmat OK\n");// 将数据拷贝到共享内存strcpy(shmaddr, "hello world\n");sleep(5); // 等待 5 秒,避免一下子断开连接。等待另外一个进程读完。// 断开共享内存连接shmdt(shmaddr);// 删除共享内存shmctl(shmid, IPC_RMID, 0);printf("quit\n");return 0;
}

shm_get.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main() {int shmid;char *shmaddr;key_t key = ftok(".", 1);// 打开共享内存shmid = shmget(key, 1024 * 4, 0);if (shmid == -1) {printf("create shm fail\n");exit(-1);}// 连接并映射共享内存shmaddr = shmat(shmid, 0, 0);printf("get from shm_write message is: %s", shmaddr);// 断开共享内存连接shmdt(shmaddr);printf("quit\n");return 0;
}

6. 结合消息队列、共享内存、信号量的示例

6.1 代码示例

get.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <string.h>// 消息队列结构
struct msg_form {long mtype;char mtext;
};// 联合体,用于 semctl 初始化
union semun {int val;struct semid_ds *buf;unsigned short *array;
};// 初始化信号量
int init_sem(int sem_id, int value) {union semun tmp;tmp.val = value;if (semctl(sem_id, 0, SETVAL, tmp) == -1) {perror("Init Semaphore Error");return -1;}return 0;
}// P 操作
int sem_p(int sem_id) {struct sembuf sbuf;sbuf.sem_num = 0;sbuf.sem_op = -1;sbuf.sem_flg = SEM_UNDO;if (semop(sem_id, &sbuf, 1) == -1) {perror("P operation Error");return -1;}return 0;
}// V 操作
int sem_v(int sem_id) {struct sembuf sbuf;sbuf.sem_num = 0;sbuf.sem_op = 1;sbuf.sem_flg = SEM_UNDO;if (semop(sem_id, &sbuf, 1) == -1) {perror("V operation Error");return -1;}return 0;
}// 删除信号量集
int del_sem(int sem_id) {union semun tmp;if (semctl(sem_id, 0, IPC_RMID, tmp) == -1) {perror("Delete Semaphore Error");return -1;}return 0;
}// 创建一个信号量集
int create_sem(key_t key) {int sem_id;if ((sem_id = semget(key, 1, IPC_CREAT | 0666)) == -1) {perror("semget error");exit(-1);}init_sem(sem_id, 1);  // 初值设为 1 资源未占用return sem_id;
}int main() {key_t key;int shmid, semid, msqid;char *shm;struct shmid_ds buf1;  // 用于删除共享内存struct msqid_ds buf2;  // 用于删除消息队列struct msg_form msg;   // 消息队列用于通知对方更新了共享内存// 获取 key 值if ((key = ftok(".", 'z')) < 0) {perror("ftok error");exit(1);}// 创建共享内存if ((shmid = shmget(key, 1024, IPC_CREAT | 0666)) == -1) {perror("Create Shared Memory Error");exit(1);}// 连接共享内存shm = (char *)shmat(shmid, 0, 0);if ((int)shm == -1) {perror("Attach Shared Memory Error");exit(1);}// 创建消息队列if ((msqid = msgget(key, IPC_CREAT | 0777)) == -1) {perror("msgget error");exit(1);}// 创建信号量semid = create_sem(key);// 读数据while (1) {msgrcv(msqid, &msg, 1, 888, 0);  // 读取类型为 888 的消息if (msg.mtext == 'q')  // quit - 跳出循环break;if (msg.mtext == 'r')  // read - 读共享内存{sem_p(semid);printf("%s\n", shm);sem_v(semid);}}// 断开连接shmdt(shm);// 删除共享内存、消息队列、信号量shmctl(shmid, IPC_RMID, &buf1);msgctl(msqid, IPC_RMID, &buf2);del_sem(semid);return 0;
}

send.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <string.h>// 消息队列结构
struct msg_form {long mtype;char mtext;
};// 联合体,用于 semctl 初始化
union semun {int val;struct semid_ds *buf;unsigned short *array;
};// P 操作
int sem_p(int sem_id) {struct sembuf sbuf;sbuf.sem_num = 0;sbuf.sem_op = -1;sbuf.sem_flg = SEM_UNDO;if (semop(sem_id, &sbuf, 1) == -1) {perror("P operation Error");return -1;}return 0;
}// V 操作
int sem_v(int sem_id) {struct sembuf sbuf;sbuf.sem_num = 0;sbuf.sem_op = 1;sbuf.sem_flg = SEM_UNDO;if (semop(sem_id, &sbuf, 1) == -1) {perror("V operation Error");return -1;}return 0;
}int main() {key_t key;int shmid, semid, msqid;char *shm;struct msg_form msg;int flag = 1;  // while 循环条件// 获取 key 值if ((key = ftok(".", 'z')) < 0) {perror("ftok error");exit(1);}// 获取共享内存if ((shmid = shmget(key, 1024, 0)) == -1) {perror("shmget error");exit(1);}// 连接共享内存shm = (char *)shmat(shmid, 0, 0);if ((int)shm == -1) {perror("Attach Shared Memory Error");exit(1);}// 创建消息队列if ((msqid = msgget(key, 0)) == -1) {perror("msgget error");exit(1);}// 获取信号量if ((semid = semget(key, 0, 0)) == -1) {perror("semget error");exit(1);}// 写数据printf("***************************************\n");printf("*                 IPC                 *\n");printf("*    Input r to send data to server.  *\n");printf("*    Input q to quit.                 *\n");printf("***************************************\n");while (flag) {char c;printf("Please input command: ");scanf("%c", &c);switch (c) {case 'r':printf("Data to send: ");sem_p(semid);  // 访问资源scanf("%s", shm);sem_v(semid);  // 释放资源// 清空标准输入缓冲区while ((c = getchar()) != '\n' && c != EOF);msg.mtype = 888;msg.mtext = 'r';  // 发送消息通知服务器读数据msgsnd(msqid, &msg, sizeof(msg.mtext), 0);break;case 'q':msg.mtype = 888;msg.mtext = 'q';msgsnd(msqid, &msg, sizeof(msg.mtext), 0);flag = 0;break;default:printf("Wrong input!\n");// 清空标准输入缓冲区while ((c = getchar()) != '\n' && c != EOF);}}// 断开连接shmdt(shm);return 0;
}

7. 对比总结

通过上述对比可以看出,各种 IPC 方式各有优劣,选择合适的方式进行进程间通信可以提高程序的效率和可靠性。

相关文章:

Linux-进程间通信(IPC)

进程间通信&#xff08;IPC&#xff09;介绍 进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;是指在不同的进程之间传播或交换信息。IPC 的方式包括管道&#xff08;无名管道和命名管道&#xff09;、消息队列、信号量、共享内存、Socket、Stre…...

C++ STL: std::vector与std::array的深入对比

什么是 std::vector 和 std::array 首先&#xff0c;让我们简要介绍一下这两种容器&#xff1a; • std::vector&#xff1a;一个动态数组&#xff0c;可以根据需要动态调整其大小。 • std::array&#xff1a;一个固定大小的数组&#xff0c;其大小在编译时确定。 虽然…...

哈哈看到这条消息感觉就像是打开了窗户

在这个信息爆炸的时代&#xff0c;每一条动态可能成为我们情绪的小小触发器。今天&#xff0c;当我无意间滑过那条由杜海涛亲自发布的“自曝式”消息时&#xff0c;不禁心头一颤——如果这是我的另一半&#xff0c;哎呀&#xff0c;那画面&#xff0c;简直比烧烤摊还要“热辣”…...

10、matlab中字符、数字、矩阵、字符串和元胞合并为字符串并将字符串以不同格式写入读出excel

1、前言 在 MATLAB 中&#xff0c;可以使用不同的数据类型&#xff08;字符、数字、矩阵、字符串和元胞&#xff09;合并为字符串&#xff0c;然后将字符串以不同格式写入 Excel 文件。 以下是一个示例代码&#xff0c;展示如何将不同数据类型合并为字符串&#xff0c;并以不…...

如何正确面对GPT-5技术突破

随着人工智能技术的快速发展&#xff0c;预训练语言模型在自然语言处理领域取得了显著的成果。其中&#xff0c;GPT系列模型作为代表之一&#xff0c;受到了广泛关注。2023年&#xff0c;GPT-5模型的发布引起了业界的热烈讨论。本文将从以下几个方面分析GPT-5的发布及其对人工智…...

HarmonyOS ArkUi 官网踩坑:单独隐藏导航条无效

环境&#xff1a; 手机&#xff1a;Mate 60 Next版本&#xff1a; NEXT.0.0.26 导航条介绍 导航条官网设计指南 setSpecificSystemBarEnabled 设置实际效果&#xff1a; navigationIndicator&#xff1a;隐藏导航条无效status&#xff1a;会把导航条和状态栏都隐藏 官方…...

解决跨域问题(vite、axios/koa)

两种方法选其一即可 一、后端koa设置中间件 app.use(async (ctx, next)> {ctx.set(Access-Control-Allow-Origin, *);ctx.set(Access-Control-Allow-Headers, Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild);ctx.set(Access-C…...

echarts实现3D柱状图(视觉层面)

一、第一种效果 效果图 使用步骤 完整实例&#xff0c;copy就可直接使用 <template><div :class"className" :style"{height:height,width:width}" /> </template><script>import echarts from echartsrequire(echarts/theme/…...

K8S集群进行分布式负载测试

使用K8S集群执行分布式负载测试 本教程介绍如何使用Kubernetes部署分布式负载测试框架&#xff0c;该框架使用分布式部署的locust 产生压测流量&#xff0c;对一个部署到 K8S集群的 Web 应用执行负载测试&#xff0c;该 Web 应用公开了 REST 格式的端点&#xff0c;以响应传入…...

20.《C语言》——【移位操作符】

&#x1f339;开场语 亲爱的读者&#xff0c;大家好&#xff01;我是一名正在学习编程的高校生。在这个博客里&#xff0c;我将和大家一起探讨编程技巧、分享实用工具&#xff0c;并交流学习心得。希望通过我的博客&#xff0c;你能学到有用的知识&#xff0c;提高自己的技能&a…...

你想活出怎样的人生?

hi~好久不见&#xff0c;距离上次发文隔了有段时间了&#xff0c;这段时间&#xff0c;我是裸辞去感受了一下前端市场的水深火热&#xff0c;那么这次咱们不聊技术&#xff0c;就说一说最近这段时间的经历和一些感触吧。 先说一下自己的个人情况&#xff0c;目前做前端四年&am…...

py黑帽子学习笔记_burp

配置burp kali虚机默认装好了社区版burp和java&#xff0c;其他os需要手动装 burp是用java&#xff0c;还得下载一个jython包&#xff0c;供burp用 配apt国内源&#xff0c;然后apt install jython --download-only&#xff0c;会只下载包而不安装&#xff0c;下载的目录搜一…...

selenium,在元素块下查找条件元素

def get_norms_ele_text(self):elementsself.get_norms_elements()locBy.CSS_SELECTOR,"div.sku-select-row-label"by loc[0] # 获取By类型&#xff0c;例如By.CSS_SELECTORvalue loc[1] # 获取具体的CSS选择器字符串&#xff0c;例如"div.sku-select-row-l…...

认识String类

文章目录 String类字符串的遍历字符串的比较字符串的替换字符串的转换字符串的切割字符串的切片字符串的查找 总结 String类 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能使用字符数组或者字符指针&#xff0c;可以使用标准库提 供的字符串系列函数完…...

计算机图形学入门23:蒙特卡洛路径追踪

1.前言 前面几篇文章介绍了Whitted-style光线追踪&#xff0c;还介绍了基于物理渲染的基础知识&#xff0c;包括辐射度量学、BRDF以及渲染方程&#xff0c;但并没有给出解渲染方程的方法&#xff0c;或者说如何通过该渲染方程计算出屏幕上每一个坐标的像素值。 Whitted-style光…...

探索 TensorFlow 模型的秘密:TensorBoard 详解与实战

简介 TensorBoard 是 TensorFlow 提供的可视化工具&#xff0c;帮助开发者监控和调试机器学习模型。它提供了多种功能&#xff0c;包括查看损失和精度曲线、可视化计算图、检查数据分布等。下面将介绍如何使用 TensorBoard。 1. 安装 TensorBoard 如果尚未安装 TensorBoard&…...

yolov8obb角度预测原理解析

预测头 ultralytics/nn/modules/head.py class OBB(Detect):"""YOLOv8 OBB detection head for detection with rotation models."""def __init__(self, nc80, ne1, ch()):"""Initialize OBB with number of classes nc and la…...

CICD之Git版本管理及基本应用

CICD:持续集成,持续交付--让对应的资料,对应的项目流程更加规范--提高效率 CICD 有很多的工具 GIT就是其中之一 1.版本控制概念与环境搭建 GIT的概念: Git是一款分布式源代码管理工具(版本控制工具) ,一个协同的工具。 Git得其数据更像是一系列微型文件系统的快照。使用Git&am…...

Python作用域及其应用

Python的作用域规则决定了变量在代码中的可见性和访问性。全局作用域中定义的变量可以在整个程序中访问&#xff0c;而局部作用域中定义的变量则只能在其被创建的函数或代码块中访问。 全局作用域与局部作用域 全局作用域中的变量通常在程序的顶层定义&#xff0c;可以被整个…...

谷歌上架,应用被Google play下架之后,活跃用户会暴跌?这是为什么?

在Google play上架应用&#xff0c;开发者们最不想到看到就是应用被下架了。这意味着所有的努力都将付诸东流&#xff0c;因为有的应用一但被下架&#xff0c;活跃用户也随之嗖嗖地往下掉&#xff0c;这事儿可真不是闹着玩的&#xff0c;严重影响了收益&#xff01; 为什么你的…...

web安全渗透测试十大常规项(一):web渗透测试之Fastjson反序列化

渗透测试之Java反序列化 1. Fastjson反序列化1.1 FastJson反序列化链知识点1.2 FastJson反序列化链分析1.3.1 FastJson 1.2.24 利用链分析1.3.2 FastJson 1.2.25-1.2.47 CC链分析1.3.2.1、开启autoTypeSupport:1.2.25-1.2.411.3.2.2 fastjson-1.2.42 版本绕过1.3.2.3 fastjson…...

Unity 3D软件下载安装;Unity 3D游戏制作软件资源包获取!

Unity3D&#xff0c;它凭借强大的功能和灵活的特性&#xff0c;在游戏开发和互动内容创作领域发挥着举足轻重的作用。 作为一款顶尖的游戏引擎&#xff0c;Unity3D内置了先进的物理引擎——PhysX。这一物理引擎堪称业界翘楚&#xff0c;能够为开发者提供全方位、高精度的物理模…...

PyTorch之nn.Module与nn.functional用法区别

文章目录 1. nn.Module2. nn.functional2.1 基本用法2.2 常用函数 3. nn.Module 与 nn.functional3.1 主要区别3.2 具体样例&#xff1a;nn.ReLU() 与 F.relu() 参考资料 1. nn.Module 在PyTorch中&#xff0c;nn.Module 类扮演着核心角色&#xff0c;它是构建任何自定义神经网…...

2024.06.24 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、校招 | 昂瑞微2025届校园招聘正式启动 校招 | 昂瑞微2025届校园招聘正式启动 2、实习 | 东风公司研发总院暑期实习生火爆招募中 实习 | 东风公司研发总院暑期实习生火爆招募中 3、实习…...

【C++】using namespace std 到底什么意思

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文作为 JohnKi 的学习笔记&#xff0c;引用了部分大佬的案例 &#x1f4e2;未来很长&a…...

基于ESP32 IDF的WebServer实现以及OTA固件升级实现记录(三)

经过前面两篇的前序铺垫&#xff0c;对webserver以及restful api架构有了大体了解后本篇描述下最终的ota实现的代码以及调试中遇到的诡异bug。 eps32的实际ota实现过程其实esp32官方都已经基本实现好了&#xff0c;我们要做到无非就是把要升级的固件搬运到对应ota flash分区里面…...

116-基于5VLX110T FPGA FMC接口功能验证6U CPCI平台

一、板卡概述 本板卡是Xilinx公司芯片V5系列芯片设计信号处理板卡。由一片Xilinx公司的XC5VLX110T-1FF1136 / XC5VSX95T-1FF1136 / XC5VFX70T-1FF1136芯片组成。FPGA接1片DDR2内存条 2GB&#xff0c;32MB Nor flash存储器&#xff0c;用于存储程序。外扩 SATA、PCI、PCI expres…...

Android - Json/Gson

Json数据解析 json对象&#xff1a;花括号开头和结尾&#xff0c;中间是键值对形式————”属性”:属性值”” json数组&#xff1a;中括号里放置 json 数组&#xff0c;里面是多个json对象或者数字等 JSONObject 利用 JSONObject 解析 1.创建 JSONObject 对象&#xff0c;传…...

盲信号处理的发展现状

盲源分离技术最早在上个世纪中期提出&#xff0c;在1991年Herault和Jutten提出基于反馈神经网络的盲源分离方法&#xff0c;但该方法缺乏理论基础&#xff0c;后来Tong和Liu分析了盲源分离问题的可辨识性和不确定性&#xff0c;Cardoso于1993年提出了基于高阶统计的联合对角化盲…...

二轴机器人装箱机:重塑物流效率,精准灵活,引领未来装箱新潮流

在现代化物流领域&#xff0c;高效、精准与灵活性无疑是各大企业追求的核心目标。而在这个日益追求自动化的时代&#xff0c;二轴机器人装箱机凭借其较佳的性能和出色的表现&#xff0c;正逐渐成为装箱作业的得力助手&#xff0c;引领着未来装箱新潮流。 一、高效&#xff1a;重…...

使用python做飞机大战

代码地址: 点击跳转...

Python面向对象编程:派生

本套课在线学习视频&#xff08;网盘地址&#xff0c;保存到网盘即可免费观看&#xff09;&#xff1a; ​​https://pan.quark.cn/s/69d1cc25d4ba​​ 面向对象编程&#xff08;OOP&#xff09;是一种编程范式&#xff0c;它通过将数据和操作数据的方法封装在一起&#xff0…...

华为仓颉编程语言

目录 一、引言 二、仓颉编程语言概述 三、技术特征 四、应用场景 五、社区支持 六、结论与展望 一、引言 随着信息技术的快速发展&#xff0c;编程语言作为软件开发的核心工具&#xff0c;其重要性日益凸显。近年来&#xff0c;华为公司投入大量研发资源&#xff0c;成功…...

【微信小程序开发实战项目】——如何制作一个属于自己的花店微信小程序(2)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…...

解锁数据资产的无限潜能:深入探索创新的数据分析技术,挖掘其在实际应用场景中的广阔价值,助力企业发掘数据背后的深层信息,实现业务的持续增长与创新

目录 一、引言 二、创新数据分析技术的发展 1、大数据分析技术 2、人工智能与机器学习 3、可视化分析技术 三、创新数据分析技术在实际应用场景中的价值 1、市场洞察与竞争分析 2、客户细分与个性化营销 3、业务流程优化与风险管理 4、产品创新与研发 四、案例分析 …...

Bridging nonnull in Objective-C to Swift: Is It Safe?

Bridging nonnull in Objective-C to Swift: Is It Safe? In the world of iOS development, bridging between Objective-C and Swift is a common practice, especially for legacy codebases (遗留代码库) or when integrating (集成) third-party libraries. One importa…...

算法训练 | 图论Part1 | 98.所有可达路径

目录 98.所有可达路径 深度搜索法 98.所有可达路径 题目链接&#xff1a;98. 所有可达路径 文章讲解&#xff1a;代码随想录 深度搜索法 代码一&#xff1a;邻接矩阵写法 #include <iostream> #include <vector> using namespace std; vector<vector<…...

【JVM基础篇】垃圾回收

文章目录 垃圾回收常见内存管理方式手动回收&#xff1a;C内存管理自动回收(GC)&#xff1a;Java内存管理自动、手动回收优缺点 应用场景垃圾回收器需要对哪些部分内存进行回收&#xff1f;不需要垃圾回收器回收需要垃圾回收器回收 方法区的回收代码测试手动调用垃圾回收方法Sy…...

Spark join数据倾斜调优

Spark中常见的两种数据倾斜现象如下 stage部分task执行特别慢 一般情况下是某个task处理的数据量远大于其他task处理的数据量&#xff0c;当然也不排除是程序代码没有冗余&#xff0c;异常数据导致程序运行异常。 作业重试多次某几个task总会失败 常见的退出码143、53、137…...

YOLOv5初学者问题——用自己的模型预测图片不画框

如题&#xff0c;我在用自己的数据集训练权重模型的时候&#xff0c;在训练完成输出的yolov5-v5.0\runs\train\exp2目录下可以看到&#xff0c;在训练测试的时候是有输出描框的。 但是当我引用训练好的best.fangpt去进行预测的时候&#xff0c; 程序输出的图片并没有描框。根据…...

【linux学习---1】点亮一个LED---驱动一个GPIO

文章目录 1、原理图找对应引脚2、IO复用3、IO配置4、GPIO配置5、GPIO时钟使能6、总结 1、原理图找对应引脚 从上图 可以看出&#xff0c; 蜂鸣器 接到了 BEEP 上&#xff0c; BEEP 就是 GPIO5_IO05 2、IO复用 查找IMX6UL参考手册 和 STM32一样&#xff0c;如果某个 IO 要作为…...

Redis分布式锁代码实现详解

引言 在分布式系统中&#xff0c;资源竞争和数据一致性问题常常需要通过锁机制来解决。Redis作为一个高性能的键值存储系统&#xff0c;因其提供的原子操作、丰富的数据结构以及网络延迟低等特点&#xff0c;成为了实现分布式锁的理想选择。本文将详细介绍如何使用Redis来实现…...

Day01-02-gitlab

Day01-02-gitlab 1. 什么是gitlab2. Gitlab vs Github/Gitee3. Gitlab 应用场景4. 架构5. Gitlab 快速上手指南5.0 安装要求5.1 安装Gitlab组件5.3 配置访问url5.6 初始化5.8 登录与查看5.9 汉化5.10 设置密码5.11 目录结构5.12 删除5.13 500 vs 5025.14 重置密码 6. Gitlab用户…...

PyCharm远程开发配置(2024以下版本)

目录 PyCharm远程开发配置 1、清理远程环境 1.1 点击Setting 1.2 进入Interpreter 1.3 删除远程环境 1.4 删除SSH 2、连接远程环境 2.1 点击Close Project 2.2 点击New Project 2.3 项目路径设置 2.4 SSH配置 2.5 选择python3解释器在远程环境的位置 2.6 配置远程…...

解决Ucharts在小程序上的层级过高问题

<qiun-wx-ucharts canvas2d"{{true}}" type"pie" opts"{{rectificationRateOpts}}" chartData"{{rectificationRateData}}" /> 开启2d渲染即可解决&#xff08;在小程序开发工具上看着层级还是高&#xff0c;但是在手机上是正常…...

重保期间的网站安全防护:网站整站锁的应用与实践

标题&#xff1a;重保期间的网站安全防护&#xff1a;网站整站锁的应用与实践 一、引言 在重大活动或事件&#xff08;通常被称为“重保”&#xff09;期间&#xff0c;网站的安全问题尤为突出。由于此时网站的访问量和关注度可能达到高峰&#xff0c;因此也成为了黑客攻击的…...

Qt自定义类型

概述 在使用Qt创建用户界面时&#xff0c;特别是那些具有特殊控件和特性的界面时&#xff0c;开发人员有时需要创建新的数据类型&#xff0c;以便与Qt现有的值类型集一起使用或代替它们。 QSize、QColor和QString等标准类型都可以存储在QVariant对象中&#xff0c;作为基于qo…...

UE4_材质_材质节点_DepthFade

一、DepthFade参数 DepthFade&#xff08;深度消退&#xff09;表达式用来隐藏半透明对象与不透明对象相交时出现的不美观接缝。 项目说明属性消退距离&#xff08;Fade Distance&#xff09;这是应该发生消退的全局空间距离。未连接 FadeDistance&#xff08;FadeDistance&a…...

如何对GD32 MCU进行加密?

GD32 MCU有哪些加密方法呢&#xff1f;大家在平时项目开发的过程中&#xff0c;最后都可能会面临如何对出厂产品的MCU代码进行加密&#xff0c;避免产品流向市场被别人读取复制。 下面为大家介绍GD32 MCU所支持的几种常用的加密方法&#xff1a; 首先GD32 MCU本身支持防硬开盖…...

快速了解GPT-4o和GPT-4区别

GPT-4o简介 在5月14日的OpenAI举行春季发布会上&#xff0c;OpenAI在活动中发布了新旗舰模型“GPT-4o”&#xff01;据OpenAI首席技术官穆里穆拉蒂&#xff08;Muri Murati&#xff09;介绍&#xff0c;GPT-4o在继承GPT-4强大智能的同时&#xff0c;进一步提升了文本、图像及语…...

ABB PPC902AE1013BHE010751R0101控制器 处理器 模块

ABB PPC902AE1013BHE010751R0101 该模块是用于自动化和控制系统的高性能可编程控制器。它旨在与其他自动化和控制设备一起使用&#xff0c;以提供完整的系统解决方案 是一种数字输入/输出模块&#xff0c;提供了高水平的性能和可靠性。它专为苛刻的工业应用而设计&#xff0c…...

虚拟机交叉编译基于ARM平台的opencv(ffmpeg/x264)

背景&#xff1a; 由于手上有一块rk3568的开发板&#xff0c;需要运行yolov5跑深度学习模型&#xff0c;但是原有的opencv不能对x264格式的视频进行解码&#xff0c;这里就需要将ffmpegx264编译进opencv。 但是开发板算力有限&#xff0c;所以这里采用在windows下&#xff0c;安…...

配置linux net.ipv4.ip_forward数据包转发

前言 出于系统安全考虑&#xff0c;在默认情况下&#xff0c;Linux系统是禁止数据包转发的。数据包转发指的是当主机拥有多个网卡时&#xff0c;通过一个网卡接收到的数据包&#xff0c;根据目的IP地址来转发数据包到其他网卡。这个功能通常用于路由器。 如果在Linux系统中需要…...

计算两个经纬度之间的球面距离(基于Mysql和PHP实现)

计算两个经纬度之间的球面距离 1、MySQL实现方式 - 基于空间函数(ST_Distance_Sphere)实现 前置条件&#xff1a;确保您使用的是 MySQL 8.0 或更高版本&#xff0c;因为较早的版本对地理空间的支持有限。 1.1 创建表和索引 说明&#xff1a;设置 location 为 point 类型 #…...

生产力工具|viso常用常见科学素材包

一、科学插图素材网站 一图胜千言&#xff0c;想要使自己的论文或重要汇报更加引人入胜&#xff1f;不妨考虑利用各类示意图和科学插图来辅助研究工作。特别是对于新手或者繁忙的科研人员而言&#xff0c;利用免费的在线科学插图素材库&#xff0c;能够极大地节省时间和精力。 …...

理解SurfaceFlinger在Android中的作用

理解SurfaceFlinger在Android中的作用 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨Android系统中一个关键的组件——SurfaceFlinger&#xff…...

深入分析 Android Activity (三)

文章目录 深入分析 Android Activity (三)1. Activity 的配置变化处理1.1 处理配置变化 2. Activity 的存储和恢复状态2.1 保存状态2.2 恢复状态 3. Activity 与 Fragment 的通信3.1 通过接口进行通信3.2 通过 ViewModel 进行通信 4. Activity 的窗口管理和视图层次结构4.1 Dec…...

aspose-*的使用

文章目录 aspose-*一、依赖--maven二、需求1、word------>pdf2、doc------>docx3、xls------>xlsx aspose-* 一、依赖–maven 备注&#xff1a;第三方的jar包可以从资源中下载&#xff0c;有上传的 <!--aspose依赖--><dependency><groupId>aspose…...

Postman实现批量发送json请求

最近有一个场景&#xff0c;需要本地批量调用某个接口&#xff0c;从文件中读取每次请求的请求体&#xff0c;实现方法记录一下。 1.读取请求体 在 Postman 中&#xff0c;如果你想在 Pre-request Script 阶段读取文件内容&#xff0c;比如为了将文件内容作为请求的一部分发送…...

Jupyter Lab 软件安装与使用

软件简介 Jupyter Lab 软件是一个基于web 的交互式开发环境&#xff0c;集成了代码编辑器、终端、文件管理器等功能&#xff0c;使得开发者可以在一个界面中完成各种任务。JupyterLab是Jupyter Notebook的全面升级&#xff0c;是一个集文本编辑器、终端以及各种个性化组件于一…...

软件系统开发标准流程文档(Word原件)

目的&#xff1a;规范系统开发流程&#xff0c;提高系统开发效率。 立项申请需求分析方案设计方案评审开发调整测试阶段系统培训试运行测试验收投入使用 所有文档过去进主页获取。 软件项目相关全套精华资料包获取方式①&#xff1a;点我获取 获取方式②&#xff1a;本文末个人…...

Android Gradle文件 一次通关

前言 Android的Gradle是每个项目一定包含的文件&#xff0c;用来定义构建配置的脚本文件&#xff0c;通常包括两个主要文件&#xff1a;build.gradle&#xff08;项目级别&#xff09;和build.gradle&#xff08;模块级别&#xff09;。 项目级别的 build.gradle 文件 项目级…...