C语言-Linux进程间通信方式

1、进程间通信方式概述

进程间通信方式有:
    管道(Pipo)和有名管道(FIFO):用于具有亲缘关系进行间通信,有名管道,允许无亲缘关系进程间的通信
    信号(Signal):比较复杂的通信方式,用于通知接收进程有某种事件发生
    消息队列:消息的连接表,包括Posix消息队列和System V消息队列
    信号量(Signal)/信号灯:主要被用作进程间或同一进程不同线程之间的同步手段
    共享内存:最有用的进程间通信方式,需要某种同步机制,互斥锁和信号量都可以
    套接字:用于不同机器之间的进程间通信

进程间通信的目的
    数据传输、共享数据、通知事件、资源共享、进程控制

2、管道通信

特点:
    半双工,数据只能一个方向流动,进行双方通信的时候要建立两个管道,用于父子间或兄弟进程间通信
    一个进程向管道中写的数据内容被管道另一端的进程读出
    写入的数据每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据
    一般的I/O函数都可以用于管道,如close、read、write等

读数据步骤:
    若写端不存在,则认为以及读到了数据的末尾,读函数返回读出的字节数为0
    若管道的写端存在,请求的字节数目大于PIPE_BUE(定义在include/linux/limits中),返回现有字节数,不大于的话,返回现有字节数或请求字节数
    在管道写端关闭后,写入的数据将一直存在,直到被读出为止

写端对读端的依赖性:
    在向进程中写入数据时,至少应该存在某一个进程,其中管道读端没有被关闭。否则就会出现管道断裂,进程收到SIGPIPE信号,默认动作为进程终止

2.1 创建无名管道

函数详解 

表头文件#include <unistd.h>定义函数int pipe(int filedes[2]);函数说明用于建立管道将文件描述符由参数filedes数组返回filedes[0] 为管道的读取端filedes[1] 为管道的写入端返回值成功返回零,否则返回-1

综合案例 

#include <stdio.h>
#include <unistd.h>int main(int argc,char *argv[])
{int filedes[2];char buffer[80];pipe(filedes);if(fork() > 0){char s[] = "hello!\n";write(filedes[1],s,sizeof(s));}else{read(filedes[0],buffer,80);printf("father %s",buffer);}return 0;
}

运行结果

linux@ubuntu:~/test$ gcc pipe_dome.c -o pipe_dome
linux@ubuntu:~/test$ ./pipe_dome 
father hello!

2.2 创建有名管道

函数详解  

表头文件#include <sys/types.h>#include <sys/stat.h>定义函数int mkfifo(const char* pathname,mode_t mode);函数说明pathname: 建立特殊的FIFO文件,该文件必须不存在mode: 描述pahtname文件的权限当使用open()打开文件时,O_NONBLOCK旗标会有下列影响:当使用O_NONBLOCK旗标时,打开文件来读取操作会立刻返回;若没有其他进程打开文件来读取,则写入操作会返回ENXIO错误没有使用O_NONBLOCK旗标时,打开FIFO文件读取操作会等到其他进程打开FIFO文件进行写入才能正常返回。同样,打开FIFO文件进行写入操作会等其他进程打开FIFO文件进程读取后才能正常返回

 综合案例 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FIFO "/home/linux/test/2"int main(int argc,char *argv[])
{char buffer[80];int fd;unlink(FIFO);                 //unlink删除指定的文件,若文件存在则删除它,确保后边mkfifo建立的特殊文件不存在mkfifo(FIFO,0666);if(fork() > 0){char s[] = "hello!\n";fd = open(FIFO,O_WRONLY);write(fd,s,sizeof(s));close(fd);}else{fd = open(FIFO,O_RDONLY);read(fd,buffer,80);printf("%s",buffer);close(fd);}return 0;
}

 运行结果

linux@ubuntu:~/test$ gcc mkfifo.c -o mkfifo
linux@ubuntu:~/test$ ./mkfifo
hello!

3、信号

信号的本质:
    在软件层次上对中断机制的一种模拟。异步的

信号来源:
    硬件来源:按下了键盘或者其他硬件故障
    软件来源:发送信号的系统函数:kill、raise、alarm、setitimer、非法运算操作

分类:
    性能:
        可靠:克服了信号可能丢失问题,这些信号支持排队
        不可靠:从UNIX继承过来的信号,进程每次处理信号后,就将对信号的相应设置为默认动作,有时候会错误处理,或信号丢失
    时间:
        实时:支持排队,都是可靠信号
        非实时:不支持排队,是不可靠信号

