Linux:进程间通信(二.共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)

Linux:进程间通信(二.共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)

上次结束了进程间通信一:Linux:进程间通信(一.初识进程间通信、匿名管道与命名管道、共享内存)


文章目录

  • 1.System V共享内存
    • 1.1相关函数介绍
    • 写个小项目
      • 项目规划
      • Cnmm.hpp
      • ShmClient.cpp
      • PipeServe.cpp
    • 1.2指令查看与删除
  • 2.System V消息队列
      • 消息队列的原理
      • 相关函数
  • 3.System V 信号量
    • 3.1概念
    • 3.2周边知识
  • 4.内核中

1.System V共享内存

在这里插入图片描述

实现进程间通信的前提就是如何让不同的进程看到同一份资源

  • 匿名管道我们是通过子进程继承父进程打开的资源
  • 命名管道是通过两个进程都打开具有唯一性标识的命名管道文件(路径+文件名)
  • 共享内存其实是通过OS创建一块shm

System V共享内存(Shared Memory)是一种Linux中用于进程间通信(IPC)的机制。它允许多个进程访问同一块物理内存区域,从而实现数据的快速共享和交换。

  1. 原理

    • 在物理内存中申请一块内存空间作为共享内存。
    • 将这块内存空间与各个进程的页表建立映射关系,使得这些进程在虚拟地址空间中可以看到并访问这块共享内存。
    • 通过这种方式,多个进程可以像访问自己的内存一样访问共享内存,从而实现数据的快速共享和交换。
  2. 使用方式

    • 创建:使用shmget()系统调用来创建共享内存。这个函数会分配一块指定大小的内存区域,并返回一个标识符,用于后续对这块共享内存的操作。
    • 关联:使用shmat()系统调用来将共享内存关联到进程的地址空间。这个函数会将共享内存的地址告诉进程,使得进程可以通过这个地址来访问共享内存。
    • 取消关联:当进程不再需要访问共享内存时,可以使用shmdt()系统调用来取消关联。这个函数会断开进程与共享内存之间的映射关系。
    • 释放:当所有进程都不再需要这块共享内存时,可以使用shmctl()系统调用来释放它。这个函数会回收这块内存区域,并释放相关的资源。
  3. 特性:

  • 共享内存的生命周期是在进程结束后仍然存在的,直到显式地将其删除或者系统重启。这种情况下,如果进程没有主动释放共享内存,那么共享内存将一直存在于系统中,直到以下情况之一发生才会被释放:
  1. 代码删除:可以通过调用shmctl函数来删除共享内存,释放其资源。删除共享内存后,系统会立即释放共享内存的资源。
  2. 指令删除:在Linux系统中,可以使用ipcs命令查看系统中的IPC资源(包括共享内存),并使用ipcrm命令来删除特定的IPC资源
  • 共享内存是所有进程间通信中速度最快的原因

无需内核参与:在共享内存中,多个进程可以直接访问同一块物理内存区域,而无需通过内核进行数据的拷贝和传输。这样可以避免了进程间切换和内核态和用户态之间的数据拷贝,从而提高了通信的效率。

  • 共享内存并不提供进程间协同的机制,也不提供同步和互斥的功能,需要我们用户自己来实现

1.1相关函数介绍

ftok() 函数 Linux中用于生成一个唯一的键值(key)的系统调用,这个键值通常用于在进程间通信(IPC)中标识共享内存段、消息队列或信号量集。ftok() 函数基于一个已经存在的文件路径和一个非零的标识符(通常是一个小的正整数)来生成这个键值。

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

参数:

  • pathname:指向一个已经存在的文件路径的指针。这个文件通常被用作生成键值的“种子”或“基础”。
  • proj_id:一个非零的标识符,通常是一个小的正整数。这个值将与文件路径一起被用于生成键值。返回值:

如果成功,ftok() 函数返回一个唯一的键值key_t 类型),该键值可以在后续的 IPC 调用(如 shmget(), msgget(), semget() 等)中用作参数。如果失败,则返回 (key_t) -1 并设置 errno 以指示错误。

  1. shmget():创建或获取共享内存

shmget() 系统调用用于创建一个新的共享内存对象,或者如果它已存在,则返回该对象的标识符。

函数原型

int shmget(key_t key, size_t size, int shmflg);

