Linux的命名管道 共享内存 信号量

news2025/1/16 11:11:11

目录

命名管道

mkfifo函数

unlink函数

命名管道类

服务端

客户端

共享内存

shmget函数

ftok函数

key和shmid的区别

snprintf函数 

ipcs指令 

ipcrm指令

shmctl函数

shmat函数 

void*做返回值

创建共享内存空间

服务端

客户端 

信号量


命名管道

基本概念:用于实现进程间通信的有名管道,让不同的进程看到同一份资源

注意事项:

1、创建时需要提供文件的路径

2、命名管道在文件系统中作为一个特殊的文件而存在,但命名管道中的内容却存放在内存中,向命名管道中写入的数据不会刷新到磁盘中

mkfifo函数

函数原型:int mkfifo(const char *pathname, mode_t mode);

包含头文件: <sys/types.h>  和  <sys/stat.h>

参数:指定文件路径,创建文件时的权限

返回值:成功创建返回0,创建失败返回-1

功能:在文件系统中创建一个命名管道文件,看起来是文件但其实是管道

注意事项:管道文件在磁盘上有文件名和路径,但不占用磁盘空间来存储数据

unlink函数

函数原型:int unlink(const char *pathname);

包含头文件:<unistd.h>

参数:要删除的文件的路径

返回值:成功删除返回0,删除失败返回-1

功能:删除指定的文件

注意事项:若文件的硬链接计数为零,则释放该文件占用的磁盘空间(但是命名管道文件不占用磁盘)

命名管道类

功能负责管道的创建和销毁

/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2024-05-12 13:57:58
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2024-05-12 18:30:48
 * @FilePath: /2024.5.8/home/ubuntu/2024.5.12/namePipe.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <iostream>
#include <cstdio>
#include <cerrno>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const std::string comm_path = "./myfifo"; // 提供文件的路径,string字符串在使用时需要转换为c类型的字符串

#define DefaultFd -1 // 将-1用于标识管道的默认fd(有进程打开管道时再分配新的fd)

#define Creater 1 // 将1用于标识管道的申请者
#define User 2    // 将2用于标识管道的使用者

#define Read O_RDONLY  // 将Read用于标识只读方式
#define Write O_WRONLY // 将Write用于标识只写方式

#define BaseSize 4096 // 将4096作为读取内容的最大字节数

class NamePiped
{
private:
    bool OpenNamedPipe(int mode) // 依据对管道的操作方式
    {
        _fd = open(_fifo_path.c_str(), mode); // 每个进程打开管道时都会获得OS分配给该进程得文件描述符
        if (_fd < 0)
            return false; // 打开文件失败返回false
        return true;      // 打开文件成功返回true
    }

public:
    NamePiped(const std::string &path, int who) // 依据文件路径和身份信息构建管道
        : _fifo_path(path), _id(who), _fd(DefaultFd)
    {
        if (_id == Creater) // 只有申请者才能创建管道
        {
            int res = mkfifo(_fifo_path.c_str(), 0666); // 创建管道
            if (res != 0)
            {
                perror("mkfifo");
            }
            std::cout << "creater create named pipe" << std::endl;
        }
    }

    // 以读方式打开管道
    bool OpenForRead()
    {
        return OpenNamedPipe(Read);
    }

    // 以写方式打开管道
    bool OpenForWrite()
    {
        return OpenNamedPipe(Write);
    }

    // 读管道的方式
    int ReadNamedPipe(std::string *out) // 输出型参数
    {
        char buffer[BaseSize]; // 一次能读取到的最大内容
        int n = read(_fd, buffer, sizeof(buffer));
        if (n > 0)
        {
            buffer[n] = '\0';
            *out = buffer; //*out指向读取到的内容
        }
        return n;
    }

    // 写管道的方式
    int WriteNamedPipe(const std::string &in)
    {
        return write(_fd, in.c_str(), in.size()); // 依据wfd读取
    }

