学习记录——day27 进程间通信 IPC通信机制 消息队列 共享内存

news2024/12/28 4:14:31

目录

一、IPC通信机制

1、system V提供了三种IPC(interprocess communication)进程间通信方式 消息队列 共享内存 信号量集

2、该通信机制是独立于进程而存在的:当进程将数据写入该通信对象中后,即使进程已经结束,对象中保存的内容仍然存在

3、IPC对象相关指令   ipcs  ipcrm

二、消息队列

1、消息队列的特点

2、消息队列的相关API函数接口 ftok msgget msgsnd msgrcv msgctl

 3、发送端实现

4、接收端实现

5、 获取消息队列的属性

三、共享内存

1、特点

2、共享内存的PAI函数接口  shmget  shmat shmdt

 3、发送端实现

4、接收端实现

使用消息队列完成两个进程之间相互通信

00snd.c

00rcv.c


 

一、IPC通信机制

1、system V提供了三种IPC(interprocess communication)进程间通信方式 消息队列 共享内存 信号量集

消息队列:本质上是在内核空间维护的一个队列,发送者可以将消息先放入到该队列上,接收者根据自己的需求读取队列上的信息
共享内存:在进程外申请一个物理内存,不同进程可以通过内存映射的方式共同使用这段内存,类似于多线程中的临界资源,同样存在竟态,通过使用信号量解决
信号量集:将多个无名信号量,放入一个集合中,分别控制不同的进程,用于进程间同步问题

2、该通信机制是独立于进程而存在的:当进程将数据写入该通信对象中后,即使进程已经结束,对象中保存的内容仍然存在

3、IPC对象相关指令   ipcs  ipcrm

1)ipcs                              查看当前所有的ipc对象的信息
2)ipcs -q                          查看消息队列的信息
3)ipcs -m                         查看共享内存的信息
4)ipcs -s                          查看信号量集的信息
5)ipcrm -q\-m\-s   ID号    删除指定的ipc对象

二、消息队列

1、消息队列的特点

1)放入消息队列中的消息需要进行封装,包括消息类型和消息数据

2)消息队列的消息遵循先进先出原则,如果取出时不指定类型,则默认取第一个,如果指定了类型,则取该类型第一个放入队列中的消息

3)消息队列相关API函数接口

4)消息队列的大小为 16k

2、消息队列的相关API函数接口 ftok msgget msgsnd msgrcv msgctl

1)创建用于生成消息队列的钥匙
       #include <sys/types.h>
       #include <sys/ipc.h>

       key_t ftok(const char *pathname, int proj_id);
        功能:通过给定的文件路径和一个随机ID值创建出一个用于IPC通信的key值       ftok("/", 'k');
        参数1:文件路径,该文件的inode号占key值的2字节,该文件的设备号占key值的1字节
        参数2:一个给定的随机值,该值占key值的1字节
        返回值:成功返回创建出的key值,失败返回-1并置位错误码

2)通过钥匙创建出一个消息队列对象
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/msg.h>

       int msgget(key_t key, int msgflg);
        功能:通过给定的key值创建一个消息队列
        参数1:用于创建消息队列的key值,该值可以由ftok创建出来,也可以是 IPC_PRIVATE,表示进行亲缘进程间的通信
        参数2:创建标识位
                IPC_CREAT:表示本次操作要创建一个消息队列,如果该key值对应的消息队列已经存在,则直接打开该消息对象
                IPC_EXCL:表示本次确保要创建一个新的消息队列,如果该消息队列已经存在,则该函数报错,错误码为EEXIST
                创建文件的权限,也在该参数中,使用位或连接
        返回值:成功返回消息队列的id号,失败返回-1并置位错误码

