当前位置: 首页 > news >正文

Linux--进程间通信(1)(匿名管道)

目录

1.了解进程通信

1.1进程为什么要通信

1.2 进程如何通信

1.3进程间通信的方式 

 2.管道

2.1管道的初步理解

2.2站在文件描述符的角度-进一步理解管道

2.3 管道的系统调用接口(匿名管道)

2.3.1介绍接口函数:

2.3.2编写一个管道的代码


1.了解进程通信


1.1进程为什么要通信

以下是进程间通信的几个主要原因:

  1. 数据共享与协作
    • 当多个进程需要共同访问或修改同一份数据时,它们需要通过某种方式进行通信,以确保数据的一致性和完整性。
    • 进程间通信允许进程协同工作,共同完成任务。例如,一个进程负责数据收集,而另一个进程负责数据处理和存储。
  2. 系统效率
    • 进程间通信可以减少不必要的数据复制和重复计算,提高系统效率。
    • 通过共享内存或消息传递等方式,进程可以直接访问所需的数据或资源,而无需经过额外的拷贝或转换。
  3. 模块化与解耦
    • 在软件设计中,模块化是一个重要的原则。通过将不同的功能划分为独立的进程,可以提高代码的可维护性和可重用性。
    • 进程间通信是实现模块化设计的重要手段之一。通过定义明确的通信接口和协议,不同的进程可以独立地开发和测试,然后再通过通信接口进行集成。
  4. 并发与并行
    • 并发和并行是现代操作系统和计算机架构的重要特性。它们允许多个进程同时运行,以提高系统的吞吐量和响应速度。
    • 进程间通信是实现并发和并行编程的关键技术之一。通过适当的通信机制,不同的进程可以协调彼此的工作,确保并发和并行操作的正确性和高效性。
  5. 分布式系统与网络应用
    • 在分布式系统和网络应用中,不同的进程可能位于不同的计算机或设备上。它们需要通过网络进行通信,以交换数据、共享资源和协调操作。
    • 进程间通信是分布式系统和网络应用中的核心技术之一。它允许不同的进程在物理上分离的情况下仍然能够相互协作和通信。
  6. 操作系统与内核功能
    • 操作系统和内核提供了许多基本的服务和功能,如文件系统、设备驱动、进程调度等。这些服务和功能通常需要由多个进程共同协作完成。
    • 进程间通信允许操作系统和内核中的不同进程之间进行通信和协作,以实现更高级别的功能和服务。

1.2 进程如何通信

进程间通信的前提:先让不同的进程,看到同一份(由操作系统提供的)资源(“一段内存”)。

        假如进程A要和进程B进行通信,肯定不能让B直接访问到A进程中的资源,这就不符合进程具有独立性的概念了。那么,这时候就只能借助操作系统的帮助了。当进程A需要与进程B进行通信的时候,操作系统需要确保进程间通信的安全性和隔离性,OS会创建一个共享资源,满足进程间资源的读写。OS提供了很多的系统调用,OS创建的共享资源不同,系统调用接口不同,进程间的通信就会有不同的种类!


1.3进程间通信的方式 

以下三种都属于本地通信:

管道(Pipe)

管道是一种最基本的进程间通信(IPC)机制,它用于在具有亲缘关系的进程之间(通常指父子进程)进行单向数据传输。管道是基于文件描述符实现的,分为无名管道(也称为匿名管道)和命名管道(也称为FIFO)。(直接复用内核代码直接通信)

  • 匿名管道:仅能在具有亲缘关系的进程间使用。在进程创建时,由父进程创建管道,然后父进程将读/写端通过文件描述符的形式传递给子进程,子进程从该描述符中读取或写入数据。
  • 命名管道:可以在任意两个进程间使用,具有一个唯一的名称,在文件系统中以文件的形式存在。任何具有访问权限的进程都可以通过该名称访问命名管道,并进行数据的读写操作。

