Linux高级进程通信

目录

第1关:socket之本地通信

任务描述

相关知识

创建 socket 流程

命名 socket

其他接口

编程要求

答案:

第2关:命名管道

任务描述

相关知识

命名管道的定义

命名管道的创建

命名管道的访问

命名管道的访问

编程要求

答案:

第3关:消息队列

任务描述

相关知识

消息队列的基本概念

消息队列的创建

发送消息

接收消息

控制函数

编程要求

答案 :


第1关:socket之本地通信

任务描述

试想这样的场景:

你有事情要告知同一个科室的同事 A ,但是你没有同事 A 的微信,你需要找同一个科室的同事 B 获取同事 A 的微信,然后给同事 A 发消息。

整个事件的过程如下:

你向同事 B 询问同事 A 的微信号;

同事 B 得到同事 A 的允许后将同事 A 的微信号告诉你;

你添加同事 A 为微信好友;

同事 A 确认并通过好友认证。

以本地 socket 通信代替整个事件的过程:创建 socket->链接socket->向对端发送消息->接收对端发过来的消息。

本关任务:

建立一个命名 socket,指定地址为本地 socket 文件;

连接 socket 成功后,发送消息到服务端;

接收从服务端来的消息。

相关知识

在 Linux 中,套接字 socket 通信是非常常见的通信方式。通信过程中采用三次握手,四次挥手的通信流程。

通常套接字 socket 通信是运用在网络上两台主机上,通信双方采用网络地址和端口号作为通信地址来进行通信。服务端绑定此地址,然后开始监听此地址;客户端连接此地址即可。

在本地通信中,socket 进程通信与网络通信使用的是统一套接口,只是地址结构与某些参数不同。Socket 通信在另外的实训中已有介绍,对此不太熟悉的学员可以自行查阅下。

创建 socket 流程

创建 socket 采用系统调用 socket ,原型如下:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int socket(int domain, int type, int protocol);

参数详解如下:

domain:参数指定协议族,对于本地套接字来说,其值须被置为 AF_UNIX ;

type:参数指定套接字类型,可被设置为 SOCK_STREAM (流式套接字)或 SOCK_DGRAM (数据报式套接字);对于本地套接字来说, SOCK_STREAM 是一个有顺序的、可靠的双向字节流,相当于在本地进程之间建立起一条数据通道; SOCK_DGRAM 相当于单纯的发送消息,在进程通信过程中,理论上可能会有信息丢失、复制或者不按先后次序到达的情况,但由于其在本地通信,不通过外界网络,这些情况出现的概率很小。

protocol :参数指定具体协议,protocol 字段应被设置为 0 。

返回值为生成的套接字描述符。

命名 socket

本地套接字的通信双方均需要具有本地地址,其中本地地址需要明确指定,指定方法是使用struct sockaddr_un类型的变量。

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
struct sockaddr_un {
    sa_family_t     sun_family;     /* AF_UNIX */
    char    sun_path[UNIX_PATH_MAX];        /* 路径名 */
};

socket 根据此命名创建一个同名的 socket 文件,客户端连接的时候通过读取该 socket 文件连接到 socket 服务端。

应用示例如下:
 

//name the server socket   
server_addr.sun_family = AF_UNIX;  
strcpy(server_addr.sun_path,"/tmp/UNIX.domain");  
server_len = sizeof(struct sockaddr_un);  
client_len = server_len;  
其他接口

其他接口,比如服务端的listenaccept,客户端的connect等均没有区别。

编程要求

在本实训中,后台存在一个用于与客户端之间通信的服务端,学员需要实现的代码位于客户端。

本关的编程任务是完成客户端的代码编写,补全右侧代码片段localsocket_testBeginEnd中间的代码,具体要求如下:

首先建立一个命名 socket ,指定地址为./socket_test;

连接 socket 成功后,发送消息(发送内容为 localsocket_test 中的参数 buffer)到服务端;

接收从服务端来的消息。关闭 socket ;

如果接收成功返回 0,接受失败返回 -1。

答案:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