3)向消息队列中存放消息
       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
       功能:向消息队列中存放消息,要求当前进程对消息队列具有可写权限
       参数1:消息队列的id号
       参数2:是指向封装好的消息的起始地址,通常类型如下,但是需要用户自己定义
          struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[1];    /* message data */
           };
        参数3:表示参数2中,消息正文的大小,不包含消息类型的大小
        参数4:发送标识位,表示是否阻塞
            0:表示阻塞
            IPC_NOWAIT:表示非阻塞
        返回值:成功返回0,失败返回-1并置位错误码

4)从消息队列中取消息
        size_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
        功能:从消息队列中取消息
        参数1:消息队列的id号
        参数2:存放消息的容器起始地址
        参数3:消息正文的大小
        参数4:取出消息的类型
                >0: 表示取出该类型的消息的第一个消息
                =0:不限制类型,直接取消息队列中的第一个
                <0: 取出消息队列中类型小于msgtyp绝对值的第一个
                    例如:  50   10   2   10    6   6  8
                    -7:    2  6  6 ---> 2
        参数5:是否阻塞
            0:表示阻塞
            IPC_NOWAIT:表示非阻塞
        返回值:成功返回成功读取的字节个数,失败返回-1并置位错误码

5)控制消息队列
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/msg.h>

       int msgctl(int msqid, int cmd, struct msqid_ds *buf);
       功能:完成对消息队列指定的cmd操作
       参数1:消息队列的id号
       参数2:操作指令
          IPC_STAT:获取消息队列的属性,此时参数3必须要给定,表示接收消息队列的属性
             struct msqid_ds {
               struct ipc_perm msg_perm;     /* 拥有者和权限 */
               time_t          msg_stime;    /* 最新一次向消息队列中发送数据的时间 */
               time_t          msg_rtime;    /* 最新一次消息队列接受数据的时间 */
               time_t          msg_ctime;    /* 最新一次操作消息队列的时间 */
               unsigned long   __msg_cbytes; /* 当前队列中已用的字节数 */
               msgqnum_t       msg_qnum;     /* 当前队列中消息的个数*/
               msglen_t        msg_qbytes;   /* 队列的最大容量,默认是16K */
               pid_t           msg_lspid;    /* 最后一次向消息队列中发送消息的进程id号 */
               pid_t           msg_lrpid;    /* 最后一次从消息队列中取消息的进程id号 */
           };
               对第一个成员的介绍
              struct ipc_perm {
               key_t          __key;       /* 键值 */
               uid_t          uid;         /* 当前拥有者的用户id号 */
               gid_t          gid;         /*当前拥有者的组id号 */
               uid_t          cuid;        /* 创建消息队列的进程的用户id */
               gid_t          cgid;        /* 创建消息队列进程的组id号 */
               unsigned short mode;        /* 操作权限 */
               unsigned short __seq;       /* 队列号 */
           };
         IPC_SET:设置消息队列的属性  
         IPC_RMID:删除消息队列,当参数2位该值时,参数3可以忽略,直接填NULL即可
         返回值:成功返回0,失败返回-1并置位错误码

 3、发送端实现

#include<myhead.h>
//要发送的消息类型
struct msgbuf 
{
    long mtype;       /* message type, must be > 0 */
    char mtext[1024];    /* message data */
};
#define SIZE sizeof(struct msgbuf)-sizeof(long)


