【linux深入剖析】命名管道 | 匿名管道与命名管道的区别 | system V共享内存

目录
- 1. 命名管道
- 2. 创建命名管道
- 3.匿名管道与命名管道的区别
- 4. 命名管道的打开规则
- 5. system V 共享内存
- 6. 共享内存的理解
- 7. 共享内存数据结构:
- 8. 共享内存函数
- shmget函数---创建共享内存
- shmat函数---将共享内存段连接到进程地址空间
- shmdt函数---将共享内存段与当前进程脱离
- shmctl函数 ---控制共享内存
- 9. 共享内存通信
- 10. 共享内存的特点
1. 命名管道
- 管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
- 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
- 命名管道是一种特殊类型的文件
命名管道(Named Pipe),也称为命名管道文件或FIFO(First-In-First-Out,先进先出队列),是一种在操作系统级别创建的特殊类型的文件,它允许不同进程间通过文件系统共享数据或通信。在Windows环境中,它们通常用于两个进程之间的临时、无服务器的数据交换,比如应用程序间的同步或者是服务端向客户端发送信息。
命名管道有以下几个关键特点:
- 双向通信:既可以从一端读取数据,也可以从另一端写入数据。
- 非阻塞模式:支持非阻塞I/O操作,提高程序的并发性能。
- 安全隔离:默认情况下,只有拥有足够权限的进程才能访问命名管道。
2. 创建命名管道
- 命名管道可以从命令行上创建,命令行方法是使用下面这个命令:
mkfifo filename
-
mkfifo
是Unix/Linux系统中的一个命令行工具,全称“Make FIFO”,用于创建一个名为“FIFO”(Fifo File)或“命名管道”(Named Pipe)。这是一个特殊的文件类型,类似于普通文件,但它提供了一种半双工的通信机制,即数据只能从一端写入,另一端读取,不能同时双向传输。 -
当你创建一个FIFO文件时,需要指定其路径,例如mkfifo /path/to/myfifo。一旦创建,其他进程就可以通过这个文件名来读写数据。因为它是基于文件的操作,所以权限管理也是按照常规文件来进行的。
-
FIFOs常用于在同一台机器上不同进程之间的异步通信,特别是当通信需求简单且不需要网络连接的情况。它们在守护进程、系统启动脚本或其他需要进程间通信的应用场景中十分常见。
- 命名管道也可以从程序里创建,相关函数有:
int mkfifo(const char *filename,mode_t mode);
-
在C语言中,它是一个库函数,通常在头文件unistd.h中声明。这个函数的主要作用是在当前工作目录下创建一个名为filename的命名管道(FIFO),并设置其权限模式mode。
-
filename参数是你要创建的FIFO文件的路径和名称,比如 “my_fifo”。mode参数是一个整数,包含了文件的访问权限信息,如读写权限(S_IRWXU、S_IWUSR等位标志组合)以及文件所有者和组的权限。这个参数可以根据应用需求调整。
-
该函数返回一个整数值,如果操作成功,返回0;若失败则返回负值,可以检查errno变量获取错误原因。常见的错误包括权限不足、文件已存在或者无法在指定路径创建等。
🐥在Linux下创建一个命名管道名称为fifo如下:
🐥当我们向管道文件输入信息的时候,命令行会锁住不动,这就是证明我们的信息输入在管道里,需要我们进行处理了
🐥我们复制会话,在另一个窗口将管道信息打印
🐥可以发现左边的命令行恢复正常,并且信息被打印在了右边,证明信息被输出
🐥我们再采取循环的方式进行打印输出
🐥在这里可以一直输出信息了。
在使用管道的时候,我们可以发现,管道里无论写入什么,其大小一直都是0。
当你向命名管道写入数据时,确实会观察到写入的字节数总是显示为0,但实际上你已经成功地将数据放入了管道中。这是因为Linux在内部实现了这种特殊的数据结构,当你查看标准的write()操作返回值时,它并不反映实际的数据长度,而是表示是否成功写入管道。
当write()返回0时,通常意味着管道已满或者出错,而不是真的没有写入任何东西。正确的做法是在读取之前检查返回值和管道的状态,比如通过fcntl()或ioctl()函数获取管道的读写指针位置等信息。如果你确认已经写入数据,而显示的字节数为0,可能需要检查管道的权限、文件描述符状态或是否有其他进程阻塞在读取端。
3.匿名管道与命名管道的区别
- 匿名管道由pipe函数创建并打开。
- 命名管道由mkfifo函数创建,打开用open
- FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义
匿名管道只能对具有血缘关系的进程进行进程间通信,但是命名管道可以让两个毫不相干的进程进行通信,这是为什么?
匿名管道(也叫无名管道)是基于内核机制的,它的创建是隐式的,通常由操作系统自动为其分配一个唯一的ID。因为它们是在父进程和子进程之间创建的,所以只能用于父子进程之间的通信,这就是所谓的“血缘关系”限制。一旦子进程结束,匿名管道也随之消失,因此无法支持跨进程的持久化通信。
相比之下,命名管道(fifo,即first-in-first-out队列)是预创建的,并有一个明确的路径名。当一个进程打开这个命名管道时,它就是通过这个名字而不是关联关系来找到管道的。这就使得任何一个拥有权限并知道名称的进程都可以尝试去读取或写入管道,即使这些进程彼此没有任何血缘关系。这种设计使得命名管道非常适合那些需要在任意进程间共享信息的应用场景。
因为路径具有唯一性,所以,我们可以使用路径+文件名,来唯一的让不同进程看到同一份资源
4. 命名管道的打开规则
如果当前打开操作是为读而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
O_NONBLOCK enable:立刻返回成功
如果当前打开操作是为写而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO
5. system V 共享内存
-
System V是Unix操作系统的一个版本系列,它起源于AT&T贝尔实验室对早期Unix系统V的改进和发展。System V最初由System I(第一代大型机Unix)发展而来,经历了多个版本,包括System V Release 1 (SVR1) 到System V Release 4 (SVR4),后者也被称为Solaris 2.x。
-
System V的主要特点是稳定性、可靠性以及兼容性。它引入了许多重要的改进,比如内核模块化设计、网络功能增强、标准工具集和系统管理工具的提升等。SVR4尤其显著,它是许多现代Unix和Linux发行版的基础,如Red Hat Enterprise Linux和SUSE Linux等。
-
System V也与POSIX标准紧密关联,它定义了一套通用的应用程序接口(API),使得不同厂商的Unix系统之间能够更好地交互。
共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据
共享内存示意图
6. 共享内存的理解
System V共享内存是一种进程间通信(IPC,Inter-Process Communication)机制,它允许不同的进程之间直接交换数据,而无需通过文件系统或者网络。在Unix-like系统如Linux上,System V模型源于System V Interprocess Communication Specification,其核心思想是通过一段预分配的内存区域(称为段或段映射),让多个进程可以同时访问。
共享的原理和动态库的共享原理一致,共享内存的申请主要分为以下三步:
- 操作系统在物理内存上申请一块空间。
- 将申请到的空间,通过页表挂接到进程地址空间的共享区。
- 返回起始虚拟地址,供程序中使用。
我们想释放共享内存时,就只需要去除掉我们在页表上的关联信息,然后再将物理内存空间释放即可
在系统中,一般都会有有多组进程都需要通信,因此系统中一般会存在多个共享内存
所以操作系统要把这多个共享内存管理起来。
- 先描述,再组织,操作系统中一定有一个内核结构体是用来描述共享内存的。
7. 共享内存数据结构:
struct shmid_ds {struct ipc_perm shm_perm; /* operation perms */int shm_segsz; /* size of segment (bytes) */__kernel_time_t shm_atime; /* last attach time */__kernel_time_t shm_dtime; /* last detach time */__kernel_time_t shm_ctime; /* last change time */__kernel_ipc_pid_t shm_cpid; /* pid of creator */__kernel_ipc_pid_t shm_lpid; /* pid of last operator */unsigned short shm_nattch; /* no. of current attaches */unsigned short shm_unused; /* compatibility */void *shm_unused2; /* ditto - used by DIPC */void *shm_unused3; /* unused */
};
struct shmid_ds 是 System V 共享内存的状态信息结构体,在 Linux 系统中用来描述共享内存段的属性和状态。下面是 struct shmid_ds 结构体中各个成员的含义:
成员 | 含义 |
---|---|
struct ipc_perm shm_perm | 用于描述共享内存的操作权限。 |
int shm_segsz | 共享内存段的大小,以字节为单位。 |
__kernel_time_t shm_atime | 最后一次附加(attach)该共享内存的时间。 |
__kernel_time_t shm_dtime | 最后一次分离(detach)该共享内存的时间。 |
__kernel_time_t shm_ctime | 最后一次修改该共享内存的时间。 |
__kernel_ipc_pid_t shm_cpid | 创建者进程的进程号(PID)。 |
__kernel_ipc_pid_t shm_lpid | 最后一次操作该共享内存的进程号(PID)。 |
unsigned short shm_nattch | 当前附加(attach)该共享内存的进程数。 |
unsigned short shm_unused | 未使用的字段,用于兼容性。 |
void* shm_unused2 | 未使用的字段,由 DIPC(Distributed Inter-Process Communication)使用。 |
void* shm_unused3 | 未使用的字段。 |
通过这些状态信息,我们可以获取共享内存段的大小、权限、最后访问时间、创建者信息以及当前附加进程的数量等相关信息。这些信息对于管理和监控共享内存非常有用,能够帮助我们更好地理解和控制共享内存的状态。
8. 共享内存函数
shmget函数—创建共享内存
int shmget(key_t key, size_t size, int shmflg);
shmget()是Unix/Linux系统提供的一种System V共享内存管理函数,它的作用是在内核级为应用程序动态创建一块预分配的共享内存区域。这个函数需要以下几个关键参数:
key
:这是一个整数,用于标识共享内存区。相同的key值会产生相同的共享内存资源,方便程序找到并链接起来。size
:想要创建的共享内存块的大小,以字节为单位。flag
:标志位,通常包括以下几个选项:
SHM_RDONLY
: 创建只读共享内存
SHMReadWrite 或 0
: 创建可读写共享内存
SHM创造出错时保留旧的内容
: 如果先前存在同key的共享内存,就保留它
调用shmget()返回一个进程ID,如果成功则指向新的或已存在的共享内存区域的首地址;若失败则返回-1,并设置errno错误码。
使用完毕后,通过shmat()函数将这个地址映射到进程的地址空间,然后就可以像普通数组那样访问共享内存了。当不再需要时,应调用shmdt()解除内存映射,最后使用shmctl()函数关闭共享内存区域。
shmat函数—将共享内存段连接到进程地址空间
void *shmat(int shmid, const void *shmaddr, int shmflg);
这个函数是一个C语言中的函数原型,用于进程间的共享内存操作。它属于系统调用的一部分,常在头文件sys/shm.h中找到。函数接收三个参数:
shmid (整型)
:这是由之前调用 shmget() 函数获取的共享内存标识符,代表了要连接到的共享内存块。shmaddr (void*)
:这是一个可选参数,如果提供,表示希望映射到特定的物理地址。如果没有指定,就会从已创建的共享内存的第一个字节开始映射。shmflg (标志位)
:这是操作标志,可以包含以下几个标志之一(例如 SHM_RDONLY 或 SHM_WRITECOPY 等)来控制共享内存的行为,如只读、写入副本等。
函数的返回值是 void * 类型,代表了映射到进程地址空间内的共享内存的起始位置。如果操作成功,返回非NULL地址;失败则返回 NULL。使用完共享内存后,需要调用 shmdt() 函数解除映射。
shmaddr为NULL,核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr -
(shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示连接操作用来只读共享内存
shmdt函数—将共享内存段与当前进程脱离
int shmdt(const void *shmaddr);
Unix/Linux 系统下的 System V 共享内存 API 中的一个函数,用于将共享内存段从进程的地址空间中分离出来。这个函数接收一个指向共享内存区域(通常是从 shmat() 或者 shm_open() 创建的)的指针作为参数。
shmaddr
: 由shmat所返回的指针
返回值
:成功返回0;失败返回-1
当你调用 shmdt(shmaddr) 时,它会让当前进程不再直接映射该内存块到它的虚拟地址空间中,但仍保留对这块内存的所有权。这通常发生在你想结束对共享内存的访问,但并不立即删除它,因为其他进程可能还在使用这个内存。随后,你可以通过 shmctl() 来正式地取消共享内存(SHM_RMID 命令),或者直到所有关联进程都终止才会自动清除。
注意: 将共享内存段与当前进程脱离不等于删除共享内存段
shmctl函数 —控制共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
Linux 系统提供的 System V 共享内存管理函数。此函数的作用是控制已存在的共享内存段(由 shmat() 或 shmopen() 创建并分配给特定 ID (shmid) 的那段内存)。它接受三个参数:
shmid
:是一个整数,表示之前通过 shmget() 函数创建的共享内存标识符。cmd
:是一个操作命令,例如:
SHM_INFO
:获取关于指定共享内存的信息,如大小、创建时间等,并存储在 buf 结构中。
SHM_SETATTR
:修改共享内存属性,比如设置权限等。
SHM_RENAME
:改变共享内存名称。
SHM_LOCK 和 SHM_UNLOCK
:锁定或解锁共享内存区域。
SHM.removeItem 或 SHM_RMID
:删除共享内存。
buf
:如果 cmd 包含信息请求或需要传递数据,则此指针指向一个 struct shmid_ds 结构,用于存储响应信息。
通过这个函数,进程可以管理和维护其使用的共享内存资源。
9. 共享内存通信
processa:
#include "comm.hpp"
#include <unistd.h>int main()
{// 创建共享内存int shmid = CreatMem();// 挂接共享内存char *shamem = (char*)shmat(shmid, nullptr, 0);// ipc-cod 通信代码while(true){cout << "client asy@ " << shamem << endl; // 直接访问共享内存sleep(1);}// 去关联shmdt(shamem);// 释放共享内存int ret = shmctl(shmid, IPC_RMID, NULL);return 0;
}
processb:
#include "comm.hpp"
#include <unistd.h>int main()
{// 获取共享内存int shmid = GetMem();// 挂接char *shmaddr = (char*)shmat(shmid, nullptr, 0);// ipc-code 通信代码while(true){cout << "Please enter:";fgets(shmaddr, size, stdin);}// 去关联shmdt(shmaddr);return 0;
}
一旦有了共享内存,并且挂接到当前进程的地址空间上了,在程序中就把它当做该进程自己的内存空间来使用即可,无需再调用系统调用。一旦有人把数据写入到共享内存,其实我们立马就能看到,不需要经过系统调用,就能直接看到数据。可以把共享内存就当做用户自己 malloc 出来的一块空间。
10. 共享内存的特点
- 共享内存的共享内存是所有的进程间通信中,速度最快的。
数据存储在一个可以被多个进程直接访问的物理内存区域。这种方式的优点在于速度极快,因为不需要经过网络传输或系统调用,进程可以直接读写内存中的数据,无需中间环节。它特别适合于在同一台机器上、对性能有极高要求的应用程序之间,比如实时系统和高性能计算。进程在使用的时候,需要将内容从写端拷贝到管道,然后再将内容拷贝到读端,就会有两次拷贝,而共享内存则只需要拷贝一次,因为我们写是拷贝到共享内存中,从共享内存中读取就相当于在文件中读取数据,这就不算拷贝
在共享内存中,通常通过映射文件或内存段使得进程能够映射相同的地址空间,然后就可以直接操作这块内存了。它的缺点是需要所有涉及的进程都能正确地管理这部分内存,并同步对它的访问,防止数据冲突。同时,由于涉及硬件层面,如果进程崩溃未正常结束,可能会导致其他进程的内存访问混乱。
- 共享内存可以提供较大的空间
共享内存允许进程之间共享非常大的数据块,因为它基于物理内存而不是受限的系统消息队列。这种特性使得它可以支持跨越核心甚至整个计算机系统的大型数据结构,例如大规模数组、复杂的算法数据结构等。由于它是直接在内存中交换数据,因此不存在像文件I/O那样的限制,也不受文件大小的约束。
然而,尽管空间大,但共享内存也有其局限性。首先,内存资源是有限的,如果分配的空间过大超过了可用内存,可能会导致系统不稳定。其次,当涉及到跨机器的共享内存时,这通常通过特殊的网络技术和集群配置才能实现,而且会带来额外的复杂性和开销。此外,管理和同步共享的大空间数据也是一个挑战,需要考虑数据的一致性和并发控制问题。
相关文章:

【linux深入剖析】命名管道 | 匿名管道与命名管道的区别 | system V共享内存
🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 1. 命名管道2. 创建命名管…...
Vite 常用插件配置:自动导入+自动注册组件+动态创建图标+设置组件名
创建 Vue3Vite 项目 创建 Vue3 项目 $ pnpm create vuelatest通过脚手架选择开启以下功能 ✔ Project name: … <your-project-name> ✔ Add TypeScript? … No / Yes ✔ Add JSX Support? … No / Yes ✔ Add Vue Router for Single Page Application development?…...

(leetcode学习)236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖…...

Zabbix监控系统:zabbix服务部署+基于Proxy分布式部署+zabbix主动与被动监控模式
一、Zabbix概述 1.1 简介 zabbix 是一个基于 Web 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。 zabbix 能监视各种网络参数,保证服务器系统的安全运营,提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问题。 zabbix…...

【Vue实战教程】之 Vue Router 路由详解
Vue Router路由 1 路由基础 1.1 什么是路由 用Vue.js创建的项目是单页面应用,如果想要在项目中模拟出来类似于页面跳转的效果,就要使用路由。其实,我们不能只从字面的意思来理解路由,从字面上来看,很容易把路由联想…...
测试用例接口开发实战
测试用例接口开发实战 前言 在上一集,我们也大概完成了对Jmeter的二次开发的Demo版本的了解,我们接下来就要基于这个Demo来将Jmeter压测进行平台化。 那么这一集,我们讲一讲测试用例接口开发实战。 StressCaseController 我们的Controll…...
C#中压缩文件夹,及其内容
压缩包格式,本文主要用于说明如何使用代码 文件或文件夹压缩为 zip压缩包及其解压操作, 下面分两个版本进行实现 1.简单版本 bool DoCompressDirectoryInfo(string folderPath){try{var zipFilePath $"{folderPath}.zip";var directoryInfo …...
机器学习 | 回归算法原理——多项式回归
Hi,大家好,我是半亩花海。接着上次的最速下降法(梯度下降法)继续更新《白话机器学习的数学》这本书的学习笔记,在此分享多项式回归这一回归算法原理。本章的回归算法原理基于《基于广告费预测点击量》项目,…...
力扣224【基本计算器】
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。 注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。 1 < s.length < 3 * 105 s 由数字、‘’、‘-’、‘(’、‘)’、和 ’ ’ 组成 s 表示一个有效的…...

【Linux】HTTP 协议
目录 1. URL2. HTTP 协议2.1. HTTP 请求2.2. HTTP 响应 1. URL URL 表示着是统一资源定位符(Uniform Resource Locator), 就是 web 地址,俗称“网址”; 每个有效的 URL 可以通过互联网访问唯一的资源, 是互联网上标准资源的地址; URL 的主要由四个部分组成: sche…...
@Builder注释导致@RequestBody的前端json反序列化失败,HTTP400
项目里发生了一个bug,就是前端请求一个接口时候,报了HTTP 400 Bad Request 通常来说这个问题是前后端的参数没对齐,比如前端传了个String,但后端对应的是Integer。 所以我就排查了半天,结果没发现啥错误,…...
网络学习|如何理解服务的端口号
文章目录 1. 端口号的定义2. 端口号的分类3. 端口号的用途4. 注意事项5. 示例图解 后端面试中可能遇到的端口相关问题及答案1. 什么是端口号?为什么需要端口号?2. 知名端口(Well-Known Ports)有哪些,举例说明ÿ…...

《0基础》学习Python——第十八讲__爬虫/<1>
一、什么是爬虫 爬虫是一种网络数据抓取的技术。通过编写程序(通常使用Python),爬虫可以自动化地访问网页,解析网页内容并提取出所需的数据。爬虫可以用于各种用途,如搜索引擎的索引,数据分析和挖掘&#x…...

NFTScan 浏览器现已支持 .mint 域名搜索功能!
近日,NFT 数据基础设施 NFTScan 浏览器现已支持用户输入 .mint 域名进行 Mint Blockchain 网络钱包地址的搜索查询, NFTScan 用户能够轻松地使用域名追踪 NFT 交易,为 NFT 钱包地址相关的搜索查询功能增加透明度和便利性。 NFTScan explorer…...

Git基本原理讲解、常见命令、Git版本回退、Git抛弃本地分支拉取仓库最新分支
借此机会写篇博客汇总一下自己去公司实习之后遇到的一些常见关于Git的操作。 Git基本认识 Git把数据看作是对小型文件系统的一组快照,每次提交更新,或在Git中保存项目状态时,Git主要对当时的全部文件制作一个快照并保存这个快照的索引。同时…...

前端网页打开PC端本地的应用程序实现方案
最近开发有一个需求,网页端有个入口需要跳转三维大屏,而这个大屏是一个exe应用程序。产品需要点击这个入口,并打开这个应用程序。这个就类似于百度网盘网页跳转到PC端应用程序中。 这里我们采用添加自定义协议的方式打开该应用程序。一开始可…...

遇到not allow unquoted fieldName怎么办
前言 Exception in thread "main" com.alibaba.fastjson2.JSONException: not allow unquoted fieldName, offset 2, character , line 1, column 3, fastjson-version 2.0.25 { "data":null, "code":200, "msg":"成功"…...

IDEA安装并使用通义灵码
IDEA安装并使用通义灵码 通义灵码介绍安装通义灵码 通义灵码介绍 在数字革命的前沿,阿里云技术团队匠心独运,倾力打造“通义灵码”——一个融合尖端科技的智能编码助手,旨在革新软件工程的未来。 实时代码扩展 通义灵码具备深度理解代码脉络的…...

<数据集>AffectNet表情识别数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:29752张 标注数量(xml文件个数):29752 标注数量(txt文件个数):29752 标注类别数:7 标注类别名称:[anger,contempt,disgust,fear,happy,neutral,sad,surprise] 序号类…...
ThinkPHP对接易联云打印
引入composer包 composer require yly-openapi/yly-openapi-sdk <?phpnamespace app\common\library;use app\admin\model\yp\Order; use App\Api\PrintService; use App\Config\YlyConfig; use App\Oauth\YlyOauthClient; use think\Cache; use think\Config;class Yly {…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...