    ~NamePiped()
    {
        if (_id == Creater) // 只有申请者才能创建管道
        {
            int res = unlink(_fifo_path.c_str());
            if (res != 0)
            {
                perror("unlink");
            }
            std::cout << "creater free named pipe" << std::endl;
        }
        if (_fd != DefaultFd) // 关闭写端fd
            close(_fd);
    }

private:
    const std::string _fifo_path; // 提供的文件路径
    int _id;                      // 标识使用者的身份信息
    int _fd;                      // 标识文件描述符
};

服务端

功能:申请并创建管道,以及最后管道的销毁,读取管道中的内容(读端)

/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2024-05-12 13:59:38
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2024-05-12 18:42:19
 * @FilePath: /2024.5.8/home/ubuntu/2024.5.12/sever.cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "namedPipe.hpp"

// server read: 管理命名管道的整个生命周期
int main()
{
    NamePiped fifo(comm_path, Creater);
    // 对于读端而言,如果我们打开文件,但是写还没来,我会阻塞在open调用中,直到对方打开
    // 进程同步
    if (fifo.OpenForRead()) // 调用以读方式打开管道函数
    {
        std::cout << "server open named pipe done" << std::endl;

        sleep(3);
        while (true) // 循环写入数据
        {
            std::string message;
            int n = fifo.ReadNamedPipe(&message);
            if (n > 0)
            {
                std::cout << "Client Say> " << message << std::endl;
            }
            else if (n == 0)
            {
                std::cout << "Client quit, Server Too!" << std::endl;
                break;
            }
            else
            {
                std::cout << "fifo.ReadNamedPipe Error" << std::endl;
                break;
            }
        }
    }

    return 0;
}

客户端

功能:向管道中写入消息,向管道中写入内容(写端)

/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2024-05-12 13:57:27
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2024-05-12 18:52:30
 * @FilePath: /2024.5.8/home/ubuntu/2024.5.12/client.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "namedPipe.hpp"

// write
int main()
{
    NamePiped fifo(comm_path, User); // 管道的使用者
    if (fifo.OpenForWrite())         // 调用以写方式打开管道函数
    {
        std::cout << "client open namd pipe done" << std::endl; // 客户端持续输入
        while (true)
        {
            std::cout << "Please Enter> ";
            std::string message;
            std::getline(std::cin, message); // 将获取的命令行字符串作为message写入管道
            fifo.WriteNamedPipe(message);
        }
    }

    return 0;
}
  • 输入型参数:只读,不修改
  • 输出型参数:由函数初始化或修改,用于返回数据
  • 输入输出型参数:由调用者初始化,由函数修改,并返回修改后的结果

共享内存

  1. 共享内存空间是可以存在多份的,每一对儿通信的进程都有一个共享内存空间 
  2. ①和②都是由OS进行的,用户想要进行这些操作需要使用OS提供的系统调用接口
  3. 共享内存 =  内存空间(数据) + 共享内存的属性
  4. 共享内存不随着进程的结束而自动释放,它会一直存在直到系统重启,需要使用指令和系统调用接口手动销毁内存(共享内存生命周期随内核,文件的生命周期随进程)

shmget函数

函数原型:int shmget(key_t key, size_t size, int shmflg);

包含头文件:<sys/ipc.h>  和  <sys/shm.h>

参数:“协商”后的共享内存空间的标识符,要创建的共享内存空间的大小,操作方式

返回值:创建成功返回标识符

功能:创建新的共享内存段

注意事项:shmflg取值的不同会使得shmget函数产生不同的效果:

  • IPC_CREAT:不存在就新建。存在就,则什么都不干
  • IPC_EXCL:单独使用没有意义需要和IPC_CREAT配合使用
  • IPC_CREAT | IPC_EXCL:使用两个标识符,如果共享内存存在则返回错误,如果不存在则新建一个共享内存段
  • 使用 IPC_CREAT 时,还可以与权限位进行按位或运算来指定共享内存段的访问

ftok函数

函数原型:key_t ftok(const char *pathname, int proj_id);

包含头文件:<sys/ipc.h>  和  <sys/types.h>

参数:用于生成 key 的路径名,项目标识符

返回值:返回生成的 key

功能:根据给定的路径名和项目标识符生成一个 key,生成一个足够随机的用于标识共享内存空间的标识符