int main(int argc, const char *argv[])
{
    //1、创建key值,用于生产消息队列
    key_t key = ftok("/", 'k');
    if(key == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    //2、通过key值创建一个消息队列
    int msqid = msgget(key, IPC_CREAT|0664);
    if(msqid == -1)
    {
        perror("msgget error");
        return -1;
    }
    printf("msqid = %d\n", msqid);        //id号

    //向消息队列中存放消息
    struct msgbuf buf;
    
    while(1)
    {
        printf("请输入消息类型:");
        scanf("%ld", &buf.mtype);
        getchar();                    //吸收回车
        printf("请输入消息正文:");
        fgets(buf.mtext, SIZE, stdin);        //从终端获取数据
        buf.mtext[strlen(buf.mtext)-1] = 0;   //将换行换成 '\0'

        //将消息发送到消息队列中
        msgsnd(msqid, &buf, SIZE, 0);
        //参数1:消息队列id号
        //参数2:消息的起始地址
        //参数3:消息正文大小
        //参数4:阻塞形式发送数据
        printf("发送成功\n");

        if(strcmp(buf.mtext, "quit") == 0)
        {
            break;
        }
    }

    return 0;
}

4、接收端实现

#include<myhead.h>
//要发送的消息类型
struct msgbuf 
{
    long mtype;       /* message type, must be > 0 */
    char mtext[1024];    /* message data */
};
#define SIZE sizeof(struct msgbuf)-sizeof(long)


int main(int argc, const char *argv[])
{
    //1、创建key值,用于生产消息队列
    key_t key = ftok("/", 'k');
    if(key == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    //2、通过key值创建一个消息队列
    int msqid = msgget(key, IPC_CREAT|0664);
    if(msqid == -1)
    {
        perror("msgget error");
        return -1;
    }
    printf("msqid = %d\n", msqid);        //id号

    //从消息队列中读取消息
    struct msgbuf buf;
    
    while(1)
    {
        msgrcv(msqid, &buf, SIZE, 0, 0);
        //参数1:消息队列id号
        //参数2:数据容器起始地址
        //参数3:数据的正文大小
        //参数4:消息类型,0表示任意类型
        //参数5:表示阻塞读取消息

        printf("收到消息为:%s\n", buf.mtext);
    }

    return 0;
}

5、 获取消息队列的属性

#include<myhead.h>


int main(int argc, const char *argv[])
{
    //1、创建key值,用于生产消息队列
    key_t key = ftok("/", 'k');
    if(key == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    //2、通过key值创建一个消息队列
    int msqid = msgget(key, IPC_CREAT|0664);
    if(msqid == -1)
    {
        perror("msgget error");
        return -1;
    }
    printf("msqid = %d\n", msqid);        //id号

    //获取该消息队列的属性
    struct msqid_ds ds;          //用于存放消息队列属性的变量
    if(msgctl(msqid, IPC_STAT, &ds) == -1)
    {
        perror("msgctl error");
        return -1;
    }

    //程序执行至此,该消息队列中的相关信息就被存入到ds结构体中了
    printf("键:%#x, msqid:%d, 权限:%#o, 已用字节:%ld, 消息:%ld\n", \
            ds.msg_perm.__key, msqid, ds.msg_perm.mode, ds.__msg_cbytes,\
            ds.msg_qnum);



    return 0;
}

三、共享内存

1、特点

1)共享内存是多个进程共享一个外部的物理内存,直接访问内存获取数据,避免了数据的传输,使得效率较高

2)共享内存具有时效性,存放到共享内存区域中的数据,如果不及时读取,下一次写入后,前面的数据会被覆盖

3)共享内存的操作不是一次性的,写入到共享内存中的数据,即使读取出去后,依然存在于共享内存,直到下一次写入

2、共享内存的PAI函数接口  shmget  shmat shmdt

1)创建共享内存对象
         #include <sys/ipc.h>
       #include <sys/shm.h>

       int shmget(key_t key, size_t size, int shmflg);
       功能:通过给定的key值创建一个共享内存的对象,并返回该对象的id
       参数1:key值,可以是IPC_PRIVATE也可以是由ftok创建出来的
       参数2:申请的共享内存段的大小,必须是PAGE_SIZE的整数倍,如果超过,则向上取整
       参数3:创建的标识
                IPC_CREAT:表示本次操作要创建一个共享内存,如果该key值对应的共享内存已经存在,则直接打开该共享内存对象
                IPC_EXCL:表示本次确保要创建一个新的共享内存,如果该共享内存已经存在,则该函数报错,错误码为EEXIST
                创建文件的权限,也在该参数中,使用位或连接
        返回值:成功返回创建出来的共享内存的id,失败返回-1并置位错误码
 