信号的处理方式:
    忽略信号:即对信号不做任何处理,SIGKILL和SIGSTOP不能忽略
    捕捉信号:定义信号处理函数,当信号发生时,执行相应的处理函数
    执行默认操作:进程对实时信号的默认操作反应是进程终止

信号发送的主要函数有:
    kill、raise、sigqueue、alarm、setitimer、abort

3.1 信号发送函数kill和alarm

函数详解   

表头文件#include <sys/types.h>#include <signal.h>定义函数int kill(pid_t pid,int sig);函数说明用于发送信号给指定进程pid: 指定的进程pid>0:将信号传递给指定的pid进程pid=0:将信号传给目前进程相同的进程组的所有进程pid=-1:将信号广播传送给系统内所有的进程pid<0:将信号传给进程组识别码为pid绝对值的所有进程sig:指定要传送的信号返回值执行成功将返回0,如果有错误则返回-1

 综合案例  

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>int main(int argc,char *argv[])
{pid_t pid;int status;pid = fork();if(pid == 0){printf("I an child process!\n");sleep(10);}else{printf("send signal to child process (%d)\n",pid);sleep(1);kill(pid,SIGABRT);                    //向子进程中发送信号6wait(&status);                        //等待子进程中断或结束,将结束信号返回if(WIFSIGNALED(status))               //判断子进程是否因信号而结束printf("child process receive signal %d\n",WTERMSIG(status));   //获取子进程因信号而中止的信号代码}return 0;
}

  运行结果

linux@ubuntu:~/test$ gcc kill_dome.c -o kill_dome
linux@ubuntu:~/test$ ./kill_dome 
send signal to child process (25564)
I an child process!
child process receive signal 6

 函数详解   

表头文件#include <unistd.h>定义函数unsigned int alarm(unsigned int seconds);函数说明用来设置信号传送闹钟设置信号SIGALRM,在经过seconds指定的秒数后传送给目前的进程若参数为0,则之前设置的闹钟会被取消,剩下的时间返回返回值返回之前闹钟剩余的秒数,如果之前未设置闹钟则返回0

 综合案例   

#include <stdio.h>
#include <unistd.h>
#include <signal.h>void handler()
{printf("hello\n");
}int main(int argc,char *argv[])
{int i;signal(SIGALRM,handler);alarm(5);for(i = 1;i < 7;i++){printf("sleep %d ..\n",i);sleep(1);}return 0;
}

 运行结果

linux@ubuntu:~/test$ gcc ararm_dome.c -o alarm_dome
linux@ubuntu:~/test$ ./alarm_dome
sleep 1 ..
sleep 2 ..
sleep 3 ..
sleep 4 ..
sleep 5 ..
hello
sleep 6 ..

3.2 自定义信号处理方式

3.2.1 signal函数

  函数详解   

表头文件#include <signal.h>
​
定义函数void (*signal(int signum,void(*handler)(int)))(int);
​
函数说明用于传送信号给指定的进程signum: 指定信号编号来设置该信号的处理函数void(*handler)(int): 信号处理函数如果参数handler不是函数指针,则必是下列两个常数之一SIG_IGN:忽略参数signum指定信号SIG_DFL:将参数signum指定的信号重设为核心预设的信号处理方式
​
返回值返回先去的信号处理函数指针,若错误则返回-1注意:信号跳转到自定的handler处理函数后,系统会自动将此函数换回原来系统预设的处理方式,若要改变此操作,采用sigaction

  综合案例   

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>void my_func(int sign_no)
{if(sign_no == SIGINT)printf("I have get SIGINT\n");else if(sign_no == SIGQUIT)printf("I have get SIGQUIT\n");
}int main(int argc,char *argv[])
{printf("Waiting for signal SIGINT or SIGQUIT\n");/*注册信号处理函数*/signal(SIGINT,my_func);signal(SIGQUIT,my_func);pause();   //暂停主进程,直到收到信号exit(0);return 0;
}

 运行结果

linux@ubuntu:~/test$ ./signal_dome 
Waiting for signal SIGINT or SIGQUIT
I have get SIGQUIT//新开窗口
linux@ubuntu:~$ ps -aux|grep signal_dome
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
linux    25920  0.1  0.5  15872  5560 pts/2    S+   19:02   0:01 vi signal_dome.c
linux    25992  0.0  0.0   1988   280 pts/3    T    19:15   0:00 ./signal_dome
linux    26000  0.0  0.0   1988   284 pts/3    S+   19:16   0:00 ./signal_dome
linux    26064  0.0  0.0   6044   836 pts/5    T    19:16   0:00 grep --color=auto -l signal_dome
linux    26071  0.0  0.0   6044   836 pts/5    S+   19:17   0:00 grep --color=auto signal_dome
linux@ubuntu:~$ kill -SIGQUIT 26000                            //向暂停的进程发送信号

3.2.2 sigaction函数

表头文件#include <signal>定义函数int sigaction(int signum,const struct sigaction *act,struct sigaction * oldact);函数说明用于查询或设置信号处理方式signum:指定信号编号来处理函数sigaction定义如下:struct sigaction{void (*sa_handler)(int);  //新处理函数,同signal函数的参数handlersigset_t sa_mask;         //处理该信号时暂时将sa_mask信号搁置int sa_flags;             //用来处理信号的其他相关操作//A_NOCLDSTOP:如果参数signum为SIGCHLD,则当子进程暂停时并不会通知父进程//SA_ONESHOT/SA_RESETHAND:在调用新的信号处理函数前,将此信号处理方式改为系统预设的方式//SA_RESTART:被信号中断的系统调用会自行重启//SA_NOMASK/SA_NODEFER:在处理此信号未结束前不理会此信号的再次到来void (*sa_restorer)(void);   //已过时,POSIX不支持它}若参数oldact不是NULL指针,则原来的信号处理方式会由结构sigaction返回返回值成功返回0,错误返回-1

3.3 信号集操作

信号集被定义为一种数据类型:
typedef struct
{unsigned long sig[_NSIG_WORDS];
}sigset_t

3.3.1 sigemptyset函数

表头文件#include <signal.h>定义函数int sigemptyset(sigset_t *set);函数说明用于初始化信号集将参数set初始化,并清空返回值执行成功返回0,错误返回-1

3.3.2 sigfillset函数

表头文件#include <signal.h>
​
定义函数int sigfillset(sigset_t *set);
​
函数说明用于将所有信号加入信号集将参数set初始化,然后把所有信号加入此信号集里返回值成功返回0.错误返回-1

3.3.3 sigaddset()函数

表头文件#include <signal.h>
​
定义函数int sigaddset(sigset_t *set,int signum);
​
函数说明增加一个信号到信号集用来将参数signum代表的信号加入至set中
​
返回值成功返回0.错误返回-1

3.3.4 sigdelset函数

表头文件#include <signal.h>
​
定义函数int sigdelset(sigset_t *set,int signum);
​
函数说明用于从信号集中删除一个信号用来将参数signum代表的信号从参数set中删除
​
返回值成功返回0.错误返回-1

3.3.5 sigismember函数

表头文件#include <signal.h>
​
定义函数int sigismember(const sigset_t *set,int signum);
​
函数说明测试某个信号是否已加入信号集内用来测试参数signum代表的信号是否加入参数set中
​
返回值成功返回0.错误返回-1

4、消息队列

概念
    消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式和特定的优先级。对消息队列有写权限的进程可以按照一定的规则添加新消息,对于消息队列有读权限的进程则可以从消息队列中读走消息,消息队列是随内核持续的

类型
    POSIX消息队列和系统V消息队列,考虑程序的移植性,尽量用POSIX消息队列

基础理论
    系统V消息队列是随内核持续的,只有在内核重启或者显示删除一个消息队列时,该消息队列才会真正被删除
    系统中记录消息队列的数据结构(struct ipc_ids msg_ids)位于内核中  消息队列可以在msg_ids中找到访问入口
    每个消息都有一个队列头,用struct msg_queue来描述

对消息队列的操作
    打开或创建消息队列:要获得消息队列描述词,需提供消息队列的键值
    读写消息队列:每个消息都有类似如下的数据结构
        struct msgbuf
        {
            long mtype;        //消息类型
            char mtext[1];     //消息内容,长度不一定为1
        }
        故对于发送消息来说,需要预置一个msgbuf缓冲区并写入消息内容,读同样
    获取或设置消息队列属性

4.1 ftok函数

表头文件#include <sys/types.h>#include <sys/ipc.h>定义函数key_t ftok(char* pathname,char proj);
​
函数说明用于将文件名转化成键值pathname:相应的一个文件,必须存在,且在程序的访问范围内char:任意一个字符
​
返回值返回与文件对应的键值

4.2 msgget函数

表头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>
​
定义函数int msgget(key_t key,int msgflg);
​
函数说明用于创建一个消息队列key:一个键值msgflg:标志位IPC_CREAT、IPC_EXCL、IPC_NOWAIT若没有消息队列与键值key对应,且msgflg包含IPC_CREAT标志位或参数key位IPC_PRIVATE则将创建一个新的消息队列
​
返回值成功返回队列描述词,否则返回-1

4.3 msgrcv函数

表头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>
​
定义函数int msgrcv(int msqid,struct msgbuf *msgp,int msgsz,long msgtyp,int msgflg);
​
函数说明用于读出消息队列的数据msqid:消息队列描述词*msgp:将消息存在msgp所指向的msgbuf结构中msgsz:指定msgbuf的mtext的长度msgtyp:请求读取的消息类型msgflg:控制消息队列中没有相应类型的消息可以接收时将发生的事情IPC_NOWAIT:没有返回条件的消息,调用立即返回ENOMSG
​
返回值成功则返回读出消息的实际字节数,否则返回-1

4.4 msgsnd函数

表头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>
​
定义函数int msgsnd(int msqid,struct msgbuf *msgp,int msgsz,int msgflg);
​
函数说明用于向消息队列中写入数据msqid:消息队列描述词*msgp:将存在msgp所指向的msgbuf结构中的消息进行发送msgsz:消息的大小msgflg:有意义的msgflg标志为IPC_NOWAIT,表明消息队列没有足够的空间容纳要发送的消息时,msgsnd是否等待
​
返回值成功返回0,否则返回-1

4.5 msgctl函数

表头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>
​
定义函数int msgctl(int msqid,int cmd,struct msqid_ds *buf);
​
函数说明用于控制消息队列msqid:消息队列描述词cmd:IPC_STAT:获取消息队列信息,返回的信息存储在buf指向的msqid结构中IPC_SET:设置消息队列的属性,设置的属性存储在buf指向的msqid结构中IPC_RMID:删除msqid标识的消息队列
​
返回值成功返回0,否则返回-1

5、信号灯(了解)

作用:
    提供对进程间共享资源的访问控制机制,相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源

类型:
    二值信号灯:最简单的信号灯形式,信号灯的值只能取0或1,类似于互斥锁
    计算信号灯:信号灯的值可以取任意非负值

内核实现原理:
    系统V信号灯也是随内核持续的。在内核中由数据结构struct ipc_ids sem_ids记录,所有信号灯都可以在结构sem_ids中找到访问入口

信号灯的使用
    打开或创建信号灯:与消息队列的创建及打开相同
    信号灯值操作:linux可以加减信号灯的值,相当于对共享资源的释放和占有
    获得或设置信号灯属性:系统中的每一个信号灯集都对应一个struct sem_array结构,该结构记录了信号灯集的各种信息,存在于系统空间。为了设置、获得该信号灯集的各种信息和属性,在用户空间有一个重要的联合结构与之对应,即union semun

5.1 semget函数

表头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>
​
定义函数int semget(key_t key,int nsems,int semflg);
​
函数说明配置信号灯key:是一个键值,由ftok获得,标识唯一一个信号灯集,用法与msgget中的key相同nsems:指定打开或者新创建的信号灯集中包含的信号灯的数目semflg:标志位,与msgget相同返回值成功返回信号灯集描述词,否则返回-1

5.2 semop函数

表头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>
​
定义函数int semop(int semid,struct sembuf *sops,unsigned nsops);
​
函数说明用于信号灯处理semid:信号集IDsops:指向数组的每一个sembuf结构都描述一个特定信号灯上的操作nsops:sops数组的大小sembuf的结构为:struct sembuf{unsigned short sem_num;     //对应集中的信号灯,0对应第一个信号灯short          sem_op;      //大于0,等于0,小于0确定了对sem_num指定的信号灯进行的3种操作short          sem_flg;     //IPC_NOWAIT和SEM_UNDO两个标志}
​
返回值成功返回0,否则返回-1

5.3 semctl函数

表头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>
​
定义函数int semctl(int semid,int semnum,int cmd,union semun arg);
​
函数说明用于控制信号灯semid:指定信号灯集cmd:具体的操作类型IPC_STAT:获取信号灯信息,由arg.buf返回IPC_SET:设置信号灯信息,设置信息保存在arg.buf中CETALL:返回所有信号灯信息,结果保存在arg.array中CETNCNT:返回等待semnum所代表信号灯的值增加的进程数GETPID:返回最后一个对semnum所代表信号灯执行semop操作的进程IDGETVAL:返回semnum所代表信号灯的值GETZCNT:返回等待semnum所代表信号灯的值变成0的进程数SETALL:设置semnum所代表信号灯的值为arg.val

6、共享内存方式

概念
    共享内存是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A,B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间,A和B都能看到对方内存中数据的更新,由于共用一块内存,必然需要某种同步机制,互斥锁和信号量都可以

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

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

相关文章

Angular基础学习(入门 --> 入坑)

目录 一、Angular 环境搭建 二、创建Angular新项目 三、数据绑定 四、ngFor循环、ngIf、ngSwitch、[ngClass]、[ngStyle]、管道、事件、双向数据绑定--MVVM 五、DOM 操作 &#xff08;ViewChild&#xff09; 六、组件通讯 七、生命周期 八、Rxjs 异步数据流 九、Http …

51单片机的光照强度检测【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块光照传感器按键蜂鸣器LED等模块构成。适用于光照强度检测、光照强度测量报警等相似项目。 可实现功能: 1、LCD1602实时显示光照强度信息 2、光照强度传感器&#xff08;电位器模拟&#xff09;采集光照信息 3、可…

X86架构(九)——保护模式的进入

全局描述符表 全局描述符表(Global Descriptor Table,GDT)是保护模式下非常重要的一个数据结构。 在保护模式下&#xff0c;对内存的访问仍然使用段地址和偏移地址&#xff0c;在每个段能够访问之前&#xff0c;必须先行设置好 GDT 的地址&#xff0c;并加载全局描述符表寄存…

emp.dll丢失怎么解决,快来试试这个几个解决方法

在日常使用电脑玩游戏的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中最常见的就是“emp.dll丢失”。那么&#xff0c;emp.dll到底是什么&#xff1f;它为什么会丢失&#xff1f;丢失后会对我们的电脑产生什么影响&#xff1f;本文将为您详细解析emp.dll的概念…

[BUUCTF从零单排] Web方向 03.Web入门篇之sql注入-1(手工注入详解)

这是作者新开的一个专栏《BUUCTF从零单排》&#xff0c;旨在从零学习CTF知识&#xff0c;方便更多初学者了解各种类型的安全题目&#xff0c;后续分享一定程度会对不同类型的题目进行总结&#xff0c;并结合CTF书籍和真实案例实践&#xff0c;希望对您有所帮助。当然&#xff0…

打造高业绩朋友圈:策略与实践

在数字化时代&#xff0c;朋友圈不仅是个人生活的展示窗口&#xff0c;更是商业变现的有力平台。许多人通过精心经营朋友圈&#xff0c;实现了财富的增长&#xff0c;甚至达到了年入百万的惊人业绩。朋友圈已成为普通人实现逆袭的重要战场。 要打造一个业绩过万的朋友圈&#…

关于武汉芯景科技有限公司的IIC电平转换芯片XJ9509开发指南(兼容PCa9509)

一、芯片引脚介绍 1.芯片引脚 2.引脚描述 二、系统结构图 三、功能描述 1.VCCA1.35V,VCCB5V,A1输入&#xff0c;B1输出 2.VCCA1.35V,VCCB5V,B1输入&#xff0c;A1输出 3.VCCA1.35V,VCCB5V,A2输入&#xff0c;B2输出 4.VCCA1.35V,VCCB5V,B2输入&#xff0c;A2输出

升级 Windows 后如何恢复丢失的文件

升级到 Windows 11 后可以恢复丢失的文件&#xff01;阅读帖子直到最后&#xff0c;了解如何做到这一点。 为了获得安全更新并使用最新的操作系统&#xff0c;人们会升级到最新版本的 Windows。然而&#xff0c;在这样做的过程中&#xff0c;许多人丢失了他们的重要文件&#…

基于SpringBoot+Vue+MySQL的体育商城系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着互联网的飞速发展&#xff0c;电子商务已成为人们日常生活中不可或缺的一部分。体育用品市场作为其中的一个重要分支&#xff0c;也逐渐向线上转移。基于SpringBootVueMySQL的体育商城系统应运而生&#xff0c;旨在通过构建…

优秀的拆分C++

题目&#xff1a; 样例解释&#xff1a; 样例1解释 6422221 是一个优秀的拆分。注意&#xff0c;6222 不是一个优秀的拆分&#xff0c;因为拆分成的 3 个数不满足每个数互不相同。 思路&#xff1a; 题目大致意思是说给定一个正整数NN&#xff0c;让你用二进制表示&#xff08;…

PDCA优化任务流程

这里写目录标题 一、背景二、PDCA重要性与必要性概念PDCA循环的重要性 三、PDCA分析这次任务的执行任务描述分析原因&#xff1a;结合PDCA分析&#xff1a;提高办法&#xff1a; 四、总结 一、背景 汇报任务完成情况&#xff0c;未提交实际成果。 本次总结旨在通过PDCA循环的视…

鸿蒙开发(NEXT/API 12)【硬件(振动开发1)】振动

通过最大化开放马达器件能力&#xff0c;振动器模块服务拓展了原生马达服务&#xff0c;实现了振动与交互融合设计&#xff0c;从而打造出细腻精致的一体化振动体验和差异化体验&#xff0c;提升用户交互效率、易用性以及用户体验&#xff0c;并增强品牌竞争力。 运作机制 Vi…

学习docker第二弹------基本命令[帮助启动类命令、镜像命令、容器命令]

docker目录 前言基本命令帮助启动类命令停止docker服务查看docker状态启动docker重启docker开机启动docker查看概要信息查看总体帮助文档查看命令帮助文档 镜像命令查看所有的镜像 -a查看镜像ID -q在仓库里面查找redis拉取镜像查看容器/镜像/数据卷所占内存删除一个镜像删除多个…

机器学习:opencv--背景建模

目录 一、背景建模是什么&#xff1f; 二、背景建模的目的 三、背景建模的方法及原理 四、代码实现 1.创建卷积核 2.创建混合高斯模型 3.处理图像 4.绘制人形轮廓 5.条件退出 一、背景建模是什么&#xff1f; 指在计算机视觉中&#xff0c;从视频序列中提取出静态背景…

Anaconda虚拟环境默认路径在C盘怎么更改

笔者已经新建好了虚拟环境并且安装了对应库&#xff0c;输入conda env list查询发现虚拟环境竟然安装到了C盘(&#xff61;•́︿•̀&#xff61;)&#xff0c;为避免下一次创建虚拟环境出错&#xff0c;笔者现在修改默认路径置D盘&#xff08;软件安装盘&#xff09; 参考两…

ROS学习笔记(四):使用 `ros2 run usb_cam usb_cam_node_exe` 启动 USB 摄像头

文章目录 前言1 安装 usb_cam 包2 启动 USB 摄像头3 订阅相机发布的节点信息并进行可视化3.1 使用 rqt_image_view3.2 使用 image_view3.3 使用 rviz 4 常见问题与解决方案4.1 摄像头未被识别4.2 相机显示异常4.3 如何指定不同的相机4.4 摄像头参数调整 5. 调试信息 5. 结论 前…

pyboard405意外故障,micropython OLED例程无法运行,折腾了大半天。

thonny报告&#xff1a; Traceback (most recent call last): File "<stdin>", line 3, in <module> RuntimeError: name too mode # main.py -- put your code here! from machine import I2C,Pin #从machine模块导入I2C、Pin子模块 from ss…

SpringBoot项目请求不中断动态更新代码

在开发中&#xff0c;有时候不停机动态更新代码热部署是一项至关重要的功能&#xff0c;它可以在请求不中断的情况下下更新代码。这种方式不仅提高了开发效率&#xff0c;还能加速测试和调试过程。本文将详细介绍如何在 Spring Boot 项目在Linux系统中实现热部署&#xff0c;特…

MySQL - 运维篇

一、日志 1. 错误日志 2. 二进制日志 3. 查询日志 记录了所有的增删改查语句以及DDL语句 4. 慢查询日志 二、主从复制 1. 概述 2. 原理 3. 搭建 三、分库分表 1. 介绍 2. Mycat概述 3. Mycat入门 4. Mycat配置 5. Mycat分片 6. Mycat管理及监控 四、读写分离 1. 介绍 2. 一…

PostgreSQL的安装与使用指南

PostgreSQL,简称Postgres,是一个功能强大的开源对象-关系数据库系统。它以其稳定性、可靠性、数据完整性以及对SQL标准的严格遵循而著称,广泛应用于各种规模的企业级应用、Web应用和数据仓库中。本文将详细介绍PostgreSQL在不同操作系统上的安装、配置及基本使用方法。 一、…