注意事项:该函数内部进行的操作是依据路径和项目标识符生成一个key_t类型的随机数,后续两个进程间通信时会使用相同的两个参数生成两个相同的key,从而可以找到对应的共享内存块

key和shmid的区别

        key是一个由自定义的(文件路径 + 随机值)经过ftok函数中的算法生成的一个随机值,服务端和客户端共用一个key,服务端将该key交给OS提供的系统调用接口shmget就可以创建一块共享内存空间并获取OS对于该块共享内存空间的标识符shmid,服务端也将该key交给shmget可以获得与服务端相同的shmid(相当于服务端会去创建一个共享内存空间用于二者间的通信,但是客户端会找不到,于是二者提前约定好一个key,服务端说我会用这个key交给shmget会创建一个共享内存空间并得到它的shmid,你找的时候就用这个key去找,找的方式就是也将key交给shmget同时你要保证你是寻找而不是创建,将咱俩约定好的key交给shmget后它会告诉你我创建的共享内存空间的shmid是什么,之后咱俩就拿着这个shmid交流了),最后客户端和服务端就要利用该shmid访问该块共享内存空间(服务端和客户端有一对儿一样的钥匙,服务端用钥匙去找前台shmget开了一个只能用该钥匙打开的房间号为shmid的房间,客户端来找服务端的时候也要去找前台shmget说之前有一个人拿着跟我一样的钥匙开了个房间你告诉我这个房间号吧,然后shmget就拿着你的钥匙去找之前的开房信息,发现你这把钥匙对应了某个房间号,然后后就将该房间号shmid,告诉客户端)

snprintf函数 

函数原型:int snprintf(char *str, size_t size, const char *format, ...);

包含头文件:<stdio.h>

参数:待写入的目标字符串,要写入的长度(可以包括\0),格式化字符串,可变参数列表

返回值:写入到字符串中的字符数

功能:向目标字符串中写入指定长度的字符

注意事项:是sprintf的升级版

ipcs指令 

功能:查看共享内存段信息的命令

常见用法:

1、ipcs -m查看共享内存段信息

  • 键值 (key):用于唯一标识共享内存段的键值
  • 权限 (perms):显示共享内存段的权限,包括所有者、组和其他用户的权限
  • 拥有者 (owner):拥有共享内存段的用户
  • 组 (group):拥有共享内存段的用户组
  • 大小 (bytes):共享内存段的大小(以字节为单位)
  • 连接的进程 (nattch):当前连接到共享内存段的进程数量
  • 最后连接时间 (attime):最后一个进程连接到共享内存段的时间

ipcrm指令

功能:删除共享内存段

常见用法:ipcrm -m 共享内存的shmid

shmctl函数

函数原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);

包含头文件: <sys/ipc.h>  和  <sys/shm.h>

参数:共享内存段的标识符,指定要执行的操作,指向共享内存空间属性结构体的指针

返回值:成功指向返回

功能:对共享内存段进行相关操作,比如:

  • 获取共享内存段的信息(cmd = IPC_STAT)
  • 设置共享内存段的权限(cmd = IPC_SET)
  • 删除共享内存段(cmd = IPC_RMID)
struct shmid_ds ds;
int n = shmctl(_shmid, IPC_STAT, &ds);

shmat函数 

函数原型:void *shmat(int shmid, const void *shmaddr, int shmflg);

包含头文件:<sys/types.h>  和  <sys/shm.h>

参数: 共享内存段的标识符,指定共享内存连接到进程地址空间的地址,IPC选项

返回值:连接成功返回指向共享内存空间(虚拟地址)首字节的指针,失败返回-1

功能:将共享内存空间连接到调用进程的地址空间,以便该进程可以访问和操作共享内存中的数据

注意事项:shmaddr的取值通常为NULL,表示让OS自动选择合适的地址,shmflg通常为0

int shmdt(const void* shmaddr)为取消连接函数,与shmat函数一样的头文件,shmaddr指向要分离的共享内存段的地址

void*做返回值