2)将共享内存地址映射到用户空间
       void *shmat(int shmid, const void *shmaddr, int shmflg);
       功能:映射共享内存的地址到用户空间
       参数1:共享内存ID
       参数2:对齐页地址,一般填NULL,让系统选择合适的对齐页
       参数3:共享内存的权限
           SHM_RDONLY:只读权限
           0:    读写权限
       返回值:  成功返回映射的共享内存段的地址,失败返回(void *)-1并置位错误码          
       
 3)取消共享内存的映射
             int shmdt(const void *shmaddr);
             功能:取消共享内存的映射
             参数:共享内存映射的地址
             返回值:成功返回0,失败返回-1并置位错误码
                 
 4)共享内存的控制函数
        #include <sys/ipc.h>
       #include <sys/shm.h>

       int shmctl(int shmid, int cmd, struct shmid_ds *buf);
       功能:控制共享内存对象
       参数1:共享内存的id号
       参数2:操作指令
          IPC_STAT:获取共享内存的属性,此时参数3必须要给定,表示接收共享内存的属性
         IPC_SET:设置共享内存的属性  
         IPC_RMID:删除共享内存,当参数2位该值时,参数3可以忽略,直接填NULL即可
        返回值: 成功返回0,失败返回-1并置位错误码      

 3、发送端实现

#include<myhead.h>
#include<sys/user.h>

int main(int argc, const char *argv[])
{
    //1、创建key值用于创建共享内存段
    key_t key = ftok("/", 't');
    if(key == -1)
    {
        perror("ftok error");
        return -1;
    }

    printf("key = %d\n", key);

    //2、创建一个共享内存的对象
    int shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664);
    if(shmid == -1)
    {
        perror("shmget error");
        return -1;
    }
    printf("shmid = %d\n", shmid);

    //3、将共享内存段映射到程序中来
    char *addr = (char *)shmat(shmid, NULL, 0);
    //参数1:共享内存的id号
    //参数2:系统自动映射对齐页
    //参数3:表示对共享内存的操作权限为读写权限
    printf("addr = %p\n", addr);         //输出映射的地址

    //向共享内存中写入数据
    strcpy(addr, "hello a hua qing yuan jian\n");

    sleep(5);

    //取消映射关系
    if(shmdt(addr) ==-1)
    {
        perror("shmdt error");
        return -1;
    }


    while(1);

    return 0;
}

4、接收端实现

#include<myhead.h>
#include<sys/user.h>

int main(int argc, const char *argv[])
{
    //1、创建key值用于创建共享内存段
    key_t key = ftok("/", 't');
    if(key == -1)
    {
        perror("ftok error");
        return -1;
    }

    printf("key = %d\n", key);

    //2、创建一个共享内存的对象
    int shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664);
    if(shmid == -1)
    {
        perror("shmget error");
        return -1;
    }
    printf("shmid = %d\n", shmid);

    //3、将共享内存段映射到程序中来
    char *addr = (char *)shmat(shmid, NULL, 0);
    //参数1:共享内存的id号
    //参数2:系统自动映射对齐页
    //参数3:表示对共享内存的操作权限为读写权限
    printf("addr = %p\n", addr);         //输出映射的地址

    //读出共享内存中的数据
    printf("消息为:%s", addr);

    sleep(5);
    if(shmdt(addr) == -1)
    {
        perror("shmdt error");
        return -1;
    }

    //删除共享内存
    if(shmctl(shmid, IPC_RMID, NULL) == -1)
    {
        perror("shmctl error");
        return -1;
    }


    while(1);

    return 0;
}

使用消息队列完成两个进程之间相互通信

00snd.c

#include <myhead.h>

// 要发送的信息类型
struct msgbuf
{
    long mtype;
    char mtext[1024];
};

#define SIZE sizeof(struct msgbuf) - sizeof(long)