System V进程间通信(IPC)

System V IPC是UNIX系统V版本提供的一组进程间通信机制,包括消息队列、信号量和共享内存。

  • 消息队列:允许进程间发送和接收消息。消息队列是保存在内核中的消息链表,发送方将消息添加到队列的尾部,接收方从队列的头部取走消息。每个消息具有一个唯一的类型,接收方可以根据类型选择性地接收消息。
  • 信号量:用于同步和互斥。信号量是一个整数变量,用于表示某种资源的数量。进程可以通过对信号量进行P(减)和V(加)操作来实现对资源的访问控制。
  • 共享内存:允许两个或多个进程共享同一块内存空间。共享内存是进程间通信中最快的方式,因为数据直接在内存中传递,不需要进行内核和用户空间的数据拷贝。但是,共享内存需要进程间进行同步以防止数据的不一致。

POSIX进程间通信(IPC)

POSIX IPC是POSIX(Portable Operating System Interface)标准定义的一组进程间通信机制,包括消息队列、信号量、共享内存以及套接字等。POSIX IPC与System V IPC的主要区别在于它们的接口和语义有所不同,但它们都提供了类似的通信功能。

  • POSIX消息队列:与System V消息队列类似,但具有更丰富的功能和更灵活的接口。
  • POSIX信号量:与System V信号量类似,但提供了更丰富的操作,如等待多个信号量等。
  • POSIX共享内存:与System V共享内存类似,但提供了更简洁的接口和更丰富的功能,如内存映射文件等。

 2.管道


2.1管道的初步理解

        如果我们以两种不同的方式(读和写)打开同一个文件(hello.txt),这时会创建两个不同的文件结构体对象,但操作系统只会加载一份该文件的(inode,内核级文件缓冲区,操作发方法集合,内容和属性)。 

        理解一种现象:为什么父子进程会向同一个显示器终端打印数据?

        因为进程默认会打开三个标准输入输出:0,1,2。怎么做到的?因为bash打开了,我们在OS中运行的进程都是bash的子进程,因此所有的子进程也就默认打开了。

        close():为什么我们的子进程主动close(0/1/2),不影响父进程继续使用显示器文件呢?

        因为文件的结构体对象中包含了内存级的引用计数,父进程的关闭只会导致引用计数--,只有当引用计数为0时,文件资源才会被彻底的释放。

        当我们创建一个子进程后,子进程会继承父进程的内核数据结构(这里指文件的),但内容不会,子进程中管理文件的数据结构,包含了指向文件的结构体对象的指针,当然也可以通过文件的结构体对象,对打开的文件进行读写。多个进程都可以通过内核级文件缓冲区看到文件的资源,我们将这个内核级文件缓冲区称作:管道文件!未来父进程往管道文件中写,子进程向管道文件中读,就实现进程通信了!!!

        这种通信,只允许父和子的单向通信,这意味着数据只能从管道的写端流向读端,而不能反过来。这样的设计目:管道最初被设计为一种简单的进程间通信机制,主要用于父子进程之间的数据传递。它的设计目标就是实现单向数据流,以满足这种简单的通信需求。(父->子 / 子->父)    