参数

  • key:一个键,用于唯一标识共享内存对象。通常使用ftok()函数生成。

    1. 共享内存在内核中同时可以存在很多个,OS必须要管理所有的共享内存
    • 如何管理呢?先描述,在组织
    • 系统中会存在很多共享内存,怎么保证,多个不同的进程看到的是同共享内存呢? 要给共享内存提供唯一性的标识
    1. key便是那个唯一性标识符。那么为什么这个key要由我们用户来传入呢?
    • 如果然系统生成,将值返回让我们得到。那我们如何给另外一个进程呢?要做到就要有进程间通信,这不倒反天罡了?
  • size:共享内存的大小(以字节为单位)。

  • shmflg:权限标志和选项。通常设置为IPC_CREAT如果对象不存在则创建,存在的话直接获取)和权限(如0666)。

    若设置为IPC_CREAT|IPC_EXCL(如果对象不存在则创建,存在的话出错返回)

返回值:成功时返回共享内存对象的标识符;失败时返回-1并设置errno

  1. shmctl():控制共享内存

在这里插入图片描述

shmctl() 系统调用用于获取或设置共享内存的属性,或者删除共享内存对象。

函数原型

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数

  • shmid:共享内存对象标识符。
  • cmd:要执行的操作。例如,IPC_RMID用于删除共享内存对象,IPC_STAT用于获取其状态。
  • buf:指向shmid_ds结构的指针,用于传递或接收共享内存的状态信息。

返回值:成功时返回0;失败时返回-1并设置errno

  1. shmat():将共享内存关联到进程的地址空间

shmat() (attach)系统调用用于将共享内存对象关联到调用进程的地址空间

在这里插入图片描述

函数原型

void *shmat(int shmid, const void *shmaddr, int shmflg);

参数

  • shmidshmget()返回的共享内存对象标识符
  • shmaddr:希望将共享内存附加到的进程的地址。如果设置为NULL,则系统选择地址(一般都这样)。
  • shmflg:通常设置为0或SHM_RND(使附加地址向下舍入到最接近的SHMLBA边界)。

返回值:成功时返回共享内存附加到进程的地址;失败时返回(void *)-1并设置errno

  1. shmdt():取消共享内存的关联

在这里插入图片描述

shmdt() 系统调用用于取消之前通过shmat()附加到进程的共享内存的关联。

函数原型

int shmdt(const void *shmaddr);

参数

  • shmaddrshmat()返回的共享内存附加到进程的地址。

返回值:成功时返回0;失败时返回-1并设置errno

写个小项目

项目规划

在这里插入图片描述

  • Cnmm.hpp:函数的声明定义,头文件的包含、宏定义等任务
  • ShmClient.cpp:客户端,
  • ShmServer.cpp:服务端(服务器)

makefile:

.PHONY:all
all:shm_client shm_servershm_server:ShmServer.ccg++ -o $@ $^ -std=c++11
shm_client:ShmClient.ccg++ -o $@ $^ -std=c++11
.PHONY:clean
clean:rm -f shm_client shm_server

Cnmm.hpp