使用原因:void*是一种通用指针类型,可以指向任何类型的数据,当函数需要返回一个指针但该指针指向的数据类型可能不确定时(比如malloc函数只负责申请空间并返回一个指向该内存空间的void*类型的指针,调用者要根据需要将该void*指针转换为新类型的指针,从而告诉编译器我们在这块内存中存放的是什么类型的数据),通常会将返回类型声明为void*(内存中的某个位置本身并没有数据类型,数据类型是用来解释内存中的内容的方式。当我们将一个指针转换为特定类型的指针时,我们告诉编译器如何解释这块内存中的内容)

注意事项:在使用void* 类型的返回值时,通常需要将其转换为实际的数据类型,以便正确的访问和操作数据

创建共享内存空间

#ifndef _SHM_HPP_ // 头文件只能包含一次
#define _SHM_HPP_

#include <iostream>
#include <string>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

// 创建使用者的标识
const int gCreater = 1;
const int gUser = 2;

// 自定义全局全局参数用于让两个通信的进程生成同样的key
const std::string gpathname = "/home/ubuntu/2024.5.13";
const int gproj_id = 0x66;

// 自定义共享内存空间的大小,一般为4096 * n
const int gShmSize = 4096;

class Shm
{
    // 不希望将这些接口暴露给用户,用户只需要使用即可
private:
    // 获取key
    key_t GetCommKey()
    {
        key_t k = ftok(_pathname.c_str(), _proj_id);
        if (k < 0)
        {
            perror("ftok");
        }
        return k;
    }

    // 创建共享内存空间
    int GetShmHelper(key_t key, int size, int flag)
    {
        int shmid = shmget(key, size, flag);
        if (shmid < 0)
        {
            perror("shmget");
        }
        return shmid;
    }

    // 将角色转换为字符串
    std::string RoleToString(int who)
    {
        if (who == gCreater)
            return "Creater";
        else if (who == gUser)
            return "User";
        else
            return "None";
    }

    // 将共享内存空间挂接到进程地址空间,调用该函数相当于调用malloc函数
    void *AttachShm()
    {
        if (_addrshm != nullptr)
            DatechShm(_addrshm);

        std::cout
            << "进行挂接" << std::endl;
        void *shmaddr = shmat(_shmid, nullptr, 0);
        if (shmaddr == nullptr) // 挂接失败
        {
            perror("shmat");
        }

        std::cout << "who: " << RoleToString(_who) << " attach shm..." << std::endl;
        return shmaddr;
    }

    // 解除挂接
    void DatechShm(void *shmaddr)
    {
        std::cout << "解除挂接" << std::endl;
        if (shmaddr == nullptr)
            return;
        shmdt(shmaddr);
        std::cout << "who: " << RoleToString(_who) << " detach shm..." << std::endl;
    }

public:
    // 构造函数
    Shm(const std::string &pathname, int proj_id, int who)
        : _pathname(pathname), _proj_id(proj_id), _who(who), _addrshm(nullptr)
    {
        _key = GetCommKey();
        if (_who == gCreater) // 如果是创建者就调用专门为创建者准备的函数GetShmForCreater
            GetShmForCreater();
        else if (_who == gUser) // 如果是使用者就调用专门为使用者准备的函数GetShmForUser
            GetShmForUser();
        std::cout << "shmid: " << _shmid << std::endl;
        std::cout << "_key: " << ToHex(_key) << std::endl;
        if (_who == gUser)
        {
            std::cout << "shm get done..." << std::endl;
        }
        // 不论是谁只要获取到一个共享内存空间的shmid,就将该共享内存空间挂接到进程地址空间上
        _addrshm = AttachShm();
    }

    // 析构函数:删除共享内存空间
    ~Shm()
    {
        if (_who == gCreater)
        {
            int res = shmctl(_shmid, IPC_RMID, nullptr);
            std::cout << "shm remove done..." << std::endl;
        }
    }

    // 将key转换为16进制,便于后续的查看
    std::string ToHex(key_t key)
    {
        char buffer[128];
        snprintf(buffer, sizeof(buffer), "0x%x", _key);
        return buffer;
    }