int localsocket_test(const char *buffer, char *recv_buff, int length)
{
	/*********begin***********/
    struct sockaddr_un server_addr;

    //创建socket
    int sockfd=socket(AF_UNIX,SOCK_STREAM,0);

    //设置服务器地址
    server_addr.sun_family=AF_UNIX;
    strncpy(server_addr.sun_path,"./socket_test",sizeof(server_addr.sun_path)-1);

    //连接socket
    connect(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));

    //发送消息到服务端
    write(sockfd,buffer,strlen(buffer));
    //send(sockfd,buffer,strlen(buffer),0);也可

    //接收从服务端发来的消息
    read(sockfd,recv_buff,length-1);
    //recv(sockfd,recv_buff,length-1,0);也可

    //关闭socket
    close(sockfd);

    return 0;
	
	/**********end************/
}

第2关:命名管道

任务描述

试想这样的场景:

你想请工程部来建筑一个别墅,但是你没有工程部的联系方式,恰好你的好友 Mike 与工程部非常熟,你打电话给你的好友,希望可以与工程部经理进行三方通话并传递别墅需求。

整个事件的过程如下:

你给好友打电话告知你的别墅需求;

好友让你等下,他把工程部经理加进来进行三方通话;

好友把工程部经理加入三方通话;

你把别墅需求直接告知工程部经理;

谈话结束,你挂断电话;

工程部经理也挂断电话。

以命名管道代替整个事件的过程,创建命名管道->打开命名管道->等待对端打开命名管道->发送消息->关闭命名管道。

本关任务:

检测命名管道文件是否存在,如若不存在则创建道;

以阻塞的方式打开命名管道;

通过命名管道发送消息;

关闭命名管道。

相关知识

在 Linux 中,命名管道是一种比较常见的进程间通信方式。相对于其他类型管道来说,命名管道弥补了通信的双方进程需要有共同祖先的弊端,这给我们在不相关的的进程之间交换数据带来了可能性。

命名管道的定义

命名管道也被称为FIFO文件,它是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为和其他管道类似。

由于 Linux 中所有的事物都可被视为文件,所以对命名管道的使用也就变得与文件操作非常的统一,使用也非常方便,同时我们也可以像平常的文件名一样在命令中使用。

命名管道的创建

创建命名管道的函数原型如下:

#include <sys/types.h>  
#include <sys/stat.h>  
int mkfifo(const char *filename, mode_t mode);  

参数详解如下:
 

filename:命名管道文件的路径,类似"/tmp/my. fifo ";

mode:命名管道文件的模式,表明执行此文件的权限,类似"0666"。
 

返回值:

若成功则返回 0,否则返回 -1,错误原因存于 errno 中。

命名管道的访问

mkfifo 函数只是创建一个 FIFO文件 ,要使用命名管道首先要将其打开,与打开其他文件一样, FIFO文件 也可以使用 open 调用来打开。

open 函数的相关知识这里就不做赘述了,但是这里要强调四点:

不能以 O_RDWR 模式打开 FIFO文件 进行读写操作,而其行为也未明确定义,因为如果以读/写方式打开一个管道,进程就会读回自己的输出,同时我们通常使用 FIFO 只是为了单向的数据传递

传递给 open 调用的是 FIFO 的路径名,而不是正常的文件。

当使用 O_NONBLOCK 时,打开 FIFO文件 来读取的操作会立刻返回,但是若还没有其他进程打开 FIFO文件 来读取,则写入的操作会返回 ENXIO 错误代码;

当没有使用 O_NONBLOCK 时,打开 FIFO 来读取的操作会等到其他进程打开 FIFO文件 来写入才正常返回。同样地,打开 FIFO文件 来写入的操作会等到其他进程打开 FIFO 文件 来读取后才正常返回。

核心代码如下:

参数详解如下:

filename:命名管道文件的路径,类似"/tmp/my. fifo ";

mode:命名管道文件的模式,表明执行此文件的权限,类似"0666"。

返回值:

若成功则返回 0,否则返回 -1,错误原因存于 errno 中。

命名管道的访问

mkfifo 函数只是创建一个 FIFO文件 ,要使用命名管道首先要将其打开,与打开其他文件一样, FIFO文件 也可以使用 open 调用来打开。

open 函数的相关知识这里就不做赘述了,但是这里要强调四点:

不能以 O_RDWR 模式打开 FIFO文件 进行读写操作,而其行为也未明确定义,因为如果以读/写方式打开一个管道,进程就会读回自己的输出,同时我们通常使用 FIFO 只是为了单向的数据传递

