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

news2024/11/15 1:54:02
🍁你好,我是 RO-BERRY
📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油

请添加图片描述


目录

  • 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. 创建命名管道

  1. 命名管道可以从命令行上创建,命令行方法是使用下面这个命令:

mkfifo filename

  • mkfifo是Unix/Linux系统中的一个命令行工具,全称“Make FIFO”,用于创建一个名为“FIFO”(Fifo File)或“命名管道”(Named Pipe)。这是一个特殊的文件类型,类似于普通文件,但它提供了一种半双工的通信机制,即数据只能从一端写入,另一端读取,不能同时双向传输。

  • 当你创建一个FIFO文件时,需要指定其路径,例如mkfifo /path/to/myfifo。一旦创建,其他进程就可以通过这个文件名来读写数据。因为它是基于文件的操作,所以权限管理也是按照常规文件来进行的。

  • FIFOs常用于在同一台机器上不同进程之间的异步通信,特别是当通信需求简单且不需要网络连接的情况。它们在守护进程、系统启动脚本或其他需要进程间通信的应用场景中十分常见。

  1. 命名管道也可以从程序里创建,相关函数有:

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. 共享内存的特点

  1. 共享内存的共享内存是所有的进程间通信中,速度最快的。

数据存储在一个可以被多个进程直接访问的物理内存区域。这种方式的优点在于速度极快,因为不需要经过网络传输或系统调用,进程可以直接读写内存中的数据,无需中间环节。它特别适合于在同一台机器上、对性能有极高要求的应用程序之间,比如实时系统和高性能计算。进程在使用的时候,需要将内容从写端拷贝到管道,然后再将内容拷贝到读端,就会有两次拷贝,而共享内存则只需要拷贝一次,因为我们写是拷贝到共享内存中,从共享内存中读取就相当于在文件中读取数据,这就不算拷贝

在共享内存中,通常通过映射文件或内存段使得进程能够映射相同的地址空间,然后就可以直接操作这块内存了。它的缺点是需要所有涉及的进程都能正确地管理这部分内存,并同步对它的访问,防止数据冲突。同时,由于涉及硬件层面,如果进程崩溃未正常结束,可能会导致其他进程的内存访问混乱。

  1. 共享内存可以提供较大的空间

共享内存允许进程之间共享非常大的数据块,因为它基于物理内存而不是受限的系统消息队列。这种特性使得它可以支持跨越核心甚至整个计算机系统的大型数据结构,例如大规模数组、复杂的算法数据结构等。由于它是直接在内存中交换数据,因此不存在像文件I/O那样的限制,也不受文件大小的约束。

然而,尽管空间大,但共享内存也有其局限性。首先,内存资源是有限的,如果分配的空间过大超过了可用内存,可能会导致系统不稳定。其次,当涉及到跨机器的共享内存时,这通常通过特殊的网络技术和集群配置才能实现,而且会带来额外的复杂性和开销。此外,管理和同步共享的大空间数据也是一个挑战,需要考虑数据的一致性和并发控制问题。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1939012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32之九:ADC模数转换器

目录 1. 简介 2. ADC 2.1 逐次逼近型寄存器SAR 2.2 ADC转换时间 3 ADC框图 3.1 8 bit ADC0809芯片内部框图 3.2 ADC框图 3.2.1 注入通道和规则通道 3.2.2 单次/连续转换模式 3.2.3 扫描模式 3.2.4 外部触发转换 3.2.5 数据对齐 3.2.6 模拟看门狗 4. 总结和ADC驱…

mac无法清空废纸篓怎么办 mac废纸篓清空了如何找回 cleanmymac误删文件怎么恢复

废纸篓相当于“一颗后悔药”&#xff0c;用于临时存储用户删除的文件。我们从从Mac上删除的文件&#xff0c;一般会进入废纸篓中。如果我们后悔了&#xff0c;可以从废纸篓中找回来。然而&#xff0c;有时我们会发现mac无法清空废纸篓&#xff0c;这是怎么回事?本文将探讨一些…

Unity-URP-SSAO记录

勾选After Opacity Unity-URP管线&#xff0c;本来又一个“bug”, 网上查不到很多关于ssao的资料 以为会不会又是一个极度少人用的东西 而且几乎都是要第三方替代 也完全没有SSAO大概的消耗是多少&#xff0c;完全是黑盒(因为用的人少&#xff0c;研究的人少&#xff0c;优…

JMeter学习笔记:线程组

继续&#xff1a;请求&#xff08;Sampler元件模拟的用户请求&#xff09;出错后继续运行&#xff1b; 启动下一进程&#xff1a;如果出错&#xff0c;则同一脚本中的余下请求将不再执行&#xff0c;直接重新开始执行&#xff1b; 停止线程&#xff1a;如果遇到请求&#xff…

51单片机嵌入式开发:14、STC89C52RC 之HX1838红外解码NEC+数码管+串口打印+LED显示

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 STC89C52RC 之HX1838红外解码NEC数码管串口打印LED显示 STC89C52RC 之HX1838红外解码NEC数码管串口打印LED显示1 概述2 硬件电路2.1 遥控器2.2 红外接收器电路2.3 STC89C52单…

深入理解Linux网络(三):TCP对象创建

深入理解Linux网络&#xff08;三&#xff09;&#xff1a;TCP对象创建 TCP对象创建inet_createsock_init_data TCP对象创建 常见的三句TCP编程&#xff1a; int main() {int sk socket(AF_INET, SOCK_STREAM, 0);connect(sk, ...)recv(sk, ...) }简单的两三⾏代码&#xff…

逆向案例二十八——某高考志愿网异步请求头参数加密,以及webpack