    // 服务端创建共享内存空间
    bool GetShmForCreater()
    {
        _shmid = GetShmHelper(_key, gShmSize, IPC_CREAT | IPC_EXCL | 0666); // 如果没有就创建,如果有了就返回错误,即没有返回错误那么就是创建了一个新的共享内存空间
        if (_shmid >= 0)                                                    // 0666表示所有者、所属组和其他用户对共享内存空间都有读写权限,但没有执行权限
        {
            std::cout << "shm creat done..." << std::endl;
            return true; // 创建成功返回true
        }
        std::cout << "shm creat fail..." << std::endl;
        return false;
    }

    // 客户端使用共享内存
    bool GetShmForUser()
    {
        _shmid = GetShmHelper(_key, gShmSize, IPC_CREAT | 0666); // 使用者根据与创造者一样得_key获得依据创造者创造的共享内存空间得shmid,仅有IPC_CREAT是因为此时服务端已经创建好了共享内存空间此时用户端只需要找到它对应的共享内存空间的shmind即可
        if (_shmid >= 0)
        {
            return true; // 获取成功返回true
        }
        std::cout << "shm get fail..." << std::endl;
        return false;
    }

    // 获取进程空间的地址
    void *Addr()
    {
        return _addrshm;
    }

    // 清空共享内存空间
    void Zero()
    {
        if (_addrshm)
        {
            memset(_addrshm, 0, gShmSize);
        }
    }

    //  获取共享内存空间属性结构体中的内容
    void DebugShm()
    {
        struct shmid_ds ds;
        int n = shmctl(_shmid, IPC_STAT, &ds); //
        if (n < 0)
            return;
        std::cout << "ds.shm_perm.__key : " << ToHex(ds.shm_perm.__key) << std::endl;
        std::cout << "ds.shm_nattch: " << ds.shm_nattch << std::endl;
    }

private:
    key_t _key;
    int _shmid;

    std::string _pathname;
    int _proj_id;
    int _who;

    void *_addrshm;
};

#endif

服务端

/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2024-05-12 23:03:25
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2024-05-14 17:41:26
 * @FilePath: /2024.5.8/home/ubuntu/2024.5.13/server.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "shm.hpp"
#include "namedPipe.hpp"

int main()
{
    // 1. 创建共享内存
    Shm shm(gpathname, gproj_id, gCreater);
    char *shmaddr = (char *)shm.Addr();

    shm.DebugShm();

    // 2. 创建管道
    NamePiped fifo(comm_path, Creater);
    fifo.OpenForRead(); // 以读方式打开管道

    while (true)
    {
        std::string temp;
        fifo.ReadNamedPipe(&temp);//将读到的内容写入字符串中

        std::cout << "shm memory content: " << shmaddr << std::endl;
    }

    sleep(5);

    return 0;
}

客户端 

/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2024-05-12 23:03:16
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2024-05-14 17:38:18
 * @FilePath: /2024.5.8/home/ubuntu/2024.5.13/client.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "shm.hpp"
#include "namedPipe.hpp"

int main()
{
    // 1. 创建共享内存

    Shm shm(gpathname, gproj_id, gUser);
    shm.Zero();
    char *shmaddr = (char *)shm.Addr();//shmaddr指向一段内存空间
    sleep(3);

    // 2. 打开管道(利用管道保护共享内存空间)
    NamePiped fifo(comm_path, User);
    fifo.OpenForWrite(); // 以写方式打开管道

    // 当成string
    char ch = 'A';
    while (ch <= 'Z')
    {
        shmaddr[ch - 'A'] = ch;

        std::string temp = "wakeup";
        std::cout << "add " << ch << " into Shm, " << "wakeup reader" << std::endl;
        fifo.WriteNamedPipe(temp);
        sleep(2);
        ch++;
    }
    return 0;
}

1、使用管道是因为共享内存空间不会提供对自己本身的保护机制,这就会导致数据不一致问题(客户端还没写完,服务端就疯狂的读取),在两个进程间都能访问到同一块共享内存空间后,在两个进程间创建管道,

信号量

~over~

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

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

相关文章

Unity使用sherpa-onnx实现离线语音合成