传递给 open 调用的是 FIFO 的路径名,而不是正常的文件。

当使用 O_NONBLOCK 时,打开 FIFO文件 来读取的操作会立刻返回,但是若还没有其他进程打开 FIFO文件 来读取,则写入的操作会返回 ENXIO 错误代码;

当没有使用 O_NONBLOCK 时,打开 FIFO 来读取的操作会等到其他进程打开 FIFO文件 来写入才正常返回。同样地,打开 FIFO文件 来写入的操作会等到其他进程打开 FIFO 文件 来读取后才正常返回。

核心代码如下:

/*客户端*/
...... 
int res = mkfifo(fifo_name, 0777);
char buffer[1024] = {0};
strncpy(buffer, "this is client.", strlen("this is client."));
if (res == 0)
{
    int pipe_fd = open(fifo_name, O_WRONLY);
int bytes_write= write(pipe_fd, buffer, bytes_read); 
if(0 < bytes_write)
{
printf("send message successful.
");
}
......
}
/*服务端*/
...... 
int res = mkfifo(fifo_name, 0777);
char buffer[1024] = {0};
if (res == 0)
{
    int pipe_fd = open(fifo_name, O_RDONLY);
int bytes_read = read(pipe_fd, buffer, PIPE_BUF);  
if(0 < bytes_read)
{
printf("receive: %s
", buffer);
}
......
}

测试步骤:

分别运行./server./client

运行结果:

send message successful.

receive : this is client.
编程要求

在本实训中,存在一个服务端用于与客户端之间的通信。

本关的编程任务是完成客户端的代码编写,补全右侧代码片段namepipe_commuBeginEnd中间的代码,具体要求如下:

检测命名管道文件./my_fifo是否存在,如若不存在则创建命名管道文件;

可读、阻塞的方式打开命名管道;

通过命名管道发送消息(namepipe_commu 的参数 buffer );

关闭命名管道。

答案:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <string.h>

void namepipe_commu(const char *buffer)
{
	/***********begin***********/
	const char *fifo_path="./my_fifo";//检测命名管道文件./my_fifo是否存在
    int fd=open(fifo_path,O_WRONLY);//以可读、阻塞的方式打开命名管道
    if (write(fd,buffer,strlen(buffer))==-1){//通过命名管道发送消息(namepipe_commu的参数buffer)
        close(fd);
        return;
    }
	/***********end***********/
}

第3关:消息队列

任务描述

试想这样的场景:

你辅助你学弟的专业学习,你把相关的书籍不定期的放在图书馆的 1-2-58 书架上,学弟每次学完一本后会去拿之后的书籍。

整个事件的过程如下:

你打开书架;

每隔一段时间,你放上一本书;

学弟打开书架;

每学完一本书后,学弟再取走一本书。

以消息队列代替整个事件的过程,创建消息队列>发送消息->对方取走消息->删除消息队列。

本关任务:

创建消息队列;

每隔 1s 发送一则消息,共发送三条,分别为"C", "Linux", "Makefile";

最后发送一条"End"消息;

等待 10s ,删除消息队列。

相关知识

在 Linux 中,每种通讯方式应用的主流场景不同,在异步处理或者不需要很高的实时性的场景下,比较频繁的是消息队列。

消息队列的基本概念

消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。

消息队列中的每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题

消息队列与命名管道一样,每个数据块都有一个最大长度的限制。在 Linux 系统中,使用宏 MSGMAX 和 MSGMNB 来限制一条消息的最大长度和一个队列的最大长度。

消息队列是链表队列,它通过内核提供一个struct msqid_ds *msgque[MSGMNI]向量维护内核的一个消息队列列表,因此 Linux 系统支持的最大消息队列数由 msgque 数组大小来决定,每一个 msqid_ds 表示一个消息队列,并通过msqid_ds.msg_first、msg_last 维护一个先进先出msg链表队列。

发送一个消息到该消息队列时,把发送的消息构造成一个 msg 结构对象,并添加到msqid_ds.msg_first、msg_last 维护的链表队列;当接收消息的时候也是从**msg链表队列尾部查找到一个 msg_type 匹配的 msg 节点,从链表队列中删除该 msg 节点,并修改** msqid_ds 结构对象的数据。

消息队列的创建

创建命名管道的函数原型如下:

参数详解如下:

key:消息队列关联的键,比如 1024;

msgflg:消息队列的建立标志和存取权限;使用 IPC_CREAT 时,如果内核中没有此队列,则创建队列;当 IPC_EXCL 和 IPC_CREAT 一起使用时,如果队列已经存在,则失败。

返回值:

成功执行时,返回消息队列标识值;失败返回 -1。

发送消息
#include <sys/msg.h>
int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);  

参数详解如下:

msgid:msgget 函数返回的消息队列标识符;

msg_ptr:一个指向准备发送消息的指针,但是消息的数据结构却有一定的要求,指针 msg_ptr 所指向的消息结构一定要是以一个长整型成员变量开始的结构体,接收函数将用这个成员来确定消息的类型;

struct my_message
{    
long int message_type;    
/* The data you wish to transfer*/    
}; 

msg_sz:msg_ptr 指向的消息的长度,注意是消息的长度,而不是整个结构体的长度,不包括长整型消息类型成员变量的长度

msgflg:用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情,一般设为 0。
返回值:

如果调用成功,消息数据的一分副本将被放到消息队列中,并返回 0,失败时返回 -1。

接收消息
#include <sys/msg.h>
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);   
参数详解如下: msgid,msg_ptr,msg_st 和 msgflg 的作用和函数 msgsnd 的一样。