#pragma once#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <string>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>using namespace std;const char *pathname = "/home/zc/study/lesson26/5.4_shm_ipc";
const int proj_id = 0x1;
const int defaultsize = 4096; // 单位是字节key_t GetShmKeyOrDie()
{key_t key = ftok(pathname, proj_id);if (key == -1){cerr << "ftok error, errno : " << errno << ", error string: " << strerror(errno) << std::endl;exit(1); // 出错就直接退出}return key;
}int CreateShmOrDie(key_t key, int size, int flag)
{int shmid = shmget(key, size, flag);if (shmid < 0){std::cerr << "shmget error, errno : " << errno << ", error string: " << strerror(errno) << std::endl;exit(2); // 出错就直接退出}return shmid;
}int CreateShm(key_t key, int size)
{return CreateShmOrDie(key, size, IPC_CREAT | IPC_EXCL | 0666); // 没有就创建,有就报错,权限666
}int GetShm(key_t key, int size)
{return CreateShmOrDie(key, size, IPC_CREAT); // 不存在则创建,存在的话直接获取
}void DeleteShm(int shmid)
{int n = shmctl(shmid, IPC_RMID, nullptr);if (n == -1){cerr << "shmctl error" << errno << endl;}else{cout << "delete successfully" << endl;}
}void *ShmAttach(int shmid)
{void *addr = shmat(shmid, nullptr, 0);if ((long long int)addr == -1){std::cerr << "shmat error" << std::endl;return nullptr;}return addr;
}void ShmDt(void *addr)
{int n = shmdt(addr);if (n < 0){cerr << "shmdt error" << endl;}
}

ShmClient.cpp

#include "Comm.hpp"int main()
{// 获取keykey_t key = GetShmKeyOrDie();cout << "key:" << key << endl;// 获取shmidint shmid = GetShm(key, defaultsize);cout << "shmid:" << shmid << endl;// 进行挂接void *tem = ShmAttach(shmid);char *addr = (char *)tem;cout << "Attch successfully" << endl;// 进行通信,这里进行写入for (char ch = 'A'; ch <= 'Z'; ch++){addr[ch - 'A'] = ch;}// 取消挂接ShmDt(tem);return 0;
}

PipeServe.cpp

#include "Comm.hpp"
#include <unistd.h>int main()
{// 获取keykey_t key = GetShmKeyOrDie();cout << "key:" << key << endl;// 创建共享内存int shmid = CreateShm(key, defaultsize);cout << "shmid:" << shmid << endl;// 进行挂接void *tem = ShmAttach(shmid);char *addr = (char *)tem;cout << "Attch successfully" << endl;// 进行通信,这里进行读for (;;){cout << "shm content: " << addr << std::endl;}// 取消挂接ShmDt(tem);// 删除共享内存sleep(50);DeleteShm(shmid);return 0;
}

1.2指令查看与删除

  1. 使用ipcs命令查看系统中的共享内存:
ipcs -m

显示的以下内容:

  1. 键值 (key):共享内存段的键值,用于唯一标识一个共享内存段。在创建共享内存段时可以指定一个键值,其他进程可以通过这个键值来访问同一个共享内存段。
  2. shmid:共享内存段的标识符,是系统为每个共享内存段分配的唯一标识符。其他进程可以通过 shmid 来操作同一个共享内存段。
  3. 权限 (perms):共享内存段的权限信息,包括读、写、执行权限。通常以八进制形式表示,比如 0600 表示用户具有读写权限,其他用户没有权限。
  4. 拥有者 (owner):共享内存段的拥有者,即创建该共享内存段的用户或进程。
  5. 大小 (bytes):共享内存段的大小,以字节为单位。表示该共享内存段所分配的内存空间大小。
  6. 附加进程数 (nattch):当前附加到共享内存段的进程数目。当一个进程附加到共享内存段时,nattch 数加一;当一个进程分离(detach)时,nattch 数减一。

在这里插入图片描述

  1. 使用ipcrm命令删除指定的共享内存:
ipcrm -m <shmid>

<shmid>是要删除的共享内存段的标识符。通过这个命令可以删除指定的共享内存段,释放其资源。

在这里插入图片描述

shmid与key分辨:

在共享内存的设计中,keyshmid 的使用确实是为了实现内核层和用户层之间的解耦,从而使它们在宏观层面上互不影响,具有独立性。下面详细解释一下这种设计的好处和原因:

  • 内核层使用 key 来唯一标识共享内存段,而用户层使用 shmid 来访问和操作已存在的共享内存段。这种设计使得内核层和用户层的代码逻辑相互独立,彼此不直接依赖。
  • 当内核层需要进行某些代码改动或优化时,只需在内核层处理 key 的逻辑,而不需要影响用户层的代码。用户层代码不需要关心内核层的具体实现细节,只需要通过 shmid 来操作共享内存即可。

2.System V消息队列

System V消息队列是一种进程间通信的机制,允许进程之间通过消息进行通信。消息队列提供了一个消息缓冲区,进程可以向消息队列发送消息,也可以从消息队列接收消息。下面我们来详细讲解消息队列的原理以及相关函数。

消息队列的原理

  1. 消息队列结构:消息队列是一个由内核维护的消息缓冲区,通常由消息类型和消息数据组成。每个消息都包含一个消息类型和消息数据,进程可以根据消息类型选择接收特定类型的消息。

  2. 消息发送:进程可以调用系统调用函数向消息队列发送消息,将消息写入消息队列中。发送消息时,需要指定消息队列的标识符、消息类型以及消息数据等信息。

  3. 消息接收:进程可以调用系统调用函数从消息队列接收消息,读取消息队列中的消息。接收消息时,可以选择阻塞式接收或非阻塞式接收,进程可以根据需要选择适合的接收方式。

  4. 消息类型:每个消息都有一个消息类型,进程可以根据消息类型选择接收特定类型的消息。这样可以实现不同类型的消息传递和处理。

  5. 消息队列管理:消息队列由内核管理,进程可以通过系统调用函数对消息队列进行创建、删除、发送消息、接收消息等操作。

相关函数

当使用System V消息队列相关函数时,需要了解函数的原型、参数和返回值。以下是这些函数的介绍:

  1. msggetint msgget(key_t key, int msgflg);
    • 参数key为消息队列的键值,msgflg为权限标志和操作标志的组合。
    • 返回值:成功时返回消息队列标识符,失败时返回-1并设置errno
  2. msgctlint msgctl(int msqid, int cmd, struct msqid_ds *buf);
    • 参数msqid为消息队列的标识符,cmd为控制命令,buf为消息队列信息结构体指针。
    • 返回值:成功时返回0,失败时返回-1并设置errno
  3. msgsndint msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    • 参数msqid为消息队列的标识符,msgp为消息缓冲区指针,msgsz为消息长度,msgflg为标志位。
    • 返回值:成功时返回0,失败时返回-1并设置errno
  4. msgrcvssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
    • 参数msqid为消息队列的标识符,msgp为消息缓冲区指针,msgsz为消息长度,msgtyp为消息类型,msgflg为接收标志。
    • 返回值:成功时返回接收到的消息数据的长度,失败时返回-1并设置errno

3.System V 信号量

3.1概念

  1. 信号量本质:
  • 信号量通常被用来保护公共资源,确保多个进程或线程能够有序地访问和使用这些资源

  • 信号量是一个整型变量,通常用于控制对共享资源的访问。信号量的值可以表示可用资源的数量或者某个资源的占用情况

  • 信号量:信号量本质是一个计数器,描述临界资源数量的计数器

    为什么不能直接用一个int来进行呢?

    无法在进程间共享 而且一个int ++- -不是原子的

  • 信号量:公共资源中,对局部性资源进行预定的机制。可以被用于对局部性资源进行预定,实现对资源的合理分配和控制

  • 信号量是让不同的进程看到同一个计数器资源,而进程间通信是让不同的进程看到一份资源。所以信号量也属于进程间通信

进程申请信号量一旦成功:就一定有这个进程的资源了(相当于去看电影买票,一定有我们的座位了,而且别人也买不了这个座位)

当我们释放信号量后,这份资源才能给别人(看完电影后,这个座位才能接着被下一个买)

申请信号量和释放信号量来保护临界资源, 是大家都要遵守的规则(我们程序员)

  • 所有的进程,访问临界资源,都必须先申请信号量, 所有进程都得先看到同一个信号量 ==> 信号量本身就是共享资源
  1. 信号量操作:

    那谁来保护信号量呢? 通过使用原子的PV操作来保障

  • P操作(等待操作):当进程需要访问共享资源时,首先执行P操作,即尝试获取信号量。如果信号量的值大于0,则将信号量的值减1,表示资源已被占用,进程可以继续执行;如果信号量的值为0,则表示资源已被占用,进程需要等待。(允许申请多个信号量)
  • V操作(释放操作):当进程使用完共享资源后,执行V操作,即释放信号量。释放信号量会增加信号量的值,表示资源已经释放,其他进程可以继续访问。

3.2周边知识

  1. 互斥和同步:

    • 互斥:指的是在访问共享资源时,任何时刻只允许一个执行流访问,其他执行流需要等待。这样可以避免多个执行流同时修改共享资源导致数据不一致。互斥是通过使用锁或信号量等机制来实现的。(任何时候都只有一个人能访问,当信号量为1——只有一个整体资源时,不就是互斥吗)
    • 同步:指的是在访问共享资源时,具有一定的顺序性,确保多个执行流按照特定的顺序访问资源。同步可以通过信号量、条件变量等机制来实现,以确保执行流之间的协调和顺序性。
  2. 临界资源和临界区:

    • 临界资源:是指被保护起来的,任何时刻只允许一个执行流访问的公共资源。访问临界资源的代码段被称为临界区。
    • 临界区:是指访问临界资源的代码段,程序员需要在临界区内使用互斥和同步机制来确保对临界资源的安全访问
  3. 原子性:指的是操作对象的操作是不可分割的,要么整个操作完成,要么没有开始。在多线程或多进程环境中,保证操作的原子性是非常重要的,可以通过锁或原子操作等机制来实现。

  4. 保护临界区的本质:程序员需要保护临界区,确保在任何时刻只有一个执行流可以访问临界资源,避免数据竞争和不一致性。这通常通过使用锁、信号量或其他同步机制来实现。


4.内核中

内核中,所有的描述管理IPC资源的结构体,第一个成员大家都一样 kern_ipc_perm。我们可以用指针数组来进行管理

在这里插入图片描述

在内核中,对IPC资源的管理也是转变为对数组的增删查改

类型不同我们怎么解决呢?——直接强转

  • (msg_ queue*)ipc[0]> q _time;
  • (sem_array)ipc[1]->q_time;
  • (shmid kernel)ipc[2]-> 。。。

那怎么知道是什么类型呢?

kern_ipc_perm里有一个有个mode变量,能来表示类型

#define IPC TYPE SHM Ox1
#define IPC TYPE MSG (0x1<<1)
#define IPC TYPE SEM(0x1 << 2)//定义这三个宏后shmid kernel* (kern ipc_perm* p)
{if (p->mode & IPC TYPE SHM){return (shmid kernel)ipc}else if (p->mode & IPC TYPE MSG){///}else{///}
}

好啦,我也是结束了实训,才到家!!!
感谢大家的支持

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

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

相关文章

HackTheBox--BoardLight

BoardLight 测试过程 1 信息收集 NMAP端口扫描 端口扫描开放 22、80 端口 80端口测试 # 添加 boardLight.htb 到hosts文件 echo "10.10.11.11 boardLight.htb" | sudo tee -a /etc/hosts检查网页源代码&#xff0c;发现 board.htb # 添加 board.htb 到 hosts 文…

大话光学原理:3.干涉与衍射

一、干涉 这是一束孤独的光&#xff0c;在真空的无垠中悄无声息地穿行。忽然&#xff0c;一堵高耸的墙壁挡住了它的去路&#xff0c;它别无选择&#xff0c;只能硬着头皮冲撞而去。在摸索中&#xff0c;它意外地发现墙壁上竟有两道孔隙&#xff0c;笔直而细长&#xff0c;宛如量…

图吧工具箱:装机爱好者必备工具合集

名人说:莫道谗言如浪深,莫言迁客似沙沉。 ——刘禹锡《浪淘沙》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、概述二、主要功能1、硬件检测2、测试与故障诊断三、使用方法四、总结很高兴你打开了这篇博客,更多好用的软件工具,请关注我、订阅专栏…

Python从0到100(三十五):beautifulsoup的学习

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

暴雨突袭不可不看!水浸传感器作用有这些

最近全国进入“看海”模式的新闻不断冲上热搜&#xff0c;深圳、长沙、郑州......多地遭受了暴雨突袭&#xff0c;不仅影响到了居民日常生活出行&#xff0c;更容易为机房、仓库、工厂等需要防水的场所带来漏水隐患。水浸传感器的作用是实时检测监测范围内是否有漏水发生&#…

Linux文件编程(打开/创建写入读取移动光标)

目录 一、如何在Linux下做开发 1.vi编辑器 2.gcc编译工具 3.常用指令 二、文件打开及创建 三、写入文件 四、读取文件 五、文件“光标”位置 一、如何在Linux下做开发 所谓文件编程&#xff0c;就是对文件进行操作&#xff0c;Linux的文件和Windows系统的文件大差不差…

基于变分模态分解和Cramer von Mises检验的一维信号降噪方法(MATLAB)

关于变分模态分解&#xff1a; 变分模态分解中为什么要各个模态估计的带宽之和最小&#xff1f; 因为VMD是个优化问题&#xff0c;VMD方法首先在时域构造一个共同优化的目标&#xff0c;该目标在所有成分完全重构原信号的约束下追求所有成分的带宽总和最小&#xff08;窄带假…

vue学习day02-Vue指令-v-html、v-show与v-if、v-else与v-else-if、v-on、v-bind、v-for、v-model

6、Vue指令 指令&#xff1a;带有v-前缀的特殊标签属性 &#xff08;1&#xff09;v-html 作用&#xff1a;设置元素的innerHTML 语法&#xff1a;v-html“表达式” 示例&#xff1a; 提供一个地址&#xff0c;这里是百度的地址&#xff0c;通过v-html渲染 结果&#xff…

深度整合全球资源,分贝通打造高效、合规的海外差旅管理平台

在全球化商业活动的背景下,中国企业出海已成为常态。然而,随着海外差旅市场的全面增长,企业在海外支出管理上面临诸多挑战。据2023年数据显示,分贝通出海差旅业务GMV同比增长高达500倍,这一增长背后隐藏着企业对于更省钱、更高效管控方式的迫切需求。 面对与日俱增的开支,企业开…

【实战场景】大文件解析入库的方案有哪些?

【实战场景】大文件解析入库的方案有哪些&#xff1f; 开篇词&#xff1a;干货篇&#xff1a;分块解析内存映射文件流式处理数据库集群处理分布式计算框架 总结篇&#xff1a;我是杰叔叔&#xff0c;一名沪漂的码农&#xff0c;下期再会&#xff01; 开篇词&#xff1a; 需求背…

品牌策划秘籍:掌握这些技巧,让你的品牌一炮而红!

作为一名文案策划老司机&#xff0c;这么多年了&#xff0c;总会有一些经验的&#xff0c;这里分享出来&#xff0c;希望能够帮助后来人少走弯路吧。 想要做好品牌和文案策划&#xff0c;首先得做好“侦查”工作。 深入市场&#xff0c;了解行业动态&#xff0c;研究竞争对手…

Cesium自定义着色器构件三角面片【闪烁】问题,但是一移动视角就闪烁

问题&#xff1a;已知各个顶点的坐标信息、颜色和索引信息&#xff0c;并自定义绘制三角面片。 但是绘制的三角面片随着视角稍微改动就会出现闪烁现象&#xff01;&#xff01;&#xff01;why? Cesium数据类型的精度问题&#xff0c;例如下面为了获取能接收到高精度坐标信息…

CTF php RCE(二)

0x04 php伪协议 这种我们是先看到了include才会想到&#xff0c;利用伪协议来外带文件内容&#xff0c;但是有些同学会问&#xff0c;我们怎么知道文件名是哪个&#xff0c;哪个文件名才是正确的&#xff0c;那么这里我们就得靠猜了 include函数 因为 include 是一个特殊的语…

3-7 使用深度学习解决温度即示数问题

3-7 使用深度学习解决温度即示数问题 直接上代码 %matplotlib inline import matplotlib.pyplot as plt import numpy as np import torch torch.set_printoptions(edgeitems2, linewidth75)设置Jupyter Notebook在单元格中内嵌显示图像&#xff0c;导入所需库并设置PyTorch的…

Argo CD入门、实战指南

1. Argo CD概述 1.1 什么是 Argo CD Argo CD 是针对 Kubernetes 的声明式 GitOps 持续交付工具。 1.2 为什么选择 Argo CD 应用程序定义、配置和环境应具有声明性并受版本控制。应用程序部署和生命周期管理应自动化、可审计且易于理解。 2. Argo CD基础知识 在有效使用 Ar…

3-6 构建线性模型解决温度计示数转换问题

3-6 构建线性模型解决温度计示数转换问题 直接上源码 %matplotlib inline import numpy as np import torch torch.set_printoptions(edgeitems2, linewidth75)导入必要的库并设置 PyTorch 的打印选项&#xff0c;确保在打印张量时显示边缘项和行宽。 #%% t_c [0.5, 14.0,…

Windows C++ vs2022环境中下载、安装和使用osmesa

第一步&#xff1a;安装 MinGW-w64 请参考这篇文章进行安装&#xff1a; 在Windows中安装MinGW-w64最新版本 第二步&#xff1a;安装DirectX SDK 请参考这篇文章进行安装&#xff1a; 下载安装Microsoft DirectX SDK(June 2010) 第三步&#xff1a;安装Windows SDK 请参考这篇…

书生大模型实战营(暑假场)-入门岛-第一关

书生大模型实战营暑假场重磅开启&#xff01;&#xff0c;这场学习路线看起来很好玩呀&#xff0c;闯关学习既能学到知识又有免费算力可得&#xff0c;太良心啦。感兴趣的小伙伴赶快一起报名学习吧&#xff01;&#xff01;&#xff01; 关卡任务 好的&#xff0c;我们废话不多…

【动态规划Ⅴ】二维数组的动态规划——0/1矩阵、最大正方形

二维数组的动态规划——0/1矩阵、最大正方形 最大正方形1277. 统计全为 1 的正方形子矩阵221. 最大正方形 01矩阵542. 01 矩阵 最大正方形 下面两个题目是非常相似的&#xff0c;只是一个统计正方形数目&#xff0c;一个统计最大正方形的面积。 1277. 统计全为 1 的正方形子矩…

2.5章节python中布尔类型

在Python中&#xff0c;布尔类型&#xff08;Boolean type&#xff09;用于表示真&#xff08;True&#xff09;或假&#xff08;False&#xff09;的值。这是编程中非常基础且重要的一个概念&#xff0c;因为它允许程序进行条件判断&#xff0c;从而根据条件执行不同的代码块。…