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

Linux:进程间通信

文章目录

  • 前言
  • 一、进程间通信介绍
    • 1.1 进程间通信的目的
    • 1.2 进程间通信的发展与分类
  • 二、管道
    • 2.1 匿名管道原理
    • 2.2 通信管道会出现的情况和特性(重要)
    • 2.3 命名管道
      • 2.3.1 命名管道与匿名管道的区别
  • 三、system V
    • 3.1 共享内存原理
    • 3.2 键值
      • 3.2.1 键值生成原理
    • 3.3 共享内存相关接口函数创建信道
    • 3.4 简略介绍其余IPC和代码结构(仅作了解)
      • 3.4.1 消息队列
      • 3.4.2 代码数据结构
  • 四、system V 信号量
    • 4.1 并发编程,铺垫概念
    • 4.2 信号量
    • 4.3信号量接口和系统调用
  • 五、内核中的system V资源管理
  • 总结


前言

进程间通信其实就是让不同进程看到同一份资源的思想,然后设计不同的模式或者数据结构来达到这一目的


一、进程间通信介绍

1.1 进程间通信的目的

由于进程地址空间的独立性设计,我们在面对下面情况时需要一种机制来实现进程间的交互,这便是进程间通信的目的

  • 数据传输:⼀个进程需要将它的数据发送给另⼀个进程
  • 资源共享:多个进程之间共享同样的资源。
  • 通知事件:⼀个进程需要向另⼀个或⼀组进程发送消息,通知它(它们)发⽣了某种事件(如进
    程终⽌时要通知⽗进程)。
  • 进程控制:有些进程希望完全控制另⼀个进程的执⾏(如Debug进程),此时控制进程希望能够
    拦截另⼀个进程的所有陷⼊和异常,并能够及时知道它的状态改变。

1.2 进程间通信的发展与分类

  • 管道
  1. 匿名管道pipe
  2. 命名管道
  • System_V进程间通信
  1. System_V 消息队列
  2. • System_V 共享内存
  3. • System_V 信号量
  • POSIX进程间通信
  1. 消息队列
  2. 共享内存
  3. 信号量
  4. 互斥量
  5. 条件变量
  6. 读写锁

二、管道

2.1 匿名管道原理

管道是Unix最古老的进程间通信方式,管道是在内核空间中开辟的,管道的数据存储在内核的一个环形缓冲区中(因此匿名管道的本质是由内核在内存中维护的一个文件)!一般发生在父子进程的通信使用中
在这里插入图片描述当父进程创建子进程的时候,会进行数据上的浅拷贝,所以子进程也拥有父进程相同的指针,它们共同指向相同的文件(也就是拥有相同的文件描述符表),因此它们能使用同一个管道,并且管道是单向的,意味着两个进程只能有一个能读,另一个只能写
在这里插入图片描述