msgtype:实现一种简单的接收优先级。如果 msgtype 为 0,就获取队列中的第一个消息。如果它的值大于 0,将获取具有相同消息类型的第一个信息。如果它小于 0,就获取类型等于或小于 msgtype 的绝对值的第一个消息;

返回值:

失败时返回 -1。

控制函数
#include <sys/msg.h>
int msgctl(int msgid, int command, struct msgid_ds *buf);  

参数详解如下:

msgid 的作用和函数 msgsnd 的一样。

command :将要采取的动作,一般使用 IPC_RMID ,用于删除消息队列;

buf :用于删除消息队列时,一般设为 NULL 。

返回值:

成功时返回 0,失败时返回 -1。

编程时使用的核心代码如下:

/*客户端*/
#include <sys/msg.h>
struct msg_st
{
    long int msg_type;
    char text[BUFSIZ];
};
int main(int argc, char *argv[])
{
    ......
struct msg_st data;
......
//创建消息队列
int msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
.......
data.msg_type = 6;//指定消息类型
strncpy(data.text, "this is client.", strlen("this is client."));
msgsnd(msgid, (void *)&data, MAX_TEXT, 0);
printf("send message successful.
");
......
}
/*服务端*/
#include <sys/msg.h>
struct msg_st
{
    long int msg_type;
    char text[BUFSIZ];
};
int main(int argc, char *argv[])
{
    ......
struct msg_st data;
......
//创建消息队列
int msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
......
msgtype = 6;//指定接收消息的类型
memset(&data, 0, sizeof(struct msg_st));
msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0);
printf("receive: %s
", data.text);
......
//删除消息队列
msgctl(msgid, IPC_RMID, NULL);
}

测试步骤:

分别运行./server./client

运行结果:
 

send message successful.
 
receive : this is client.

编程要求

在本实训中,存在一个服务端用于与客户端之间的通信。

本关的编程任务是完成发送方的代码编写,补全右侧代码片段mq_commuBeginEnd中间的代码,具体要求如下:

创建 key 为 0x1234 的消息队列;

每隔 1s 发送一则消息,共发送三条,分别为"C", "Linux", "Makefile",消息类型均为 66 ;

最后发送一条"End"消息;

等待 10s ,删除消息队列。

答案 :
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

struct msgbuf
{
    long mytype;
    char bookname[100];
};

void mq_commu (void)
{
	/*********Begin*********/
    //创建key为0x1234
	key_t key=0x1234;

    //创建消息队列
    int msgid=msgget(key,IPC_CREAT|0666);

    struct msgbuf message;
    message.mytype=66;

    //发送三条消息
    strcpy(message.bookname,"C");
    msgsnd(msgid,&message,sizeof(struct msgbuf)-sizeof(long),0);
    sleep(1);//等待一秒

    strcpy(message.bookname,"Linux"); 
    msgsnd(msgid,&message,sizeof(struct msgbuf)-sizeof(long),0);
    sleep(1);//等待一秒

    strcpy(message.bookname,"Makefile");
    msgsnd(msgid, &message,sizeof(struct msgbuf)-sizeof(long),0);
    sleep(1);//等待一秒
     
    //最后发送一条"End"消息
    strcpy(message.bookname,"End");
    msgsnd(msgid,&message,sizeof(struct msgbuf)-sizeof(long),0);
    
	/**********End**********/
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux进程状态与优先级

本篇详细的讲解了 Linux 中进程会出现的各种状态&#xff0c;以及出现这些状态的原因&#xff0c;其中进程的阻塞、挂起和运行就是进程状态的体现。接着科普了一下进程的切换&#xff0c;然后讲解了进程的优先级&#xff0c;以及如何调整进程的优先级。最后对进程的特点进行了总…

C语言自定义类型中结构体、结构体声明、结构体自引用、结构体变量的定义和初始化、结构体内存对齐,结构体传参,位段等的介绍

文章目录 前言一、结构体二、 结构体声明三、 特殊的声明----匿名结构体类型四、 结构体的自引用&#xff08;1&#xff09;数据结构&#xff08;2&#xff09;结构体的自引用 五、 结构体变量的定义和初始化六、 结构体内存对齐1. 结构体的对齐规则&#xff08;1&#xff09;结…

华为eNSP综合实验-网络地址转换

实验完成之后,在AR1的g0/0/1接口抓包,查看地址转换 实现私网pc访问公网pc 实验命令展示 SW1: vlan batch 12 #创建vlan interface e0/0/1 #进入接口配置vlan端口 port link-type access port default vlan 12 q interface e0/0/2 #进入接口配置vlan端口 port link-type ac…

iphone忘记锁屏密码怎么解锁?这些解锁方法你必须知道!

在使用iPhone的过程中经常会遇到很多问题&#xff0c;比如忘记了iPhone的锁屏密码。面对这样的情况&#xff0c;许多用户可能会感到手足无措。别担心&#xff0c;本文将为您详细介绍iPhone忘记锁屏密码的解锁方法&#xff0c;让您轻松解决这一烦恼。 一、使用iTunes备份恢复 如…

盘点一下4种常见的微信的广告类型,在微信上打广告要花多少钱?

微信是一款社交媒体应用&#xff0c;集Facebook、Instagram和Snapchat的功能于一身。该应用拥有超过12亿的月活跃用户&#xff0c;其中约7亿为日活跃用户。由于其在中国网民中的成功和广泛的通信工具&#xff0c;微信是推广您业务的绝佳平台。 在这篇博客文章中&#xff0c;我…

Centos7完全卸载与安装mysql8.0+

Centos7卸载与安装mysql8.0 1、mysql8完全卸载2、mysql8安装 1、mysql8完全卸载 sudo systemctl stop mysqldsudo yum remove mysql-community-serversudo rm -rf /var/lib/mysql sudo rm -rf /etc/my.cnfsudo groupdel mysql sudo userdel mysqlsudo rm -rf /var/log/mysql s…

nginx代理原理(端口复用)探究

前言&#xff1a;对于一些常用的插件&#xff0c;我们应该学会如何使用。同时&#xff0c;其实现原理也要进行深究&#xff0c;可以为其他的项目开发做借鉴。 探究方案&#xff1a; 一、发布两个不同的服务&#xff0c;这两个服务的端口不致 二、配置nginx&#xff0c;让这两…

3W 3KVDC 隔离单、双输出 DC/DC 电源模块——TPH-3W 系列

TPH-3W系列是一款3W,单、双输出隔离电源模块&#xff0c;特别适合板上只有一种电压而要求有正负电源的场合&#xff0c;工业级温度范围–40℃到105℃&#xff0c;在此温度范围内都可以稳定输出2W&#xff0c;并且效率非常高&#xff0c;高达86%&#xff0c;温升非常低&#xff…

剁手党必看——转转红包使用规则与最优组合计算全解析

​ 1、省钱攻略基础之“了解平台红包使用规则” 2、举个栗子 3、最优红包组合计算方法进化过程 3.1、初代“笛卡尔乘积”版 3.2、二代“边算边比较Map聚合”版 3.3、三代“边算边比较数组索引定位”版 4、总结 1、省钱攻略基础之“了解平台红包使用规则” 规则一&#x…

浙大×移动云,携手点亮AI新时代

近年来&#xff0c;中国移动依托强大的算网资源优势&#xff0c;围绕大模型训练、推理和应用三大场景&#xff0c;打造了一站式智算产品体系。该体系旨在为客户提供覆盖资源、平台、应用的AI全链路服务。目前&#xff0c;一站式智算产品体系已在浙江大学智算中心和许昌中原智算…

后端常用技能:基于easy-poi实现excel一对多、多对多导入导出【附带源码】

0. 引言 在业务系统开发中&#xff0c;我们经常遇到excel导入导出的业务场景&#xff0c;普通的excel导入导出我们可以利用 apache poi、jxl以及阿里开源的easyexcel来实现&#xff0c;特别easyexcel更是将excel的导入导出极大简化&#xff0c;但是对于一些负载的表格形式&…

新能源汽车热管理方案现状与未来发展趋势

前言 新能源汽车的热管理技术在提高电池寿命、提高能量利用效率和确保车辆运行安全方面起着至关重要的作用。 一 新能源汽车热管理技术方案 1 电池热管理系统 电池热管理系统是电动汽车中至关重要的一部分&#xff0c;它通过冷却液循环、加热器、散热片等方式控制电池温度&…

【解决Android Studio】cmake报错找不到vulkan包

1 报错信息 CMake Error at D:/Android/project/cmake/3.10.2.4988404/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:137 (message): Could NOT find Vulkan (missing: Vulkan_LIBRARY) Call Stack (most recent call first): 2. 错误原因 minSdk版本不对&am…

【Linux网络编程】DNS、ICMP、NAT技术、代理服务器+网络通信各层协议总结

DNS、ICMP、NAT技术、代理服务器网络通信总结 1.DNS2.ICMP协议2.1ping命令2.2traceroute命令 3.NAT技术4.NAT和代理服务器5.网线通信各层协议总结 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&…

uniapp 小程序图片懒加载组件 ImageLazyLoad

预览图 组件【ImageLazyLoad】代码 <template><viewclass"image-lazy-load":style"{opacity: opacity,borderRadius: borderRadius rpx,background: background,transition: opacity ${time / 1000}s ease-in-out,}":class"image-lazy-loa…

白话机器3:PCA与SVM详细数学原理

一、PCA数学原理 1.数据标准化 首先&#xff0c;需要对原始数据进行标准化处理&#xff0c;使得每个特征的均值为0&#xff0c;方差为1。假设有一个的数据矩阵X&#xff0c;其中每一列是一个样本&#xff0c;每一行是一个特征。 标准化公式如下&#xff1a; 其中&#xff0c;…

Observability:监控与可观察性不同的 3 个原因

作者&#xff1a;来自 Elastic Elastic Observability Team 监控和可观察性通常可以互换使用&#xff0c;但它们并不完全相同。 监控是可观察性的重要组成部分&#xff0c;但可观察性远远超出了传统监控实践的范围。 主要区别&#xff1a;监控从各个组件收集数据 —— 时间和内…

【北京迅为】《iTOP-3588开发板快速烧写手册》-第8章 TF启动

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

PyQt:进度条实现(下载、复制)实时进度显示

一、实现思路 源文件:①被复制的文件&#xff08;一般在客户端自身PC上&#xff09;&#xff1b;②被下载的文件&#xff1b;&#xff08;一般在服务器上&#xff09;。 缓存文件&#xff1a;正在粘贴/下载获取中的文件&#xff0c;粘贴/下载完成前&#xff0c;一般是不完整的…

什么是CE认证?

目录 一、什么是CE认证&#xff1f; 二、CE认证对于企业来说有什么重要性&#xff1f; 三、企业在申请CE认证时&#xff0c;需要满足哪些条件和要求&#xff1f; 一、什么是CE认证&#xff1f; CE认证&#xff0c;即只限于产品不危及人类、动物和货品的安全方面的基本安全要…
最新文章