网址&#xff1a;aHR0cDovL3d3dy54aW5nYW9rYW90Yi5jb20vY29sbGVnZXMvc2VhcmNo 抓包分析&#xff0c;发现请求头有参数u-sign是加密的&#xff0c;载荷没有进行加密&#xff0c;直接跟栈分析。 进入第二个栈&#xff0c;打上断点&#xff0c;分析有没有加密位置。 可以看到参数…

【PyTorch】图像二分类项目-部署

【PyTorch】图像二分类项目 【PyTorch】图像二分类项目-部署 在独立于训练脚本的新脚本中部署用于推理的模型&#xff0c;需要构造一个模型类的对象&#xff0c;并将权重加载到模型中。操作流程为&#xff1a;定义模型--加载权重--在验证和测试数据集上部署模型。 import torch…

Windows11 安装Docker,安装至D盘(其他非C盘皆可)

Docker默认安装在C盘&#xff0c;这未来随着docker使用必定会导致C盘空间吃紧。 所以本文提前进行空间布局&#xff0c;将docker默认安装路径软链接到D盘。 软链接D盘 Docker默认安装路径为C:\Program Files\Docker。使用管理员权限打开命令终端 输入以下命令&#xff1a;m…

【LeetCode】day14:226 - 翻转二叉树, 101 - 对称二叉树, 104 - 二叉树的最大深度, 111 - 二叉树的最小深度

LeetCode 代码随想录跟练 Day14 226.翻转二叉树101.对称二叉树104.二叉树的最大深度111.二叉树的最小深度 226.翻转二叉树 题目描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 使用递归处理&#xff08;迭代以及层序同…

jdk1.8 List集合Stream流式处理

jdk1.8 List集合Stream流式处理 一、介绍(为什么需要流Stream&#xff0c;能解决什么问题&#xff1f;)1.1 什么是 Stream&#xff1f;1.2 常见的创建Stream方法1.3 常见的中间操作1.4 常见的终端操作 二、创建流Stream2.1 Collection的.stream()方法2.2 数组创建流2.3 静态工厂…

单链表的创建与遍历--C

基本结构声明 struct node{int data; //数据域struct node *next;//指针域 }; #include<stdio.h> #include<stdlib.h>struct node{//链表结点 int data;//数据域 struct node *next;//指针域 }; typedef struct node Node; int main(void){Node *head,*p,*…

【高数复盘】武忠祥高数辅导讲义+严选题错题一轮复盘

第一章 函数、极限和连续 高等数学辅导讲义 1. 复盘&#xff1a;(xsinxcosx)(x-sixcosx)&#xff0c;前者可以带入cosx1&#xff0c;而后者不能带入&#xff0c;为何&#xff1f; 2. 复盘&#xff1a; 这道题很明显an≤1&#xff0c;对于直接求极限&#xff0c;可以考虑夹逼…

华为防火墙总部与分支机构建立IPsec VPN涉及NAT穿越

一、IPsec VPN基本概念 1、隧道建立方式&#xff1a;分为手动建立和IKE自动协商&#xff0c;手动建立需要人为配置指定所有IPsec建立的所有参数信息&#xff0c;不支持为动态地址的发起方&#xff0c;实际网络中很少应用&#xff1b;IKE协议是基于密钥管理协议ISAKMP框架设计而…

linux系统设置开机启动的两种方法systemd及rc.local(手工写sh脚本,手工写service服务)

文章目录 知识点实验一、systemd&#xff08;一&#xff09;自写一个sh脚本并加入开机启动&#xff08;二&#xff09;源码安装的nginx加入开机启动 rc.local 知识点 在Linux系统中&#xff0c;有多种方法可以设置开机启动。以下是其中的一些主要方法&#xff1a; systemd 在较…

本地部署 mistralai/Mistral-Nemo-Instruct-2407

本地部署 mistralai/Mistral-Nemo-Instruct-2407 1. 创建虚拟环境2. 安装 fschat3. 安装 transformers4. 安装 flash-attn5. 安装 pytorch6. 启动 controller7. 启动 mistralai/Mistral-Nemo-Instruct-24078. 启动 api9. 访问 mistralai/Mistral-Nemo-Instruct-2407 1. 创建虚拟…

[图解]《分析模式》漫谈16-“我用的”不能变成“我的”

1 00:00:00,720 --> 00:00:02,160 今天&#xff0c;我们来说一下 2 00:00:02,170 --> 00:00:04,850 “我用的”不能变成“我的” 3 00:00:04,860 --> 00:00:11,390 《分析模式》的前言 4 00:00:12,260 --> 00:00:13,410 有这么一句话 5 00:00:14,840 --> 0…

postman接口测试实战篇

击杀小游戏接口测试 接口测试简单介绍击杀小游戏代码下载单接口测试(postman)接口关联并参数化接口测试简单介绍 首先思考两个问题:1.接口是什么?2.接口测试是什么? 1.我们总是把接口想的很复杂,其实呢,它就是一个有特定输入和输出参数的交互逻辑处理单元,它不需要知…

学并发编程前需要明确的一些基础知识

线程和进程的区别 在计算机科学中&#xff0c;线程和进程是两个非常重要的概念。虽然它们常常被一起提到&#xff0c;但它们实际上有很大的不同。作为一个开发者&#xff0c;我在日常工作中经常需要区分这两者&#xff0c;以便更好地进行资源管理和优化。 进程与线程的基本定…

如何解决微服务下引起的 分布式事务问题

一、什么是分布式事务&#xff1f; 虽然叫分布式事务&#xff0c;但不是一定是分布式部署的服务之间才会产生分布式事务。不是在同一个服务或同一个数据库架构下&#xff0c;产生的事务&#xff0c;也就是分布式事务。 跨数据源的分布式事务 跨服务的分布式事务 二、解决方…