#include <iostream>
#include<unistd.h>
#include<cstdio>
#include<cstring>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;void ChildWrit(const int wfd)
{char buffer[1024];int cnt=0;while(true){//snprintf是C语言的字符串处理函数,在需要读取的字符串末尾会自动添加/0,//而下面的read函数是系统级别的函数,所以在处理字符串的时候需要我们需要预留一个字节空间来添加/0snprintf(buffer,sizeof(buffer),"i am child,witing now,my pid:%d,cnt:%d",getpid(),cnt++);write(wfd,buffer,strlen(buffer));sleep(1);}}
void FatherRead(const int rfd)
{char buffer[1024];while(true){buffer[0]=0;ssize_t n=read(rfd,buffer,sizeof(buffer)-1);if(n>0){buffer[n]=0;cout<<"child say:"<<buffer<<endl;}else if(n==0){}}
}
int main() {//创建管道int fds[2]={0};int n=pipe(fds);if(n<0){cout<<"pipe error"<<endl;}else{cout<<"fds[0]"<<fds[0]<<endl;cout<<"fds[1]"<<fds[1]<<endl;}//创建子进程//关闭读写端形成单向通信信道pid_t id=fork();if(id==0){close(fds[0]);//子进程在写的时候,父进程会阻塞在read函数上面等待读取ChildWrit(fds[1]);exit(0);}close(fds[1]);FatherRead(fds[0]);waitpid(id,nullptr,0);cout<<"test pipe"<<endl;return 0;
}

2.2 通信管道会出现的情况和特性(重要)

  1. 读的慢,写端要等读端
  2. 读端关闭,写端收到SIGPIPE信号直接终止
  3. 写端不写或写的慢,读端要等写端
  4. 写端关闭,读端读完pipe内部的数据然后再读,会读到0,表明读到文件结尾

其中情况1,2,3都是基于Linux下的read,write等函数的特性进行的,而情况4则是进程本身的管理

在这里插入图片描述

2.3 命名管道

上面匿名管道能进行带有血缘关系进程的通信,那么接下来的命名管道就可以让两个毫不相关的进程进行通信。
命名管道的性质除了能让任意进程间通信外,与匿名管道基本一致,即创建一个文件(与匿名管道的区别是在磁盘上创建的文件,而匿名管道是内核上创建)一个进程往文件中写数据,一个进程读数据,且不让文件内容刷新到磁盘上(这也是磁盘上的普通文件与管道文件的区别),从而实现任意进程间的通信。

以下是有关在代码层上如何创建一个管道文件,它使用mkfifo()函数,其实在我们用户层上,所谓的管道文件也只不过是特殊的文件罢了,相较于在代码中对普通文件的操作,我们操作有名管道只不过多了创建这一步。
在这里插入图片描述
当一个文件打开命名管道时,无论是读写端,如果另一端没有打开,那么这个文件就会阻塞(卡)在open上!

2.3.1 命名管道与匿名管道的区别

• 匿名管道由pipe函数创建并打开。
• 命名管道由mkfifo函数创建,打开⽤open
• FIFO(命名管道)与pipe(匿名管道)之间唯⼀的区别在它们创建与打开的⽅式不同,⼀但这些⼯作完成之后,它们具有相同的语义。

三、system V

system V是一套 Unix/Linux 系统中进程间通信的标准化机制,,共享内存区是最快的IPC形式。⼀旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执⾏进⼊内核的系统调⽤来传递彼此的数据。

3.1 共享内存原理

共享内存实际上就是通过一定的技术手段来将两个进程的虚拟地址空间进行相连,我们只需要执行一次系统级别上的调用,创建完共享内存后,那么两个进程就能直接传递数据而不依靠内核。
在这里插入图片描述

共享内存没有保护机制(对共享内存中数据的保护),就是两个进程间的数据并不同步。system V 体系通信创建的共享内存它的生命周期随操作系统,所以我们必须手动删除我们创建的共享内存

3.2 键值

在创建信道的过程中我们需要通过某种约定,来达到两个进程可以连接同一块内存的目的,以此键值出现

键值的实现通常依赖于操作系统提供的函数ftok()【file to key】

函数原型:

#include <sys/types.h>
#include <sys/ipc.h>key_t ftok(const char *pathname, int proj_id);

它通过传入文件路径pathname(如“.”),以及proj_id(项目标识符,用于在同一文件的不同场景中生成不同键值),成功时返回生成的 key_t 类型键值,失败返回 -1,并设置 errno(如文件不存在)。失败返回 -1,并设置 errno(如文件不存在)

3.2.1 键值生成原理

  1. 提取文件的 inode 号设备号
  2. proj_id 的低 8 位与 inode 号的低 16 位、设备号的低 16 位组合:key = (proj_id & 0xFF) << 24 | (st_dev & 0xFF) << 16 | (st_ino & 0xFFFF)

3.3 共享内存相关接口函数创建信道

我们学习共享内存并理解只需要将相关函数理解就能大概明白其原理方向

函数作用&&用例
shmget创建或获取共享内存段 int shmid = shmget(key, size, IPC_CREAT 0666);
shmat将共享内存段附加到进程的地址空间 void *shm_ptr = shmat(shmid, NULL, 0);
shmdt将共享内存段从进程地址空间分离 hmdt(shm_ptr);
shmctl控制共享内存段(删除、查询信息等) shmctl(shmid, IPC_RMID, NULL);

shmget 参数:

  • key: 共享内存的唯一标识符,通常用 ftok(“path”, id) 生成。
  • size: 共享内存段大小(字节)。在操作系统中通常为4kb的整数倍大小,但在个人操作空间上是给多少显示多少,操作系统内部实际向上取整
  • flags: 权限标志(如 IPC_CREAT | 0666)。
    取值为IPC_CREAT:共享内存不存在,创建并返回;共享内存已存在,获取并返回。
    取值为IPC_CREAT | IPC_EXCL(不单独存在):共享内存不存在,创建并返回;共享内存已存在,出
    错返回。
key值是共享内存的“身份证”,它是进程间的约定,使不同进程事先通过相同key找到同一块共享内存,属于操作系统层面,而开辟完之后的返回值shmid则是用户层面上操作这块共享内存的标识符,这样做的目的是将用户和操作系统分层以实现解耦合的目的

shmat 返回值:使用标识符将开辟的共享空间关联到虚拟地址。成功返回共享内存的起始地址,失败返回 (void*)-1
参数:
shmid: 共享内存标识
shmaddr:指定连接的地址,通常用null让系统自动返回一个地址
shmflg:一般设置为0,使用shmget中设置的缺省权限
返回值:成功返回⼀个指针,指向共享内存第⼀个节;失败返回-1

shdt:去关联

shmctl 命令:
IPC_RMID: 标记共享内存段为待删除(当所有进程分离后实际删除)。
IPC_STAT: 获取共享内存段的状态信息。
成功返回0,失败返回-1

3.4 简略介绍其余IPC和代码结构(仅作了解)

3.4.1 消息队列

消息队列的技术已经是落后的了,对于我们初学者来说,已经失去了学习的意义,所以仅作了解
在这里插入图片描述

消息队列提供了⼀个从⼀个进程向另外⼀个进程发送⼀块数据的⽅法
• 每个数据块都被认为是有⼀个类型,接收者进程接收的数据块可以有不同的类型值
• 特性⽅⾯
◦ IPC资源必须删除,否则不会⾃动清除,除⾮重启,所以system_V IPC资源的⽣命周期随内核
其中接口函数不作描述。

3.4.2 代码数据结构


struct msqid_ds 
{ struct ipc_perm msg_perm;     /* Ownership and permissions */time_t          msg_stime;    /* Time of last msgsnd(2) */time_t          msg_rtime;    /* Time of last msgrcv(2) */time_t          msg_ctime;    /* Time of last change */unsigned long   __msg_cbytes; /* Current number of bytes inqueue (nonstandard) */msgqnum_t       msg_qnum;     /* Current number of messagesin queue */msglen_t        msg_qbytes;   /* Maximum number of bytesallowed in queue */pid_t           msg_lspid;    /* PID of last msgsnd(2) */pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
};

其中第一个结构体的数据结构如下

struct ipc_perm 
{key_t          __key;       /* Key supplied to msgget(2) */uid_t          uid;         /* Effective UID of owner */gid_t          gid;         /* Effective GID of owner */uid_t          cuid;        /* Effective UID of creator */gid_t          cgid;        /* Effective GID of creator */unsigned short mode;        /* Permissions */unsigned short __seq;       /* Sequence number */
};

操作系统通过维护这种数据结构体来然后通过函数来进行通信

四、system V 信号量

通信的前提是看到同一份资源,那么在对资源进行读写的时候,如果一方开始读了但另一方仅仅把想传输的资源写了一半,那么就会发生数据不一致的情况,但是如果我们加入一种保护机制,例如管道里面通过write和read函数的特性进行阻塞,就可以控制并达到想要的通信结果

4.1 并发编程,铺垫概念

在了解怎么去保护之前,我们需要知道一些概念

  • 临界资源:被多个执行流同时访问的资源,一次只允许一个进程使用。比如管道、共享内存、消息队列、信号量。
  • 临界区:进程中访问临界资源的代码(和临界资源配套)为了保护数据安全,就要把临界区保护起来,就有了信号量。
  • 原子性:一件事情要么做完,要么不做,没有中间状态。
  • IPC资源必须删除,否则不会自动清除,除非重启,所以system V IPC资源的生命周期随内核。

• 多个执⾏流(进程),能看到的同⼀份公共资源:共享资源
• 被保护起来的资源叫做临界资源
• 保护的⽅式常⻅:互斥与同步
• 任何时刻,只允许⼀个执⾏流访问资源,叫做互斥
• 多个执⾏流,访问临界资源的时候,具有⼀定的顺序性,叫做同步
• 系统中某些资源⼀次只允许⼀个进程使⽤,称这样的资源为临界资源或互斥资源。
• 在进程中涉及到互斥资源的程序段叫临界区。你写的代码=访问临界资源的代码(临界区)+不访问临界资源的代码(⾮临界区)
• 所谓的对共享资源进⾏保护,本质是对访问共享资源的代码进⾏保护

在这里插入图片描述

4.2 信号量

信号量是一个抽象概念,有时候也被叫做信号灯,本质上是一个计数器可以先用智能指针中或者文件结构体中的count去理解。信号量初始化的时候用来分割临界资源中资源。所有进程想要访问临界资源中的一小块,就必须申请信号量,本质上就是预定机制。
在这里插入图片描述

信号量同时也是共享资源
  • p操作:申请信号量,对应计数器- -,原子性,如果小于某个阈值,那么就会阻塞
    -v操作: 退出,对应计数器++,原子性

在信号量中只有0和1两态,叫做二元信号量,也就是互斥!
信号量也属于通信,都先访问信号量P,所有进程就都能看到同一个信号量,不是传递数据才属于IPC,通知,同步互斥也算

4.3信号量接口和系统调用

信号量接口的设计跟共享内存大致相同

semget:
在这里插入图片描述
在这里插入图片描述
其中参数key_t以及semflg与共享内存获取函数一致,参数nsems则是想要创建多少个信号量,成功返回信号量级标识符(非0整数),失败返回-1,并设置错误码

semctl:
在这里插入图片描述
在这里插入图片描述
同样是使用对应的标识符然后根据cmd指令进行删除等操作

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semop(int semid, struct sembuf *sops, unsigned nsops);struct sembuf
{unsigned short  sem_num;        /* semaphore index in array */short           sem_op;         /* semaphore operation */short           sem_flg;        /* operation flags */
};
sem_num指定要操作的信号量,0表示第一个信号量,1表示第二个信号量,……
sem_op信号量操作,设置1表示P操作,-1表示V操作
sem_flg操作标识

信号量同样可以用指令查看
在这里插入图片描述

五、内核中的system V资源管理

在OS中,消息队列,共享内存,信号量被当作同一种资源
在这里插入图片描述
内核分配一个ipc_perm数组,用来指向每一个IPC资源。,其实这里是以C语言的方式来实现多态
所以我们通过XXXget函数的返回值拿到的什么shmid,semid,其实就是这个(柔性)数组的下标!==
在这里插入图片描述


总结

本文描述了进程间通信的概念以及相关函数接口,并简略介绍了内核层面上如何管理通信需要的数据,仍有诸多欠缺与文章内容上深度的赘述不足。

相关文章:

Linux:进程间通信

文章目录 前言一、进程间通信介绍1.1 进程间通信的目的1.2 进程间通信的发展与分类 二、管道2.1 匿名管道原理2.2 通信管道会出现的情况和特性&#xff08;重要&#xff09;2.3 命名管道2.3.1 命名管道与匿名管道的区别 三、system V3.1 共享内存原理3.2 键值3.2.1 键值生成原理…...

Mysql配套测试之查询篇

&#x1f3dd;️专栏&#xff1a;Mysql_猫咪-9527的博客-CSDN博客 &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 条件查询简单测试&#xff1a; 1.查询英语成绩不及格的同学(<60) 2…...

基于SSM框架的汽车租赁平台(源码+lw+部署文档+讲解),源码可白嫖!

摘要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;汽车租赁平台当然不能排除在外。汽车租赁平台是在实际应用和软件工程的开发原理之上&#xff0c;运用Java语言以及SSM框架进行开发&#x…...

常考计算机操作系统面试习题(三下)

20. 请求页式存储管理系统缺页率计算 题目&#xff1a; 假设一个作业的页面走向为 1、2、3、4、1、2、5、1、2、3、4、5&#xff0c;当分配给该作业的物理块数分别为 3 和 4 时&#xff0c;计算采用下述页面置换算法的缺页率&#xff1a; (1) 先进先出&#xff08;FIFO&…...

Spring IOC核心详解:掌握控制反转与依赖注入

文章目录 前言一、IOC核心思想二、IOC容器实现1.核心接口&#xff1a;2.XML配置范例 三、Bean管理实践1.创建对象&#xff08;1&#xff09;基于xml方式创建对象&#xff08;2&#xff09;用注解的方式创建对象 2.依赖注入&#xff08;1&#xff09;基于xml方式注入属性基础类型…...

Servlet、HttpServletRequest、HttpServletResponse、静态与动态网页、jsp、重定向与转发

DAY15.2 Java核心基础 JavaWeb 要想通过浏览器或者客户端来访问java程序&#xff0c;必须通过Servlet来处理 没有Servlet&#xff0c;java是无法处理web请求的 Web交互&#xff1a; 接收请求HttpServletRequest&#xff1a;可以获取到请求的信息&#xff0c;比如uri&#…...

Linux 内核源码阅读——ipv4

Linux 内核源码阅读——ipv4 综述 在 Linux 内核中&#xff0c;IPv4 协议的实现主要分布在 net/ipv4/ 目录下。以下是一些关键的源文件及其作用&#xff1a; 1. 协议栈核心 net/ipv4/ip_input.c&#xff1a;处理接收到的 IPv4 数据包&#xff08;输入路径&#xff09;。net…...

组合总和 II:去重逻辑深度解析

组合总和 II&#xff1a;去重逻辑深度解析 在算法中&#xff0c;解决“组合总和 II”这类问题时&#xff0c;去重往往是最具挑战性的一环。如何避免重复组合&#xff0c;同时保证所有组合的唯一性&#xff0c;是实现高效算法的关键。今天&#xff0c;我们就来深度解析组合总和…...

蓝桥杯备考:二分答案之路标设置

最大距离&#xff0c;找最小空旷指数值&#xff0c;我们是很容易想到用二分的&#xff0c;我们再看看这个答案有没有二段性 是有这么个二段性的&#xff0c;我们只要二分就行了&#xff0c;但是二分的check函数是有点不好想的&#xff0c;我们枚举空旷值的时候&#xff0c;为了…...

[HY000][1366] Incorrect string value: ‘张三‘ for column ‘name‘ at row 1

常见原因 字符集不兼容 插入的数据包含当前字符集&#xff08;如 latin1&#xff09;不支持的特殊字符&#xff08;如中文、Emoji 等&#xff09;。 表、列或连接的字符集未正确配置为支持目标字符&#xff08;如未使用 utf8mb4&#xff09;。 客户端/服务端编码不一致 客户…...

什么是C++对象之间的view proxies

在C中&#xff0c;view proxies 是一种轻量级的对象&#xff0c;用于提供对另一个对象的间接访问或视图&#xff0c;而不直接拥有或管理该对象的数据。它们通常用于简化对复杂数据结构的访问&#xff0c;或在不需要复制数据的情况下提供特定的视图。 1. View Proxies 的核心概…...

MyBatis参数赋值技巧:#{} 和 ${} 的区别与实践

目录 一、前言二、 #{} 和${} 的使用方法和区别2.1 #{}使用方法2.2 ${}使用方法2.3#{} 和 ${} 的主要区别2.4使用建议 三、总结 一、前言 在 MyBatis 中&#xff0c;#{} 和 ${} 都用于在 SQL 语句中绑定参数&#xff0c;但它们在具体实现和安全性方面有所不同。理解它们的区别…...

5-1 使用ECharts将MySQL数据库中的数据可视化

方法一&#xff1a;使用Python Flask框架搭建API 对于技术小白来说&#xff0c;使用ECharts将MySQL数据库中的数据可视化需要分步骤完成。以下是详细的实现流程&#xff1a; 一、技术架构‌ 后端服务‌&#xff1a;使用Python Flask框架搭建API&#xff08;简单易学&#xff…...

协程的调度的对称与非对称

下图表示的就是对称协程&#xff0c;进入到该协程之后只能有一个操作就是yield&#xff0c;把cpu让回给调度器; 下图表示非对称协议&#xff0c;可以有两个操作&#xff0c;就是resume和yield&#xff0c;从哪里resume的&#xff0c;yield就会回到该位子&#xff1b;...

C# 中比较实用的关键字,基础高频面试题!

前言 在C#编程中关键字是构建逻辑和实现功能的基石&#xff0c;它承载着编程语言的语法规则和编程智慧。熟练掌握这些基础高频关键字对提升编程能力和面试表现至关重要&#xff0c;它们是日常开发和解决复杂问题的关键。 DotNetGuide 全面的C#/.NET/.NET Core学习、工作、面试指…...

文献分享: XTR——优化Token级检索的高效多向量模型

原文章 文章目录 1. XTR \textbf{1. XTR} 1. XTR原理 1.1. \textbf{1.1. } 1.1. 导论 1.2. XTR \textbf{1.2. XTR} 1.2. XTR的训练和推理 2. \textbf{2. } 2. 实验与分析 2.1. \textbf{2.1. } 2.1. 实验配置与结果 2.2. \textbf{2.2. } 2.2. 结果分析 3. \textbf{3. } 3. 其它分…...

【数据结构】C语言实现树和森林的遍历

C语言实现树和森林的遍历 导读一、树的遍历二、森林的遍历2.1 为什么森林没有后序遍历?2.2 森林中存不存在层序遍历?三、C语言实现3.1 准备工作3.2 数据结构的选择3.3 树与森林的创建3.4 树与森林的遍历3.4.1 先根遍历3.4.2 后根遍历3.4.3 森林的遍历3.5 树与森林的销毁3.6 算…...

《Python深度学习》第七讲:生成式深度学习

在深度学习的世界里,生成式模型是一种非常有趣且富有创造力的技术。它们能够生成全新的内容,比如文本、图像、音乐等,甚至可以创造出从未见过的虚拟世界。这一讲,我们将深入探讨生成式深度学习的核心技术,包括 LSTM 文本生成、DeepDream、神经风格迁移、变分自编码器(VAE…...

Spring的IOC

在现代 Java 开发中&#xff0c;Spring 框架几乎无处不在&#xff0c;特别是其核心的 IOC&#xff08;Inversion of Control&#xff09; 容器&#xff0c;几乎所有Spring的功能都与它紧密相关。 一、什么是IOC IOC&#xff0c;全称为 Inversion of Control&#xff08;控制反…...

常考计算机操作系统面试习题(四)

目录 1. Peterson 算法伪代码 2. 信号量生产者消费者问题分析 3. 注释 Peterson 主函数并分析输出结果 4. 用 fork 创建子进程的程序 1. Peterson 算法伪代码 题目&#xff1a; 写出 Peterson 算法的伪代码。 参考答案&#xff1a; // 定义变量 boolean flag[2]; //…...

Visual Studio Code 连接 SAP ERP 系统

首先确保服务打开 在vscode&#xff0c;在extension安装ABAP remote filesystem&#xff0c;然后打开设置SAP 系统的地址配置 CtrlshiftP 执行代码&#xff1a;AbapFS connect to an ABAP system&#xff0c;可以根据要求一步一步配置。 根据配置。加载系统 也可以直接在extens…...

从报错到成功:Mermaid 流程图语法避坑指南✨

&#x1f680; 从报错到成功&#xff1a;Mermaid 流程图语法避坑指南 &#x1f680; &#x1f6a8; 问题背景 在开发文档或技术博客中&#xff0c;我们经常使用 Mermaid 流程图 来可视化代码逻辑。但最近我在尝试绘制一个 Java Stream 转换流程图时&#xff0c;遭遇了以下报错…...

TDengine 中的 show 命令

简介 SHOW 命令可以用来获取简要的系统信息。若想获取系统中详细的各种元数据、系统信息和状态&#xff0c;请使用 select 语句查询 INFORMATION_SCHEMA 数据库中的表, 详见 元数据查询 SHOW APPS SHOW APPS;显示接入集群的应用&#xff08;客户端&#xff09;信息。 SHOW …...

博弈论中的均衡精炼:完美贝叶斯均衡、序贯均衡与颤抖手均衡详解

博弈论中的均衡精炼&#xff1a;完美贝叶斯均衡、序贯均衡与颤抖手均衡详解 1. 引言&#xff1a;为什么需要均衡精炼&#xff1f; 在博弈论中&#xff0c;纳什均衡是分析策略互动的核心工具&#xff0c;但其存在一个显著缺陷&#xff1a;无法排除不合理的均衡。例如&#xff0…...

github代理 | 快速clone项目

代理网址&#xff1a; https://ghproxy.com/ https://ghproxy.com/代理网址&#xff1a; https://ghproxy.com/ 比如需要克隆的项目git地址为&#xff1a;https://github.com/AUTOMATIC1111/stable-diffusion-webui.git git clone https://ghproxy.com/https://github.com/AUTO…...

C语言基础与进阶学习指南(附运行效果图及术语解析)

C语言基础与进阶学习指南&#xff08;附运行效果图及术语解析&#xff09; 目录 C语言标准与编译流程CPU与内存基础C语言基础语法数据类型详解变量与内存管理运算符与表达式输入输出函数函数与内存管理指针与内存操作结构体与高级应用 1. C语言标准与编译流程 1.1 C语言标准演…...

【Scrapy】Scrapy教程8——处理子链接

通过前面几篇文章,已经了解了如何去爬取网页内容并存储到数据库,但是目前只是存储了一个页面的内容,现在想要获取每篇文章链接内的文章内容,我们来看看怎么获取。 生成新请求 首先我们肯定要先拿到链接,所以第一步都获取文章标题和链接肯定少不了,然后再爬取获取到到子…...

Python推导式深入解析

引言 Python 以其简洁、高效的语法而备受开发者喜爱&#xff0c;其中推导式&#xff08;Comprehensions&#xff09;更是 Python 语法的一大特色。推导式提供了一种简洁明了的方式来创建列表、集合和字典等数据结构&#xff0c;让代码更加紧凑和易读。本文将深入探讨 Python 推…...

在 macOS 上配置 SSH 连接 GitHub

在 macOS 上使用 SSH 连接 GitHub&#xff0c;可以免去每次使用 Git 时输入密码的麻烦&#xff0c;提高开发效率。本文将介绍如何在 macOS 上生成 SSH 密钥并配置 GitHub 进行身份认证。 1. 检查是否已有 SSH 密钥 在终端运行以下命令&#xff0c;检查是否已有 SSH 密钥&#…...

常考计算机操作系统面试习题(二)(中)

目录 24. 操作系统的主要功能有哪些&#xff1f; 25. 文件的属性主要有哪些&#xff1f; 26. 对文件的基本操作主要有哪些&#xff1f; 27. 目录的基本操作有哪些&#xff1f; 28. 目录的逻辑结构有哪些种&#xff1f; 29. 简述银行家算法的Available、Max、Allocation、…...

手机录视频风噪太大?华为Pura X“AI降风噪“太硬核了

你是否也在用手机录像时&#xff0c;比如大海海浪、阅览群山、空旷的原野的时候&#xff0c;呼啸的风总是能沦为刺耳的噪音&#xff0c;让精心构思的镜头&#xff0c;最后因为呼啸的风声最终成为“灾难现场”。传统的解决方式往往陷入两难&#xff1a;物理防风罩影响收音指向性…...

React 事件处理

1. React 事件处理的基本概念 React 事件处理的特点&#xff1a; 驼峰命名法&#xff1a;事件名采用驼峰命名法&#xff0c;如 onClick、onChange。JSX 语法&#xff1a;事件处理函数通过 JSX 传递给元素&#xff0c;如 <button onClick{handleClick}>。合成事件&#…...

搭建React简单项目

一、项目构建 目录结构&#xff1a; 安装脚手架 npm install -g create-react-app // or yarn add -g create-react-app 一、项目版本 1、react&#xff1a;"^18.3.1"&#xff1b; 2、react-router-dom&#xff1a;"^6.23.1"&#xff1b; 3、项目创…...

ROCK 280A-M 工业级电调:高性能无人机动力心脏,重塑严苛场景飞行边界

—— 工业级动力控制系统解决方案 —— 【产品概述】 针对工业级无人机高负载、复杂工况需求&#xff0c;南昌长空科技的ROCK 280A-M 电调以航空级标准打造动力控制中枢。采用工业级控制算法与智能自适应系统&#xff0c;为多旋翼 / 固定翼无人机提供稳定动力支撑&#xff0c;突…...

带你从入门到精通——自然语言处理(十. BERT)

建议先阅读我之前的博客&#xff0c;掌握一定的自然语言处理前置知识后再阅读本文&#xff0c;链接如下&#xff1a; 带你从入门到精通——自然语言处理&#xff08;一. 文本的基本预处理方法和张量表示&#xff09;-CSDN博客 带你从入门到精通——自然语言处理&#xff08;二…...

八股JAVA并发

多线程 线程的创建方式有哪些? 1.继承Thread类 2.实现Runnable接口 3.Callable接口FutureTask 4.线程池 1.继承Thread类 这是最直接的一种方式&#xff0c;用户自定义类继承java.lang.Thread类&#xff0c;重写其run()方法&#xff0c;run()方法中定义了线程执行的具体任务。…...

#include <hello.h> 与 #include “hello.h“的区别

#include <hello.h> 和 #include "hello.h" 在C/C中用于包含头文件&#xff0c;但它们在搜索头文件时的行为有所不同&#xff0c;这可能导致前者找不到头文件的情况。 ### 区别 1. **搜索路径不同** - #include "hello.h"&#xff1a;编译器首先…...

PyPDF2简单介绍

PyPDF2 是一个开源的纯 Python 库&#xff0c;用于读取、操作和创建 PDF 文件。它最初是 PyPDF 的改进版&#xff0c;功能更丰富。 安装&#xff1a; bash pip install PyPDF2核心功能 1.合并 PDF 文件 python from PyPDF2 import PdfMergermerger PdfMerger() merger.appe…...

记录flutter编译项目遇到的问题

目录 1.更换flutter版本 2.解压到指定地址 3.在Android Studio配置 问题: Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source! Resolving dependencies... The current Dart SDK version is 3.3.0. Because coach d…...

小米AX6000上安装tailscale

在之前的文章中&#xff0c;已经介绍了如何解锁ax6000的ssh&#xff0c;以及必坑指南。 今天突发奇想&#xff0c;为了不让我的nas天天开着tailscale&#xff0c;所以我想让我的tailscale运行在路由器&#xff0c;这样完美实现穿透。 首先&#xff0c;通过ssh登录ax6000&#x…...

git使用经验(一)

git使用经验&#xff08;一&#xff09; 我之前已经下载了别人的代码&#xff0c;我想在此基础上进行修改&#xff0c;并移动到自己的私有仓库&#xff0c;方便上传到自己的私有仓库自己进行版本控制 git clone下来别人的代码&#xff0c;删除有关git的隐藏文件 进入到自己的…...

C语言【文件操作】详解中

引言 介绍和文件操作中文件的顺序读写相关的函数 看这篇博文前&#xff0c;希望您先仔细看一下这篇博文&#xff0c;理解一下文件指针和流的概念&#xff1a;C语言【文件操作】详解上-CSDN博客文章浏览阅读606次&#xff0c;点赞26次&#xff0c;收藏4次。先整体认识一下文件是…...

基于SpringBoot的在线学习平台

项目介绍 平台采用B/S结构&#xff0c;后端采用主流的SpringBoot语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。是一个综合的在线学习平台&#xff0c;该平台有管理员、教师、学生三类角色&#xff0c;各项功能根据不同角色分别设定。 整个平台包括前台和后台两个部分…...

鸿蒙生态开发

鸿蒙生态开发概述 鸿蒙生态是华为基于开源鸿蒙&#xff08;OpenHarmony&#xff09;构建的分布式操作系统生态&#xff0c;旨在通过开放共享的模式连接智能终端设备、操作系统和应用服务&#xff0c;覆盖消费电子、工业物联网、智能家居等多个领域。以下从定义与架构、核心技术…...

qt实现一个简单http服务器和客户端

一、功能简介 服务器&#xff1a; 登录功能、下载文件功能 客户端&#xff1a; 登录功能、下载文件功能、上传成绩功能 二、服务器代码 //HttpServer.h #ifndef HTTPSERVER_H #define HTTPSERVER_H#include <QMainWindow> #include <QTcpSocket> #include <QTc…...

深入理解Linux网络随笔(五):深度理解本机网络I/O

深入理解Linux网络随笔&#xff08;五&#xff09;&#xff1a;深度理解本机网络I/O 文章目录 深入理解Linux网络随笔&#xff08;五&#xff09;&#xff1a;深度理解本机网络I/O本机发送过程本机接收过程总结 分析本机网络I/O部分源码需要知道本机I/O是什么&#xff1f;扮演什…...

Debian12生产环境配置笔记

在 Debian 12 上进行生产环境配置的详细步骤&#xff0c;涵盖软件更新、基础软件安装、Docker 及 Redis 部署&#xff0c;以及 Nginx 配置多个虚拟主机等内容。所有命令均以 root 用户身份执行&#xff0c;无需添加 sudo 1. 更新软件 首先&#xff0c;确保系统上的所有软件包…...

工业物联网的范式革命:从“云边“ 到“边边” 协的技术跃迁

基于DIOS操作系统的去中心化重构 一、云边协同模式的局限性&#xff1a;技术瓶颈与成本困局 当前工业物联网主流的云边协同架构&#xff08;Cloud-Edge Collaboration&#xff09;已暴露出显著短板&#xff0c;其核心问题源于对中心云的过度依赖&#xff1a; ​带宽资源挤占与…...

python学习笔记--实现简单的爬虫(二)

任务&#xff1a;爬取B站上最爱欢迎的编程课程 网址&#xff1a;编程-哔哩哔哩_bilibili 打开网页的代码模块&#xff0c;如下图&#xff1a; 标题均位于class_"bili-video-card__info--tit"的h3标签中&#xff0c;下面通过代码来实现&#xff0c;需要说明的是URL中…...

【蓝桥杯速成】| 8.回溯算法

因为在进行背包问题的练习时&#xff0c;发现很多题目需要回溯&#xff0c;但本人作为小白当然是啥也不知道 那么就先来补充一下回溯算法的知识点&#xff0c;再进行练习 理论基础 回溯算法本质上是一种递归函数&#xff0c;是纯暴力搜索方法&#xff0c; 适合组合问题、排列…...