2.2站在文件描述符的角度-进一步理解管道

  1. 创建管道:父进程首先调用pipe()系统调用来创建一个管道。这个系统调用会返回一个包含两个文件描述符的数组,通常表示为pipefd[2]。其中,pipefd[0]是管道的读端,pipefd[1]是管道的写端。
  2. 创建子进程:父进程接着会调用fork()系统调用来创建一个新的子进程。子进程会继承父进程的文件描述符表,包括刚才创建的管道文件描述符。
  3. 关闭不需要的文件描述符:为了防止读写混乱,父子进程需要各自关闭不需要的文件描述符。通常,父进程会关闭管道的写端(pipefd[1]),只保留读端;而子进程会关闭管道的读端(pipefd[0]),只保留写端。这样,子进程就可以向管道中写入数据,而父进程则可以从管道中读取数据。
  4. 写入数据:子进程使用write()系统调用,通过管道的写端(pipefd[1])向管道中写入数据。写入的数据会被存储在内核的缓冲区中,等待父进程读取。
  5. 读取数据:父进程使用read()系统调用,通过管道的读端(pipefd[0])从管道中读取数据。如果父进程在读取数据时,管道中没有数据可读(即子进程还没有写入数据),那么父进程的read()调用会被阻塞,直到有数据可读为止。同样地,如果子进程向已经写满的管道中写入数据,它的write()调用也会被阻塞,直到有空间可写为止。
  6. 关闭文件描述符:当父子进程完成通信后,它们应该分别关闭各自的文件描述符,以释放资源。

        管道的数据传输是直接在内存中进行的,不涉及硬盘I/O操作。当数据被写入管道时,它会被存储在内核的缓冲区中,等待读取进程来读取。读取进程通过系统调用从内核缓冲区中读取数据,最后父子进程都关闭文件描述符,管道被释放,不会被内存缓冲区刷新到磁盘


2.3 管道的系统调用接口(匿名管道)

2.3.1介绍接口函数:

        我们通过文件的原理理解了管道,但是不能用文件的接口了,因为文件的接口没法让内存级缓冲区的数据不往磁盘刷新的,所以工程师做了一个专门的接口:pipe

pipe() 系统调用

   pipe() 系统调用用于在调用进程中创建一个管道(pipe创建的管道就是一个文件,但它不是普通文件,而是单独构成一种文件系统,他没有名字,故又称为匿名管道,并且只存在于内存中。)它接受一个文件描述符数组作为参数,并在这个数组中填充两个文件描述符:一个用于读(pipefd[0]),另一个用于写(pipefd[1])。

        

这个管道只是让(父->子 / 子->父),那我想实现双向的通信呢?

        可以创建两个管道!!!(多线程时讲解)

       

为什么管道是单向的呢?

  1. 简化设计:单向通信的管道设计简化了管道的实现和管理。通过限制数据只能在一个方向上流动,可以避免很多与双向通信相关的复杂性和潜在的同步问题。这种简单性使得管道成为一种高效、轻量级的进程间通信(IPC)机制。

  2. 避免冲突:在双向通信中,如果两个进程同时尝试读写同一个管道,可能会导致数据冲突和混乱。通过限制管道为单向通信,可以确保数据的有序性和一致性,从而避免这种冲突。

  3. 清晰性:单向通信使得管道的使用更加清晰明了。进程可以明确地知道哪个管道用于发送数据,哪个管道用于接收数据。这种明确性有助于减少编程错误和调试困难。

  4. 灵活性:虽然单个管道只能实现单向通信,但可以通过组合多个管道来实现双向通信或其他更复杂的通信模式。例如,可以使用两个管道来模拟双向通信:一个管道用于进程A向进程B发送数据,另一个管道用于进程B向进程A发送数据。这种灵活性使得管道可以适应各种不同的应用场景。

  5. 安全性:在某些情况下,限制通信方向可以提高系统的安全性。例如,在服务器和客户端之间的通信中,服务器可能只希望从客户端接收请求并发送响应,而不希望客户端能够直接读取或修改服务器的内部状态。通过使用单向通信的管道,可以确保这种安全性要求得到满足。


2.3.2编写一个管道的代码

1.初步代码:我们调用了pipe,创建管道成功后,我们查看了pipefd[0]是读文件描述符(读端),而pipefd[1]是写文件描述符(写端),不出所料是3和4,管道创建是成功的,那么意味着创建了两个structfile指向缓冲区的。