sherpa-onnx https://github.com/k2-fsa/sherpa-onnx 相关dll和lib库拷进Unity&#xff0c;官方示例代码稍作修改 using SherpaOnnx; using System; using System.IO; using System.Runtime.InteropServices; using UnityEngine;public class TTS : MonoBehaviour {public st…

基于java 自定义注解Annotation设计简单ORM框架——进阶篇

目录 引言实例新建两个注解标注实体类拼接sql语句 总结 引言 一般Java规范编程&#xff08;只是一种习惯&#xff0c;而不是强制&#xff09;中&#xff0c;变量的命名方式一般采用驼峰式命名。比如userName&#xff0c;userImage。但是在数据库中一般不会采用驼峰式&#xff…

工业物联网解决方案:机房动环监控系统

工业物联网解决方案&#xff1a;机房动环监控系统 工业物联网&#xff08;IIoT&#xff09;作为数字化转型的关键驱动力&#xff0c;正深刻改变着各行各业的运作模式&#xff0c;其中机房动环监控系统是实现智能化运维管理的重要组成部分。该系统通过集成传感器技术、大数据分…

位图(c++)

文章目录 1.位图概念2.位图的实现3.应用&#xff08;解决整形存在或次数问题&#xff09;3.1存在问题3.2次数问题 5.搜索的方法对比&#xff1a; 1.位图概念 和哈希一样&#xff0c;都是一个表来记录某个元素的个数或者存在与否&#xff1b;不同的是哈希使用的计算机定义的完整…

跨境必看|TikTok账号运营的八大秘籍

国内的传统生意都是可以在抖音上做&#xff0c;那么也可以在TikTok 上重新做一遍。那该如何才能把握住这片巨大的蓝海&#xff0c;TikTok 账号的运营就成为了主要的关键了&#xff0c;对于TikTok账号运营的八大秘籍&#xff0c;大家一起看看是如何做的&#xff1f; 一、固定节…

部署管理征信链码

一 . 链码准备 需要删除上面后面标记的文件&#xff0c;之后拖入 二. 打包链码 注意需要先启动链 打包测试链码 export FABRIC_CFG_PATH${PWD}/config peer lifecycle chaincode package ./chaincode/chaincode_basic.tar.gz --path ./chaincode/credit_chaincode --lang n…

VMware虚拟机安装详细教程

VMware下载安装好后&#xff0c;下载好我们要安装的操作系统的镜像文件后&#xff0c;此处安装的为centos7版本&#xff0c;就可以开始安装了。 1点击下一步 image 2、勾选【我接受条件款协议中的条款】&#xff0c;然后点击【下一步】。 image 3、取消勾选&#xff0c;然后点…

【瑞萨RA6M3】1. 基于 vscode 搭建开发环境(后续)

编译 mkdir build cd build cmake .. -G"Unix Makefiles" make -j或者 cmake -Bbuild -G"Unix Makefiles" cmake --build build创建快捷指令&#xff1a; 删除 .vscode/tasks.json&#xff0c; 存储占用和生成 MAP 编译完成后&#xff0c;打印内存占用…

大数据可视化实验(五):Tableau数据可视化

目录 一、实验目的... 1 二、实验环境... 1 三、实验内容... 1 1&#xff09;打开数据源... 1 2&#xff09;进入工作簿... 2 3&#xff09;字段设置... 2 4&#xff09;数据筛选... 3 5&#xff09;绘制条形图... 3 四、思考问题... 4 五、总结与心得体会... 4 一、…

04-单片机商业项目编程,从零搭建低功耗系统设计

一、本文内容 上一节《03-单片机商业项目编程&#xff0c;从零搭建低功耗系统设计-CSDN博客》我们确定了设计思路&#xff0c;并如何更有效的保持低功耗&#xff0c;这节我们就准备来做软件框架设计。在AI飞速发展的时代&#xff0c;我们也会利AI来辅助我们完成&#xff0c;让自…

【Image captioning】In Defense of Grid Features for Visual Question Answering实现流程