int main(int argc, char const *argv[])
{
    // 1、创建key值用于生成消息队列
    key_t key = ftok("/", 'k');
    if (key == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    // 2、通过key值创建一个消息队列
    int msqid = msgget(key, IPC_CREAT | 0664);
    if (msqid == -1)
    {
        perror("msgget error");
        return -1;
    }
    printf("msqid = %d\n", msqid);

    // 3、创建父子进程
    pid_t pid;
    if ((pid = fork()) == -1)
    {
        perror("fork error");
        return -1;
    }
    else if (pid == 0)
    {
        // 子进程
        // 4、从消息队列接收信息
        struct msgbuf buf;
        while (1)
        {
            msgrcv(msqid, &buf, SIZE, 2, 0);
            printf("进程1子程序收到信息:%s\n", buf.mtext);

            if (strcmp(buf.mtext, "quit") == 0)
            {
                break;
            }
        }

        exit(EXIT_SUCCESS);
    }

    // 父进程
    //  3、向消息队列中输入数据
    struct msgbuf buf;
    buf.mtype = 1;
    while (1)
    {
        printf("进程1父程序输入信息:");
        fgets(buf.mtext, SIZE, stdin);
        buf.mtext[strlen(buf.mtext) - 1] = 0;

        // 将信息发送到消息队列中
        msgsnd(msqid, &buf, SIZE, 0);
        printf("发送结束\n");

        if (strcmp(buf.mtext, "quit") == 0)
        {
            break;
        }
    }
    //回收子程序资源
    wait(NULL);
    // 删除消息队列
    if (msgctl(msqid, IPC_RMID, NULL) == -1)
    {
        perror("msgctl error");
        return -1;
    }

    return 0;
}

00rcv.c

#include <myhead.h>

// 要发送的信息类型
struct msgbuf
{
    long mtype;
    char mtext[1024];
};

#define SIZE sizeof(struct msgbuf) - sizeof(long)

int main(int argc, char const *argv[])
{
    // 1、创建key值用于生成消息队列
    key_t key = ftok("/", 'k');
    if (key == -1)
    {
        perror("ftok error");
        return -1;
    }
    printf("key = %#x\n", key);

    // 2、通过key值创建一个消息队列
    int msqid = msgget(key, IPC_CREAT | 0664);
    if (msqid == -1)
    {
        perror("msgget error");
        return -1;
    }
    printf("msqid = %d\n", msqid);

    // 3、创建父子进程
    pid_t pid;
    if ((pid = fork()) == -1)
    {
        perror("fork error");
        return -1;
    }
    else if (pid == 0)
    {
        // 子进程
        // 4、向消息队列中输入数据
        struct msgbuf buf;
        buf.mtype = 2;
        while (1)
        {
            printf("进程2子程序输入信息:");
            fgets(buf.mtext, SIZE, stdin);
            buf.mtext[strlen(buf.mtext) - 1] = 0;

            // 将信息发送到消息队列中
            msgsnd(msqid, &buf, SIZE, 0);
            printf("发送结束\n");

            if (strcmp(buf.mtext, "quit") == 0)
            {
                break;
            }
        }
        exit(EXIT_SUCCESS);
    }

    // 父进程
    // 4、从消息队列读取信息
    struct msgbuf buf;
    while (1)
    {
        msgrcv(msqid, &buf, SIZE, 1, 0);
        printf("进程2父程序收到信息:%s\n", buf.mtext);

        if (strcmp(buf.mtext, "quit") == 0)
        {
            break;
        }
    }

    // 回收子程序资源
    wait(NULL);
    // 删除消息队列
    if (msgctl(msqid, IPC_RMID, NULL) == -1)
    {
        perror("msgctl error");
        return -1;
    }
    return 0;
}

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

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

相关文章

吴恩达机器学习COURSE1 WEEK2

COURSE1 WEEK2 多维特征 在线性回归中&#xff0c;往往特征不止一个&#xff0c;而是具有多维特征 例如&#xff0c;在预测房价的例子中&#xff0c;我们知道更多的信息&#xff1a; x 1 x_1 x1​&#xff1a;房屋的面积 x 2 x_2 x2​&#xff1a;卧室的数目 x 3 x_3 x3​&a…

【嵌入式】常用英文缩写及单词整理

目录 嵌入式常用英文缩写及单词整理1. 缩写部分2. 词汇部分3. 语句部分4. 调试部分5. 结束语相关文章&#xff1a; 嵌入式常用英文缩写及单词整理 1. 缩写部分 缩写全称翻译AADCAnalog-to-Digital Converter模/数转换器&#xff0c;模数转换器ADUApplication data unit应用数…

KBEngine ue5

前言 最近在试 KBEngine 的 ue4 项目&#xff0c;它在 ue4 下能够正常编译使用&#xff0c;但是现在都已经进入 ue5 时代&#xff0c;那么能不能将现有工程移到 ue5 下呢&#xff1f; 使用 ue5 打开工程的报错处理 1、DefaultBuildSettings BuildSettingsVersion.V5; kbeng…

python.tkinter设计标记语言(渲染2-渲染器)

TOC 前言 本文仅作为笔记记录。 在前文中&#xff0c;我们通过标记意义解释生成了带有明确渲染要求的参数组&#xff0c;以<title>为例&#xff0c;我们获取了title, level两个明确的渲染标记&#xff0c;这一部分由Tin标记解释器完成&#xff0c;不需要编写者花费过多…

亚马逊、eBay、沃尔玛等海外跨境电商测评自养号的技术解决方案

随着跨境电商的蓬勃发展&#xff0c;卖家们对于提升店铺流量、销量以及产品评价的需求日益迫切。在这一背景下&#xff0c;海外跨境电商测评成为了一个备受瞩目的领域。作为一家专注于此领域的技术型公司&#xff0c;凭借其深厚的技术积累和丰富的实战经验&#xff0c;为卖家们…

supermap制作发布二三维地图服务

一、下载安装 软件版本&#xff1a; SuperMap iDesktopX 11i(2023) SP1 for Windows SuperMap iServer 11i(2023) SP1 for Windows 下载地址&#xff1a; http://support.supermap.com.cn/DownloadCenter/ProductPlatform.aspx 二、运行 服务端&#xff1a;双击iserver的…

HTML学习笔记——用HTML记录学习过程4——非主体结构元素

非主体结构元素主要是为了表达逻辑结构或者附加信息的元素 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>非主体结构元素</title> </head> <body> <header><h1>head…

大模型落地应用架构的一种模式

经过几个月的实践和探索&#xff0c;看过也经历过一些成型的项目了&#xff0c;如果是奔着落地去的&#xff0c;我们的目光不能只盯着大模型本身&#xff0c;而应该放眼甚至是需要投入精力去建设很多我们别的工作上。 本文&#xff0c;着重讲的是&#xff0c;我的理解下现实成…

「实战应用」着色器对图表控件LightningChart的影响及应用

LightningChart完全由GPU加速&#xff0c;并且性能经过优化&#xff0c;可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D&#xff0c;高级3D&#xff0c;Polar&#xff0c;Smith&#xff0c;3D饼/甜甜圈&#xff0c;地理地图和GIS图表以及适用于科学&am…

PySide入门实战之五 | 信号与槽函数之鼠标、键盘等事件

&#x1f680;&#x1f680;&#x1f680; Pyside6实战教程专栏目录入口&#xff1a;点击跳转 目录 一、前期准备二、鼠标触发事件鼠标拖动窗口 一、前期准备 我们采用Pyside入门实战之四中通过QTDesigner创建的界面&#xff0c;具体由两个Label和一个Button组件构成&#xff…

【图书推荐】《数据资产管理核心技术与应用》

内容简介 《数据资产管理核心技术与应用》深入探讨数据资产管理的核心技术与应用&#xff0c;融入作者在大数据领域多年的丰富经验。《数据资产管理核心技术与应用》为读者提供一套可以落地的数据资产管理框架&#xff0c;并详解两个基于该框架进行数据资产管理的应用案例&…

[米联客-安路飞龙DR1-FPSOC] UDP通信篇连载-09 ICMP层程序设计

软件版本&#xff1a;Anlogic -TD5.9.1-DR1_ES1.1 操作系统&#xff1a;WIN10 64bit 硬件平台&#xff1a;适用安路(Anlogic)FPGA 实验平台&#xff1a;米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台&#xff1a;https://milianke.tmall.com/ 登录“米联客”FPGA社区 ht…

github技巧和bug解决方法短篇收集

有一些几句话就可以说明白的观点或者解决的的问题&#xff0c;小虎单独收集到这里。 Commits没有算入每天的activity fork的仓库是不算的。 Commits made in a fork will not count toward your contributions. 参考&#xff1a; Contribution activity not shown for github…

win7一键修复所有dll缺失详细方法,7个dll修复方法深度解析(2024)

dll文件是一种包含函数和其他关键信息的文件&#xff0c;供 Windows 应用程序使用。虽然大多数普通用户对.dll 文件的具体工作原理并不熟悉&#xff0c;但这些文件对于系统应用来说是至关重要的。通常情况下&#xff0c;人们在遇到因 DLL 文件缺失或损坏而导致的错误时&#xf…

Vue3+Ts项目中经常遇到导入组件,vscode报无法找到模块xxx,xxx隐式拥有 “any“ 类型解决办法~

1、报错截图&#xff1a; 2、解决办法&#xff1a;在确保路径正确的情况下&#xff0c;你会在 src 目录下找到一个名为 env.d.ts 的文件&#xff08;或者类似的名称&#xff09;。在这个文件中&#xff0c;你可以声明 .vue 文件的模块类型。例如&#xff1a;(这告诉 TypeScript…

探索Cohere的Prompt Tuner:革新你的提示优化工具

在今天的文章中&#xff0c;我们将深入探讨Cohere的Prompt Tuner。这是一款在你指尖的提示优化工具&#xff0c;至少这是他们所宣称的。Prompt Tuner的主要理念是&#xff0c;它提供了一种最简化、最标准化的方式来生成你所需要的提示。而最棒的部分是&#xff0c;你不需要成为…

vtkConnectivityFilter提取连通区域中的问题

直接使用vtkConnectivityFilter提取连通区域&#xff0c;渲染上没问题&#xff0c;但是打印出polydata中的点数&#xff0c;发现跟原始数据是一致的。 for (int i 0; i < numRegions; i){vtkSmartPointer<vtkConnectivityFilter> connectivityFilter vtkSmartPointe…

嵌入式人工智能(树莓派4B基础实验代码等)

本专栏收录了近40个实验,含全部实验代码,都已经打包。 1、简介 本实验平台为树莓派4B,处理器4核ARMV8架构-A72,内存8G版本,SD卡容量为64G。操作系统版本lsb_release -a 操作系统内核为uname -a 本专栏收录了树莓派系统的基本知识,环境基本配置,常用Linux系统操作、基…

Ecovadis丨Ecovadis认证丨Ecovadis评估

EcoVadis 是以下这样的一个存在和具有以下这些特点等&#xff1a; 背景方面&#xff1a; 它源自法国 &#xff0c;前身由“携手实现可持续发展 - 全球化学联盟&#xff08;TFS - CI&#xff09;”、“联合国全球契约组织&#xff08;UN Global Compact&#xff09;”、IPE公众…

<数据集>腐烂水果识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;3304张 标注数量(xml文件个数)&#xff1a;3304 标注数量(txt文件个数)&#xff1a;3304 标注类别数&#xff1a;6 标注类别名称&#xff1a;[good apple, bad apple, good orange, bad orange, good banana, bad …