#include<iostream>
#include<cerrno>
#include<cstring>
#include<unistd.h>
int main()
{//1.创建管道int pipefd[2];int n =pipe(pipefd);//输出型参数,rfd,wfdif(n!=0){std::cerr<<"errno:"<<errno<<":"<<"errstring :"<<strerror(errno)<<std::endl;return 1;}std::cout<<"pipefd[0]: "<<pipefd[0]<<", pipefd[1]: "<<pipefd[1]<<std::endl;return 0;
}

2.完成这一步的代码,就让父子进程看到了同一份资源,但还没有进行通信:

    //2.创建子进程//3.关闭不需要的fdpid_t id = fork();if(id==0){//子进程//子进程需要写,那就关闭读端colse(pipefd[0]);exit(0);}//父进程//子进程需要读,那就关闭写端colse(pipefd[0]);

3.进行通信

#include <iostream>
#include <string>
#include <cerrno>  // errno.h
#include <cstring> // string.h
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>const int size = 1024;std::string getOtherMessage()
{static int cnt = 0;std::string messageid = std::to_string(cnt); // stoi -> string -> intcnt++;pid_t self_id = getpid();std::string stringpid = std::to_string(self_id);std::string message = "messageid: ";message += messageid;message += " my pid is : ";message += stringpid;return message;
}// 子进程进行写入
void SubProcessWrite(int wfd)
{int pipesize = 0;std::string message = "father, I am your son prcess!";char c = 'A';while (true){std::string info = message + getOtherMessage(); // 这条消息,就是我们子进程发给父进程的消息write(wfd, info.c_str(), info.size()); // 写入管道的时候,没有写入\0, 有没有必要?没有必要std::cerr << info << std::endl;}std::cout << "child quit ..." << std::endl;
}// 父进程进行读取
void FatherProcessRead(int rfd)
{char inbuffer[size]; // c99 , gnu g99while (true){sleep(2);// sleep(500);ssize_t n = read(rfd, inbuffer, sizeof(inbuffer) - 1); // sizeof(inbuffer)->strlen(inbuffer);if (n > 0){inbuffer[n] = 0; // == '\0'std::cout  << inbuffer << std::endl;}else if (n == 0){// 如果read的返回值是0,表示写端直接关闭了,我们读到了文件的结尾std::cout << "client quit, father get return val: " << n << " father quit too!" << std::endl;break;}else if(n < 0){std::cerr << "read error" << std::endl;break;}// sleep(1);// break;}
}int main()
{// 1. 创建管道int pipefd[2];int n = pipe(pipefd); // 输出型参数,rfd, wfdif (n != 0){std::cerr << "errno: " << errno << ": "<< "errstring : " << strerror(errno) << std::endl;return 1;}// pipefd[0]->0->r(嘴巴 - 读)  pipefd[1]->1->w(笔->写)std::cout << "pipefd[0]: " << pipefd[0] << ", pipefd[1]: " << pipefd[1] << std::endl;sleep(1);// 2. 创建子进程pid_t id = fork();if (id == 0){std::cout << "子进程关闭不需要的fd了, 准备发消息了" << std::endl;sleep(1);// 子进程 --- write// 3. 关闭不需要的fdclose(pipefd[0]);// if(fork() > 0) exit(0);SubProcessWrite(pipefd[1]);close(pipefd[1]);exit(0);}std::cout << "父进程关闭不需要的fd了, 准备收消息了" << std::endl;sleep(1);// 父进程 --- read// 3. 关闭不需要的fdclose(pipefd[1]);FatherProcessRead(pipefd[0]);std::cout << "5s, father close rfd" << std::endl;sleep(5);close(pipefd[0]);int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){std::cout << "wait child process done, exit sig: " << (status&0x7f) << std::endl;std::cout << "wait child process done, exit code(ign): " << ((status>>8)&0xFF) << std::endl;}return 0;
}

子进程写入函数(SubProcessWrite)逻辑:

该函数在子进程中运行,用于不断向管道写入消息。具体逻辑如下:

  1. 初始化:定义一个pipesize变量(但在此函数中并未实际使用),初始化一个字符串message作为要发送的基本消息,并定义了一个字符c(同样未使用)。

  2. 构造消息:在每次循环中,将预定义的message与通过调用getOtherMessage()函数(该函数未在代码中定义)获取的其他消息合并,形成一个新的info字符串。

  3. 写入管道:使用write系统调用将info字符串的内容(不包括结尾的\0字符)写入到管道的写端。由于管道是字节流,通常不需要在写入时添加\0字符。

父进程读取函数(FatherProcessRead)逻辑:

该函数在父进程中运行,用于从管道读取子进程发送的消息。具体逻辑如下:

  1. 定义缓冲区:声明一个字符数组inbuffer作为读取数据的缓冲区,但注意size变量并未在给出的代码片段中定义,需要确保在调用此函数之前定义了size的值。

  2. 读取循环:函数进入一个循环,该循环将不断尝试从管道的读端读取数据。

  3. 休眠:在每次尝试读取之前,父进程会休眠2秒,模拟非阻塞或延迟读取的情况。

  4. 读取数据:使用read系统调用从管道的读端读取数据到inbuffer中。读取的字节数由read的返回值n确定。在读取的数据后手动添加一个\0字符作为字符串的结束标志。

  5. 处理读取到的数据

    • 如果读取到的字节数n大于0,表示成功读取到数据,将inbuffer作为字符串输出。
    • 如果n等于0,表示子进程已经关闭了写端,父进程读取到了文件结尾(EOF),于是退出读取循环。
    • 如果n小于0,表示在读取过程中发生了错误,输出错误信息并退出读取循环。
  6. 退出循环:当读取到文件结尾或发生错误时,退出循环。在函数结束时,并没有显式地关闭读端文件描述符,但在实际情况中,父进程可能需要在其他位置关闭这个文件描述符以避免资源泄漏。

管道的四种情况:

        1.如果管道内部是空的,并且write fd没有关闭,读取条件不具备,读进程会被阻塞--wait->读取条件具备<-写入数据。

        2.管道被写满,并且read fd不读且没有关闭,管道被写满,写进程会被阻塞(管道被写满--写条件不具备)--wait--写条件具备<-读取数据。

        3.管道一直在读,并且写端关闭了wfd,读端read返回值会读到0,表示读到了文件结尾。

        4.读端(rfd)直接被关闭了,写端进程会被操作系统直接使用13号文件关掉。相当于进程出现了异常。

管道的五种特征:

        1.匿名管道:只用来进行有血缘关系进程之间的进程通信,常用于父子进程之间的通信。

        2.管道内部,自带进程之间同步的机制(多执行流执行代码的时候,具有明显的顺序性)。

        3.管道文件的生命周期是随进程的。

        4.管道文件在通信的时候,是面向字节流的,write的次数和读取的次数不是一 一匹配的。由于管道是面向字节流的,并且可能涉及到缓冲,因此读取操作不一定会按照写入操作的次数来进行。例如,写进程可能分两次写入了100字节和200字节的数据,但读进程可能一次就读取了300字节的数据,或者分三次读取(100字节、100字节、100字节)。

        5. 半双工模式:匿名管道(即常见的管道)是半双工的,这意味着数据只能在一个方向上流动,通常用于有亲缘关系的进程间通信,如父子进程之间。

相关文章:

Linux--进程间通信(1)(匿名管道)

目录 1.了解进程通信 1.1进程为什么要通信 1.2 进程如何通信 1.3进程间通信的方式 2.管道 2.1管道的初步理解 2.2站在文件描述符的角度-进一步理解管道 2.3 管道的系统调用接口&#xff08;匿名管道&#xff09; 2.3.1介绍接口函数&#xff1a; 2.3.2编写一个管道的代…...

Hive环境搭建

1 安装Hive 下载文件 # wget -P /opt/ https://mirrors.huaweicloud.com/apache/hive/hive-2.3.8/apache-hive-2.3.8-bin.tar.gz 解压缩 # tar -zxvf /opt/apache-hive-2.3.8-bin.tar.gz -C /opt/ 修改hive文件夹名字 # mv /opt/apache-hive-2.3.8-bin /opt/hive 配置环境变量 …...

网络编程基础(四)

目录 前言 二、多点通信 2.1 单播 2.2 广播 2.2.1 广播得发送端实现--》类似与UDP的客户端 2.3 组播 2.3.1 组播发送端流程--》类似于UDP的客户端流程 2.3.2 组播的接收端流程---》类似于UDP的服务器端流程 前言 多点通信 一、套接字选项得获取和设置 int getsockopt(int…...

将C++ cv:mat 通过JNI 转换为jbtyearray,传到android端

cv::Mat result ; //此处为C获取到的cv::mat结果对象// 编码为JPEG格式std::vector<uchar> buf;cv::imencode(".jpg", result, buf);// 创建一个新的jbyteArray并设置其大小jbyteArray array env->NewByteArray(buf.size());if (array NULL) {// 处理内存…...

WannaCry勒索软件(CVE-2017-0144)

WannaCry 永恒之蓝 在2017年5月&#xff0c;WannaCry勒索软件爆发了一场全球性的网络安全危机&#xff0c;迅速感染了超过200,000台计算机&#xff0c;波及150多个国家。从医疗保健系统到政府机构&#xff0c;无数组织面临数据被加密和赎金要求的双重威胁。本文将提供关于Wann…...

JavaScript(ES5) 入门

01-简介 1)JavaScript 发展史 [1] 1995年,navigator(导航者),netscape(网景);用户体验性特别好 [2] 表单验证难题,表单验证都是在后台处理.当时处在网速特别慢的时代,发送一个请求,接收响应 需要5分钟左右的时候提高表单验证的速度,想开发一种语言在前端进行表单验证. [3] 1995…...

趣店集团golang一面要个20K,Channel什么情况下会出现死锁,有遇到过吗?

结束后面试官加了VX&#xff0c;并询问方便二面的时间&#xff0c;一直还没回复&#xff0c;拖着拖着给忘啦... 面试题 1、自我介绍 2、你在团队里头负责哪一块&#xff0c;这个物流开放平台流量多大 3、为什么今年3月份被从物流开放团队转到了finance财务部门&#xff0c;感…...

智能化乙级资质延期,行业标准的坚守

智能化乙级资质延期&#xff1a;行业标准的坚守 一、引言 智能化乙级资质是企业在智能化工程设计与施工领域的重要认证&#xff0c;它代表了企业的技术实力和专业水平。为确保企业能够持续满足行业标准&#xff0c;保持竞争力&#xff0c;智能化乙级资质的延期管理显得尤为重要…...

d20(184-190)-勇敢开始Java,咖啡拯救人生

目录 网络通信 网络通信三要素&#xff08;IP地址&#xff0c;端口号&#xff0c;协议 IP地址 InetAddress 端口号 协议 传输层的两个通信协议 UDP通信 java.net.Datagramsocket类 客户端 服务端 UDP通信多收多发 客户端 服务端 TCP通信 java.net.Socket类 客…...

Python 登录表单处理

分析&#xff1a; 处理登录表单以便爬⾍能够抓取需要认证的⽹⻚数据&#xff0c;通常需要模拟登录过程。这可以通过发送带有⽤⼾凭证的POST请求到登录表单的URL来实现。为了保持登录状态&#xff0c;需要处理和保存会话中的 cookies。Python的 requests 库可以⽅便地处理这些任…...

2024.05.27学习记录

1、面经复习&#xff1a; 实际工作经验章节 2、代码随想录刷题&#xff1a;动态规划剩下部分和单调栈 3、rosebush 组件库完成Input 和 AutoComplete部分内容...

BLASTBufferQueue端的GraphicBuffer怎么和SurfaceFlinger端的BufferStateLayer关联上

BLASTBufferQueue端的GraphicBuffer怎么和SurfaceFlinger端的BufferStateLayer关联上 引言 在跟进hwc_layer是如何产生的&#xff0c;并如何被填充上GraphicBuffer的&#xff0c;怎么也找不到被填充的GraphicBuffer的来源&#xff0c;最终找到了&#xff0c;它的来源是客户端的…...

48、spfa求最短路

spfa求最短路 题目描述 给定一个n个点m条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c; 边权可能为负数。 请你求出1号点到n号点的最短距离&#xff0c;如果无法从1号点走到n号点&#xff0c;则输出impossible。 数据保证不存在负权回路。 输入格式 第一行包…...

安装PyTorch详细步骤

&#x1f4a5;注意事项&#xff1a; CPU版和GPU版选一个进行安装即可 如果有Nvidia显卡&#xff0c;则安装cuda版本的PyTorch&#xff0c;如没有nvidia显卡&#xff0c;则安装cpu版。 目前常见的深度学习框架有很多&#xff0c;最出名的是&#xff1a;PyTorch&#xff08;faceb…...

linux线程,线程控制与线程相关概念

线程概念 线程这个词或多或少大家都听过&#xff0c;今天我们正式的来谈一下线程&#xff1b; 在我一开始的概念中线程就是进程的一部分&#xff0c;一个进程中有很多个线程&#xff0c;这个想法基本是正确的&#xff0c;但细节部分呢我们需要细细讲解一下&#xff1b; 什么…...

第八大奇迹

目录 题目描述 输入描述 输出描述 输入输出样例 示例 输入 输出 运行限制 原题链接 代码思路 题目描述 在一条 R 河流域&#xff0c;繁衍着一个古老的名族 Z。他们世代沿河而居&#xff0c;也在河边发展出了璀璨的文明。 Z 族在 R 河沿岸修建了很多建筑&#xff0c…...

MySQL:CRUD初阶(有图有实操)

文章目录 &#x1f4d1;1. 数据库的操作&#x1f324;️1.1 显示当前的数据库&#x1f324;️1.2 创建数据库&#x1f324;️1.3 选中数据库&#x1f324;️1.4 删除数据库 &#x1f4d1;2. 表的操作&#x1f324;️2.1 查看表结构&#x1f324;️2.2 创建表&#x1f324;️2.3…...

『大模型笔记』使用 vLLM 和 PagedAttention 快速提供 LLM 服务!

使用 vLLM 和 PagedAttention 快速提供 LLM 服务! 文章目录 一. 使用 vLLM 和 PagedAttention 快速提供 LLM 服务!1.1. PagedAttention二. 参考文献小红书中文字幕视频:https://www.xiaohongshu.com/explore/66502b60000000000500433e官网文档(推荐,里面有动图解释):vLLM:…...

简述vue-loader是什么?使用它的用途有哪些

vue-loader是一个webpack的加载器(loader)&#xff0c;主要用于将Vue组件的单文件(.vue文件)转换为JavaScript模块。使用vue-loader的主要用途包括&#xff1a; 解析.vue文件&#xff1a;vue-loader能够解析.vue文件中的模板、样式和脚本&#xff0c;并将它们分离出来进行处理…...

如何远程访问Redis?

远程访问Redis是一种常见的需求&#xff0c;特别是在分布式系统或跨地域网络中。通过远程访问&#xff0c;我们可以轻松地对远程的Redis数据库进行操作和管理。 天联保障数据安全 对于远程访问Redis的安全性问题&#xff0c;我们可以借助天联来保障数据的安全。天联是一种基于…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

k8s从入门到放弃之HPA控制器

k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率&#xff08;或其他自定义指标&#xff09;来调整这些对象的规模&#xff0c;从而帮助应用程序在负…...