In Defense of Grid Features for Visual Question Answering实现流程 网格特征预训练代码 这是该论文的特征预训练代码发布: @InProceedings{jiang2020defense,title={In Defense of Grid Features for Visual Question Answering},author={Jiang, Huaizu and Misra, Ishan…

机器学习实战宝典:用scikit-learn打造智能应用

书接上文——《数据探险家的终极指南&#xff1a;用Python挖掘机器学习的奥秘》 前文我们在这段精彩的机器学习探险之旅中&#xff0c;从基础概念出发&#xff0c;深入探索了使用Python和scikit-learn库进行数据分析和模型构建的全过程。 我们首先了解了机器学习的基本原理&am…

通义千问 1.5 -7B fine-tune验证

尝试对对中文数据进行finetune验证&#xff0c;测试模型的可优化方向。下面是代码的详细情况 代码实现 from datasets import load_dataset from transformers import (AutoModelForCausalLM,AutoTokenizer,BitsAndBytesConfig,HfArgumentParser,AutoTokenizer,TrainingArgum…

hadoop学习---基于Hive的数据仓库相关函数机制及其优化方案

Hive相关函数&#xff08;部分&#xff09;&#xff1a; if函数: 作用: 用于进行逻辑判断操作 语法: if(条件, true返回信息,false返回信息) 注意: if函数支持嵌套使用 select if(aa,’bbbb’,111) fromlxw_dual; bbbb select if(1<2,100,200) fromlxw_dual; 200nvl函数:…

【Python】理解WOE(Weight of Evidence)和IV(Information Value)

忠孝东路走九遍 脚底下踏著曾经你我的点点 我从日走到夜 心从灰跳到黑 我多想跳上车子离开伤心的台北 忠孝东路走九遍 穿过陌生人潮搜寻你的脸 有人走的匆忙 有人爱的甜美 谁会在意擦肩而过的心碎 &#x1f3b5; 动力火车《忠孝东路走九遍》 在信用评分和…

教育型内容的制胜秘诀:Kompas.ai如何结合知识与营销

在数字化营销的浪潮中&#xff0c;教育型内容已经成为品牌建立权威性和提供价值的重要手段。通过分享专业知识和见解&#xff0c;品牌不仅能够吸引目标受众&#xff0c;还能够在潜在客户心中建立起专业和可信赖的形象。本文将深入分析教育型内容的重要性&#xff0c;详细介绍Ko…

VALSE 2024合合信息 | 文档解析与向量化技术加速多模态大模型训练与应用

第十四届视觉与学习青年学者研讨会&#xff08;VALSE 2024&#xff09;近期在重庆悦来国际会议中心圆满举行&#xff0c;由中国人工智能学会&#xff08;CAAI&#xff09;、中国图象图形学会&#xff08;CSIG&#xff09;、中国民族贸易促进会主办&#xff0c;重庆邮电大学承办…

数据库系统概论(个人笔记)(第二部分)

数据库系统概论&#xff08;个人笔记&#xff09; 文章目录 数据库系统概论&#xff08;个人笔记&#xff09;2、关系模型简介2.1 关系数据库的结构2.2 数据库模式2.3 键2.4 模式图2.5 关系查询语言2.6 关系代数 2、关系模型简介 2.1 关系数据库的结构 Structure of Relational…

【目标检测】YOLOv5|YOLOv8模型QT界面可视化部署

YOLO-Deploy-QT_Interface 最近笔者做了YOLO系列算法的部署工作,现做一个总结。主要工作是做了用于部署YOLOv5和YOLOv8的可视化QT界面,可实现图片、文件夹、视频、摄像头的ONNX与OpenVino部署,具体效果如下: 代码链接:https://github.com/Zency-Sun/YOLO-Deploy-QT_Inte…

开源之夏又有新项目发布!快来认领!¥12,000 奖金等你来!

又有新项目加入开源之夏啦&#xff01;KubeBlocks 的亲兄弟 WeScale 也加入开源之夏啦&#xff01;一起来了解下 WeScale 社区及它带来的项目吧&#xff01; WeScale 是什么&#xff1f; WeScale 社区源自对更好的数据库访问体验的追求。在现代应用程序开发中&#xff0c;数据…