最新资讯

  • 【Linux】进程间通信

【Linux】进程间通信

2025-05-26 12:00:57 73 阅读

管道、共享内存、消息队列、信号量

  • 1. 进程间通信
    • 1.1. 目的
    • 1.2. 概念和本质
    • 1.3. 分类
  • 2. 管道
    • 2.1 概念
    • 2.2. 4种情况
    • 2.3. 4种特性
    • 2.4. 匿名管道
      • 2.4.1. 原理
      • 2.4.2. 概念
      • 2.4.3. 创建 — pipe()
      • 2.4.4. 应用场景 — 进程池
    • 2.5. 命名管道
      • 2.5.1. 概念和原理
      • 2.5.2. 创建 — mkfifo()
      • 2.5.3. 应用场景 — server&client通信
    • 2.6. 命名管道与匿名管道的区别
  • 3. System V 共享内存
    • 3.1. 概念和原理
    • 3.2. 共享内存函数
    • 3.3. shmget — 创建共享内存
    • 3.4. shmat — 进程挂接共享内存
    • 3.5. shmdt — 断开共享内存连接
    • 3.6. shmctl — 删除共享内存
    • 3.7. 应用场景 — server&client通信
    • 3.8. 命令行查看共享内存
    • 3.9. 优缺点
  • 4. 消息队列
    • 4.1. 原理与概念
    • 4.2. 消息队列函数
  • 5. System V中IPC资源在内核中的设计
  • 6. 信号量
    • 6.1. 储备知识
    • 6.2. 原理与概念

1. 进程间通信

1.1. 目的

  1. 数据传输:一个进程需要将它的数据发送给另一个进程。

  2. 资源共享:多个进程之间共享同样的资源。

  3. 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。

  4. 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变。

总结:为了实现多个进程之间的协同工作,以便共同完成某项任务或处理复杂的数据交互。

1.2. 概念和本质

问:一个进程可以直接访问另一个进程的数据吗?

不能,因为进程具有独立性,包括数据结构和内存数据的独立性,因此进程间直接数据访问是不可能的,这就需要通过OS提供的IPC机制来实现进程之间的信息传递。

  1. 进程间通信(简称为IPC):是指在计算机系统中,多个进程之间传输数据或者信号的一种机制或方法。

  2. 进程间通信的本质或前提:让不同的进程,看到同一份由OS提供的资源,作为交换数据的空间。

这一前提是进程间通信能够得以实现的基础。

OS提供的空间有不同的"样式",就决定了有不同的通信方式。

1.3. 分类

  1. 管道:匿名管道pipe、 命名管道。

  2. System V IPC :System V 消息队列 、 System V 共享内存 、 System V 信号量。

  3. POSIX IPC :消息队列 、 共享内存 、 信号量 、 互斥量 、 条件变量 、 读写锁。

2. 管道

2.1 概念

  1. 管道的概念:它允许一个进程的标准输出(stdout)直接连接到另一个进程的标准输入(stdin),形成的一个数据流通道,即:它允许一个进程将数据写入管道的一端(写端),另一个进程从管道的另一端(读端)读取数据,如:ls -l | grep test,|为管道。

管道是进程间通信的一种方式,常用于unix系统和Linux系统中。

  1. 管道是一种特殊的文件类型,它并不在磁盘上占用实际的物理空间来存储数据,管道的数据存在于内核的缓冲区中,这些缓冲区是内存的一部分,即:它是内存级的文件,数据交换是在内存中直接进行的,无需将数据写入到磁盘再进行读取。

基于文件的,让不同进程看到同一份资源的通信方式,叫做管道。

💡Tips:管道只能进行单向通信!但可以通过创建两个管道来实现双向通信。

2.2. 4种情况

  1. 管道内部没有数据,且(父进程)没有关闭写端fd,读端(子进程)就要阻塞等待,直到管道内部有数据。
#include
#include
#include
#include

using namespace std;

void writer(int wfd) //父进程写
{
    int cnt = 0;
    char str[128] = "hello, I am father!";
    while(1)
    {
        char buffer[128]; 
        snprintf(buffer, sizeof(buffer), "%s, cnt: %d, id: %d", str, cnt++, getpid());   
        write(wfd, buffer, strlen(buffer));
        sleep(100); //情况一:管道内部没有数据,且(父进程)没有关闭写端fd,读端(子进程)就要阻塞等待,直到管道内部有数据
    }
}

void reader(int rfd)  //子进程读
{
    while(1)
    {
        char buffer1[128];
        read(rfd, buffer1, sizeof(buffer1));
        printf("child get messages: %s
", buffer1);
    }
}

int main()
{
    //1.父进程创建管道
    int pipefd[2];
    int n = pipe(pipefd);
    if(n == -1) return 1;

    //2.父进程创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        //子进程关闭写,进行读
        close(pipefd[1]);
        reader(pipefd[0]);
    }
    //父进程关闭读,进行写
    close(pipefd[0]);
    writer(pipefd[1]);

    return 0;
}

  1. 管道内部被写满,且(子进程)未关闭读端fd,(父进程)写端就要阻塞等待,直到管道内部有空间。

💡Tips:管道的大小,通常为64kb,不同的OS值不同。

#include
#include
#include
#include

using namespace std;

void writer(int wfd) //父进程写
{
    int cnt = 0;
    // char str[128] = "hello, I am father!";
    while(1)
    {
        char buffer[128]; 
        // snprintf(buffer, sizeof(buffer), "%s, cnt: %d, id: %d", str, cnt++, getpid());   
        // write(wfd, buffer, strlen(buffer));
        char c = 'A';
        write(wfd, &c, sizeof(c)); 
        printf("pipe number:%d
", cnt++); //测试管道在内核内存中维护的缓冲区大小,64kb
    }
}

void reader(int rfd)  //子进程读
{
    while(1)
    {
        char buffer1[128];
        read(rfd, buffer1, sizeof(buffer1));
        printf("child get messages: %s
", buffer1);
        sleep(100);  //情况2:管道内部被写满,且(子进程)未关闭读端fd,(父进程)写端就要阻塞等待,直到管道内部有空间
    }
}

int main()
{
    //1.父进程创建管道
    int pipefd[2];
    int n = pipe(pipefd);
    if(n == -1) return 1;

    //2.父进程创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        //子进程关闭写,进行读
        close(pipefd[1]);
        reader(pipefd[0]);
    }
    //父进程关闭读,进行写
    close(pipefd[0]);
    writer(pipefd[1]);

    return 0;
}

  1. 不再写入数据,且关闭写端fd,读端会将管道内部剩余的数据读完,最后会读取到返回值为0,表示读结束,类似于读到了文件结尾。

读端本身不会因为写端的关闭而被OS直接关闭,它仍需要由读进程显示地关闭或随着读进程的结束而关闭。

#include
#include
#include
#include

using namespace std;

void writer(int wfd) //父进程写
{
    int cnt = 5;
    char str[128] = "hello, I am father!";
    while(cnt--)
    {
        char buffer[128]; 
        snprintf(buffer, sizeof(buffer), "%s, cnt: %d, id: %d", str, cnt, getpid());   
        write(wfd, buffer, strlen(buffer));
        sleep(1);
        // char c = 'A';
        // write(wfd, &c, sizeof(c)); 
        // printf("pipe number:%d
", cnt++); //测试管道在内核内存中维护的缓冲区大小,64kb
    }
    close(wfd); //情况3:不再写入数据,且关闭写端fd
}

void reader(int rfd)  //子进程读
{
    while(1)
    {
        char buffer1[128];
        int n = read(rfd, buffer1, sizeof(buffer1));
        if(n > 0)
            printf("child get messages: %s
", buffer1);
        else if(n == 0)  //情况3:读端会将管道内部剩余的数据读完,最后会读取到返回值为0,表示读结束,类似于读到了文件结尾
        {
            printf("write close, read ending, quit....
");
            break;
        }
        else 
        {
            printf("read error
");
            break;
        }
        //sleep(100);  //情况2:管道内部被写满,且(子进程)未关闭读端fd,(父进程)写端就要阻塞等待,直到管道内部有空间
    }
}

int main()
{
    //1.父进程创建管道
    int pipefd[2];
    int n = pipe(pipefd);
    if(n == -1) return 1;

    //2.父进程创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        //子进程关闭写,进行读
        close(pipefd[1]);
        reader(pipefd[0]);
    }
    //父进程关闭读,进行写
    close(pipefd[0]);
    writer(pipefd[1]);

    return 0;
}

  1. 不再读取,且关闭读端fd,写端仍在进行写入,OS会通过信号13:SIGPIPE直接终止进行写入的进程。

2.3. 4种特性

  1. 自带同步和互斥机制。

同步:确保两个或多个进程在运行过程中,按照预定的先后次序运行的一种机制,eg:一个任务的执行依赖于另一个任务产生的数据,管道中写操作必须先于读操作,以确保数据的正确传输和接收。

互斥:是保护共享资源,防止多个进程同时访问同一资源,导致数据不一致或错误的一种机制,即:公共资源在同一时刻只能被一个进程使用,不能被多个进程同时使用。eg:在管道中,互斥要求在同一时刻只有一个进程能够执行特定操作(r或w)。

  1. 面向字节流。

一个进程写入管道的数据是以字节序列(连续排列的字节,无固定大小)的形式存在的,而另一个进程从管道读取数据时,每次读取的字节数量是任意的,取决于此进程的读取操作。这种特性使得管道通信在很多情况下都表现得像是一种“流式服务"。

“流式服务”:意味着数据以连续不断的流的形式传输,接收方根据需要或能力来读取任意数量的数据。

  1. 管道的生命周期随进程。

管道的生命周期,与使用它的进程生命周期成正相关。当所有打开管道的文件描述符都关闭,且没有进程再引用管道时,管道就会被内核回收,其占用的资源也会被释放。

使用它的进程:包括创建它的进程,以及其他通过某种方式(如: fork)获得该管道引用的进程。

  1. 管道只能单向通信,是半双工通信的一种特殊情况。

半双工通信:允许数据在两个方向上传输,但在同一时刻只能在一个方向上进行。即:当一方正在发送数据,另一方不能同时发送数据,只能接收数据。如:对讲机。

全双工通信:允许数据在两个方向上同时传输,即:通信双方可以同时发送和接收数据。如:电话。

单工通信:数据只能单方向传输,即:一方固定为发送端,另一方固定为接收端。如:广告屏幕。

2.4. 匿名管道

2.4.1. 原理

一、补充知识:

  1. 如果一个进程同时连续两次以相同或不同的方式打开同一个文件,且第一个文件未被关闭,OS会创建两个文件描述符和文件结构体对象,但这两个文件描述符实际上指向的同一个磁盘文件和文件内核缓冲区。

即:无论你打开多次,只要文件名相同,文件系统不变,这些打开操作都指向同一个磁盘文件和文件内核缓冲区。

  1. 父进程创建子进程时,子进程会继承与进程相关的多种数据结构,如:task_struct、mm_struct、页表、文件描述符表。子进程并不会直接继承文件结构体对象,而是通过继承父进程的文件描述符来共享已经打开的文件结构体对象。

文件描述符表体现了有多少个文件和此进程相关联,是进程访问文件的接口,子进程继承父进程的文件描述符表,以便能够访问父进程打开的文件。

二、原理

为什么父进程一开始就要按照r、w方式,打开同一个文件呢?

若父进程以只读r或只写w方式打开一个文件,那么子进程继承这个文件描述符也只能以只读r或只写w方式访问这个文件,无法进行基于文件的进程间通信,因为通信需要至少一方能够写入数据,另一方能够读取数据。即:父进程一开始就要按照r、w方式为了后续能够灵活地设置通信方向。

每个进程都有一个文件描述表,用于存储指向struct file结构体的指针,struct file允许多个进程通过指针指向它。 每个struct file内部都有一个引用计数,用来跟踪有多少个fd指向它,关闭文件时,OS会将struct file引用计数–,直到引用计数=0,OS会释放struct file对象,但磁盘上的文件仍在,删除文件系统中的文件需要通过系统调用unlink()、remove()。

2.4.2. 概念

  1. 匿名管道:也被称为无名管道,是用于进程间通信的特殊文件。

匿名管道没有显示的名称,所以在文件系统中找不到,也无法通过常规的文件操作(open、write等)来访问它,只能在创建它的进程及其子进程中有效。

  1. 匿名管道在内核内存中维护一个缓冲区(通常大小为64KB,用于暂存进程间传输的数据),它是一种临时的通信机制,只能用于在具有血缘关系的进程之间的单向通信。

临时性:匿名管道的生命周期,与创建它的进程及其子进程成正相关。一旦这些进程都退出,管道和缓冲区就会消失。

因为匿名管道,是通过子进程继承父进程的相关的数据结构,使得父子进程看到同一块资源,从而实现进程间通信,所以匿名管道只能在具有血缘关系的进程间通信。

  1. 本质:在linux中,它被视为内存级的文件,不属于任何文件系统,只存在于内存中,无需向磁盘中进行刷新。

2.4.3. 创建 — pipe()

int pipe(int pipefd[0]);

  • 功能:创建一个匿名管道。

  • 参数:pipefd是一个指向包含两个整数的数组指针,这两个整数将用作于管道的文件描述符,pipefd[0]为读端文件描述符、pipefd[1]为写端文件描述符。

  • 返回值:成功时返回0,失败时返回-1,并设置错误码errno以指示错误原因。

//从字符串buffer中读取数据,写入管道,读取管道,写到字符串buffer1中
#include
#include
#include
#include

using namespace std;

void writer(int wfd)
{
    int cnt = 0;
    char str[128] = "hello, I am father!";
    while(1)
    {
        char buffer[128]; 
        snprintf(buffer, sizeof(buffer), "%s, cnt: %d, id: %d", str, cnt++, getpid());   
        write(wfd, buffer, strlen(buffer));
        sleep(1);
    }
}

void reader(int rfd) 
{
    while(1)
    {
        char buffer1[128];
        read(rfd, buffer1, sizeof(buffer1));
        printf("child get messages: %s
", buffer1);
    }
}

int main()
{
    //1.父进程创建管道
    int pipefd[2];
    int n = pipe(pipefd);
    if(n == -1) return 1;

    //2.父进程创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        //子进程关闭写,进行读
        close(pipefd[1]);
        reader(pipefd[0]);
    }
    //父进程关闭读,进行写
    close(pipefd[0]);
    writer(pipefd[1]);

    return 0;
}

2.4.4. 应用场景 — 进程池

一、定义与组成

  1. 定义:是管理一组预先创建的进程的方法,这些进程处于空闲状态,等待接收并处理任务。

  2. 组成:主要是由资源进程和管理进程组成,管理进程负责创建资源进程、分配任务、回收资源,资源进程负责执行实际的任务。

二、工作原理

  1. 工作流程:初始化 -> 任务提交 -> 任务分配 -> 任务执行 -> 任务完成 -> 资源回收。

初始化:管理进程首先会创建一组预设数量的资源进程。这些进程在初始化时处于空闲状态,并等待接收任务。同时,管理进程会设置必要的通信机制(如管道),以便与子进程进行通信。

任务提交:用户或OS将需要执行的任务提交给管理进程。

任务分配:管理进程接收到任务后,会从进程池中取出一个空闲的进程,通过之前设置的通信机制(如管道)将任务发送给该进程。

任务执行:接收到任务的资源进程开始执行任务。在执行过程中,资源进程可能需要与管理进程或其他资源进程进行通信,以获取必要的数据或同步执行状态。

任务完成:当资源进程完成任务后,它会通过之前设置的通信机制(如管道),将执行结果发送给管理进程。

资源回收:任务完成后,资源进程会返回到进程池中,标记为空闲状态,以便再次接收新的任务。这样,进程池就可以持续地为新任务提供服务,而无需每次都重新创建进程。

三、优点

  1. 减少系统开销:预先创建进程,避免了频繁创建和销毁进程,从而减少了系统的开销。

  2. 提高资源利用率:进程池可以复用进程资源,从而提高了资源利用率。

  3. 简化任务管理:进程池提供了统一的任务分配机制,从而简化了任务管理。

四、应用场景:并发计算、Web服务器、批处理任务等。

五、代码实现

#pragma once

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"task.hpp"

using namespace std;

enum //匿名枚举,用来将错误码转化为错误信息
{
    UsageError = 1,
    ProcnumError,
    PipeError
};

void Usage(const string& proc)
{
    cout << "Usage:" << proc << "proc_num" << endl;
    return ;
}

class Channel //先描述(类)
{
public:
    Channel(int wfd, int id, string& name)
        :_wfd(wfd),_id(id),_name(name)
    { }

    int Wfd(){ return _wfd; }

    string& Name(){ return _name;}

    int Id(){ return _id; }

    void Print()
    {
        cout << "_wfd: " << _wfd;
        cout << ",_id: " << _id;
        cout << ",_name: " << _name << endl;
    }

    ~Channel(){ }
private:
    int _wfd;
    pid_t _id;
    string _name;
};


class Processpol //进程池
{
public:
    Processpol(int proc_num) 
        :_proc_num(proc_num)
    { }

    vector<int> fds; //用来关闭struct file被多个文件描述符指向
    int CreatProcess(work_t work) //1.创建一组子进程、命令行管道
    {
        for(int i = 0; i < _proc_num; i++)
        {
            //父进程需要对管道进行管理,否则会被覆盖
            int pipefd[2]{0}; 
            int n = pipe(pipefd);
            if(n == -1) return PipeError; //创建管道失败
            
            pid_t id = fork(); 
            if(id == 0) //子进程
            {
                if (!fds.empty()) 
                    for (auto& fd : fds) close(fd);

                close(pipefd[1]); //关闭管道的写端
                dup2(pipefd[0], 0); //将标准输入重定向到管道读端
                work(pipefd[0]);  //执行任务 —— 回调函数
                exit(0); //终止
            }
            //父进程
            close(pipefd[0]); //关闭管道的读端

            string name = "channel-" + to_string(i); //管道名字
            _channels.push_back(Channel(pipefd[1], id, name)); 

            fds.push_back(pipefd[1]);
        }
        return 0;
    }

    //2.1.选择一个子进程、管道,来执行任务 —— 父进程'负载均衡'式的给子进程分配任务
    int NextChannel()
    {
        static int next = 0; //静态,不属于任何对象,全局, 用来定位进程池中的各个进程、管道
        int n = next;
        next++;
        next %= _channels.size(); //不可越界
        return n;
    }

    //2.3.发送任务编号到管道写端,以供子进程读取
    void SendTaskCode(int c_code, int t_code)
    {
        cout << "send code " << t_code << " to " << _channels[c_code].Name() << " proc_id " << _channels[c_code].Id() << endl;
        write(_channels[c_code].Wfd(), &t_code, sizeof(t_code)); //父进程将数据写入管道的写端
        sleep(1);
    }
    
    //3.回收资源
    /*因为子进程会继承父进程的文件描述符表,子进程会将父进程中以w方式打开上一文件的fd,
    使得上一文件被多个指针指向,所以关闭父进程写端,此文件的struct file中引用计数--,并未全部关闭*/
    void RecycleProc()
    {
        for(auto& e : _channels)
        {
            close(e.Wfd()); //关闭当前被打开文件(管道)的写端
            int rid = waitpid(e.Id(), NULL, 0); //回收子进程资源
            if(rid > 0) //等待成功
                cout << "wait process " << e.Id() << "sucess" << endl;
            cout << e.Name() << " close done. process " << e.Id() <<"quit now!" << endl; 
        }
    }

    void Debug() //打印子进程、命令行管道相关信息
    {
        for(auto& e : _channels)
        {
            e.Print();
        }
    }

    ~Processpol(){ }

private:
    vector<Channel> _channels; //再组织
    int _proc_num; //预先创建的子进程数量
};

void CtrlProcessPool(Processpol* ptr, int cnt)
{
    while(cnt--)
    {
        int c_code = ptr->NextChannel();
        int t_code = NextCode();
        ptr->SendTaskCode(c_code, t_code);
    }
}

int main(int argc, char* argv[])
{
    //设置随机数生成的种子(起始值),若无srand,则每次程序启动随机数序列均相同,使用当前时间(时间戳)来初始化种子
    srand((uint64_t)time(nullptr)); //unit64_t为无符号64位整数,long long别名

    //输入错误
    if(argc != 2) 
    {
        Usage(argv[0]);
        return UsageError;
    }

    //预设创建的进程数须>0
    int proc_num = stoi(argv[1]);
    if(proc_num <= 0) 
        return ProcnumError;
    
    Processpol* ptr = new Processpol(proc_num); //创建一个进程池
    //1.创建一组子进程、命令行管道
    ptr->CreatProcess(Work);
    ptr->Debug(); //打印子进程、命令行管道相关信息

    //2.控制子进程
    CtrlProcessPool(ptr, 5);
    cout << "task finish......" << endl;

    //3.回收资源: 子进程先要退出(关闭写端),再回收子进程资源
    ptr->RecycleProc();
    
    return 0;
}
#include
#include
#include
#include 

using namespace std;

//函数指针类型
typedef void(*work_t)(int rfd); 
typedef void(*task_t)(int rfd, int id);

//任务
void PrintLog(int rfd, int id)
{
    cout << "rfd: " << rfd << " process: " << id << " is working: " << " printf log task!" << endl;
}

void ReloadConf(int rfd, int id)
{
    cout << "rfd: " << rfd << " process: " << id << " is working: " << " reload conf task!" << endl;
}

void ConnectMysql(int rfd, int id)
{
    cout<< "rfd: " << rfd << " process: " << id << " is working: " << "Connect Mysql task!" << endl;
}

task_t task[3] = {PrintLog, ReloadConf, ConnectMysql };

int NextCode() //2.2.选择要执行任务的编号
{
    return rand() % 3; //生成一个伪随机数
}

void Work(int rfd) //2.4.子进程接受并处理任务
{
    while(true)
    {
        int code = 0; 
        int n = read(0, &code, sizeof(code)); //子进程从管道的读端读取数据
        if(n > 0)  
        {
            if(code >= 3) continue; 
            task[code](rfd, getpid()); 
        }
        else if(n == 0) //情况3,写端关闭,读取到了结尾
        {
            cout << "read ending!" << endl;
            break;
        }
        else 
        {
            cout << "read error!" << endl;
            break;
        }

        sleep(1);
    }
}

问1:为什么匿名管道的写端fd是4、5、6. . .(递增连续数字序列),读端fd一直是3?

问2:如果关闭匿名管道写端一次,就回收资源,这样做能达到目的吗,会产生什么现象?

不能,当父进程连续打开不同的文件,因为子进程会继承父进程的文件描述符表,会导致管道的写端被多个子进程fd指向,所以关闭写端fd一次,并未做到写端被完全关闭,则子进程不会读取到结束位置就退出。

2.5. 命名管道

2.5.1. 概念和原理

  1. 命名管道:也称为FIFO文件,是一种特殊类型的文件,它允许不同的进程之间通过同一个文件路径名进行通信。

  2. 与匿名管道不同,命名管道具有独特的标识符(文件路径),意味着它在文件系统中以文件的形式存在,每个命名管道都有与之对应文件路径作为其标识符,这个标识符使得不同进程,可以通过打开同一个文件路径,来访问同一个命名管道,从而实现进程间的通信。

  3. 命名管道在文件系统上表现为一个特殊类型的文件,但它实际并不存储数据,而是作为数据流动的通道。尽管它在磁盘上有简单的映像,但这个映像的大小始终为0,因为它不会将数据刷新到磁盘上,而是直接在内存中进行数据传输。

2.5.2. 创建 — mkfifo()

int mkfifo(const char* pathname,mode_t mode);

  • 功能:创建一个命名管道。

  • 参数:pathname为路径名(路径+文件名)、mode为权限位,用来指定文件权限(实际文件创建的权限还会受到umask影响)。

  • 返回值:成功时返回0,失败时返回-1,并设置错误码errno以指示错误原。。

2.5.3. 应用场景 — server&client通信

  1. 工作流程

第一步:server进程先会创建命名管道,client进程通过打开与server进程创建的命名管道相同的文件路径名来获取命名管道,此时server进程可以与client进程通过命令行管道进行数据交换。

第二步:client以写w的方式打开命令行管道,server以读r的方式打开命令行管道。

第三步:server、client进程关闭命令行管道,以便释放资源(通过ulink()删除命令行管道)。

  1. 代码实现
#include
#include
#include
#include
#include
#include
#include
 #include 

using namespace std;

#define Mode 0666 //指定命名管道的权限
#define Path "./fifo" //路径名

class Fifo
{
public:
    Fifo(const string& path) 
        :_path(path)
    {
        umask(0);
        int n = mkfifo(Path, Mode); //创建命名管道
        if(n == 0) 
        {
            cout << "mkfifo success!" << endl;
        }
        else
        {
            cout << "mkfifo failed! errno: " << errno << "errdesc: " << strerror(errno) << endl; 
        }
    }

    ~Fifo() 
    {
        int n = unlink(Path); //删除命名管道
        if(n == 0)
        {
            cout << "remove file success!" << endl;
        }
        else
        {
            cout << "remove file failed! errno: " << errno << "errdesc: " << strerror(errno) << endl; 
        }

    }

private:
    string _path;
};
#include"name_pipe.hpp"

int main()
{
    //1.创建命名管道
    Fifo fifo(Path);

    //2.以读的方式打开命名管道
    int fd = open(Path, O_RDONLY);
    if(fd <= 0)
    {
        cout << "open failed! errno: " << errno << "errdesc: " << strerror(errno) << endl;
        return 1;
    }
    cout << "open success!" << endl;

    //3.从命名管道中读取数据
    char buffer[128];
    while(1)
    {
        int n = read(fd, buffer, sizeof(buffer));
        if(n > 0)
        {
            buffer[n] = '';
            cout << "client say: " << buffer << endl;
        }
        else if(n == 0)
        {
            cout << "client quit! me to...." << endl;
            break;
        }
        else
        {
           cout << "read failed! errno: " << errno << "errdesc: " << strerror(errno) << endl;
           break;
        }
    }
}

#include"name_pipe.hpp"

int main()
{
    //1.以写的方式打开命名管道
    int fd = open(Path, O_WRONLY);
    if(fd <= 0)
    {
        cout << "open failed! errno: " << errno << "errdesc: " << strerror(errno) << endl;
        return 1;
    }
    cout << "open success!" << endl;

    //2.向命名管道中写入数据
    string str;
    while(1)
    {
        getline(cin, str);
        if(str == "quit")
            break;
        int n = write(fd, str.c_str(), sizeof(str) - 1);
        if(n == -1)
        {
            cout << "write failed! errno: " << errno << "errdesc: " << strerror(errno) << endl;
            break;
        }
    }
}

2.6. 命名管道与匿名管道的区别

  1. 创建与打开方式、存在形式

匿名管道:由pipe函数创建,同时管道的两端已经被被打开了,并返回调用进程两个fd,分别用于读写操作。它只存在与内存中,无文件名。

命名管道:由mkfifo函数创建,需要手动调用open打开。在文件系统中有对应的文件名(路径)。
2. 通信范围

匿名管道:具有血缘关系的两个进程间的通信。

命名管道:任意两个进程之间的通信,只要这两个进程可以访问到命名管道所在的文件系统路径。

  1. 生命周期

匿名管道:其生命周期随进程(父子进程)的结束而结束。

命名管道:其生命周期与文件系统中的文件相同,当文件被删除时,命名管道的生命周期结束,如果文件系统中的命名管道还在,它就可以被多个进程同时打开和访问。

3. System V 共享内存

3.1. 概念和原理

  1. 共享内存概念:是一种高效且快速的进程间通信的方式,它允许多个进程访问同一块物理内存区域,从而实现数据的共享和交换。

💡Tips:共享内存的生命周期随内核,管道的生命周期随进程!

  1. 共享内存进行通信的流程:创建共享内存 -> 构建映射 -> 进程通信 -> 解除映射 -> 删除共享内存。

系统中有许多进程进行通信,所以共享内存可以在OS中同时存在多个,则OS需要管理所有被创建的共享内存,先描述,再组织。 为了实现进程间通信,得让不同进程看到同一个共享内存,就需要在OS中给共享内存提供唯一性的标识(key值)。

struct shmid_ds {
	struct ipc_perm     shm_perm;   /* operation perms */
	int         shm_segsz;  /* size of segment (bytes) */
	__kernel_time_t     shm_atime;  /* last attach time */
	__kernel_time_t     shm_dtime;  /* last detach time */
	__kernel_time_t     shm_ctime;  /* last change time */
	__kernel_ipc_pid_t  shm_cpid;   /* pid of creator */
	__kernel_ipc_pid_t  shm_lpid;   /* pid of last operator */
	unsigned short      shm_nattch; /* no. of current attaches */
	unsigned short      shm_unused; /* compatibility */
	void            *shm_unused2;   /* ditto - used by DIPC */
	void            *shm_unused3;   /* unused */
};

struct ipc_perm{
	__kernel_key_t  key;  //共享内存的唯一性标识
	__kernel_uid_t  uid;
	__kernel_gid_t  gid;
	__kernel_uid_t  cuid;
	__kernel_gid_t  cgid;
	__kernel_mode_t mode;
	unsigned short  seq;
};

3.2. 共享内存函数

3.3. shmget — 创建共享内存

int shmget(key_t key, size_t size, int shmflg);

  1. 功能:创建一个新的共享内存 或 获取一个已存在的共享内存。

  2. 返回值:成功时,返回一个非负整数,表示共享内存的标识符(shmid);失败时,返回-1,并设置错误码errno以指示错误原因。

  3. 参数:key: 共享内存的键值, 用来唯一性标识共享内存; size: 共享内存的大小, 以字节为单位(共享内存大小通常以4KB为基本单位,建议申请大小为4KB的整数倍); shmflg: 标志位,用来指定函数行为和共享内存权限。

一、key

  1. key:是一个键值,用来在OS中唯一标识一个共享内存。

  2. key值的作用:区分共享内存、实现进程间通信。

区分共享内存:key值确保了在OS中每个共享内存都有一个唯一的标识,使得不同的共享内存可以在OS被区分开来,避免了不同进程误用其他进程的共享内存。

实现进程间通信:由于key值的唯一性,多个进程可以通过使用相同的key值来识别、访问同一个共享内存,从而实现进程间通信。这种通信方式,进程可以直接读写这块内存,避免了数据在进程间的复制,提高了通信效率。

  1. key值的生成:在创建共享内存时,通常需要程序员提供一个key值,为了避免与OS中现有的共享内存key值冲突,一般不会自己随意取key值,而是通过系统调用接口ftok来生成唯一的key值,但频繁调用ftok,会出现键值冲突。

key_t ftok(const char* pathname, int proj_id);

  1. 功能:将一个已经存在的路径名pathname和一个项目标识符proj_id(非0整数),通过特定算法(数学运算),转化为一个唯一的键值,用来标识共享内存或其他IPC对象(消息队列、信号量集等),这个key会被填充到维护共享内存的数据结构中。

  2. 参数:pathname,指向文件名的指针,这个文件必须存在于文件系统中。 pro_id:是一个用户自定义的项目标识符,用于进一步区分同一文件的不同IPC资源,通常是8位整数(0~255)。

  3. 返回值:成功时返回一个具有唯一性的key值;文件不存在,失败返回-1,并设置错误码errno以指示错误原因。

  4. 使用场景:当多个进程需要共享同一块内存时,可以使用相同的文件路径和项目标识来调用ftok函数,从而生成相同的key值,然后,它们可以使用这个key值调用shmget函数,就可以访问到同一块共享内存。

为什么key值要让用户传入呢?

只要通信双方事先约定好了参数,两个进程可以基于相同的文件路劲和项目标识符来生成同一个key值,当它们分别调用shmget函数并传入相同的key,就能够看到同一个共享内存,从而实现进程间通信。如果key是由内核设定,进程之间不知道对方创建共享内存的key值,因为进程具有独立性,从而无法建立通信。

eg:进程A创建共享内存,其key值如果由OS自动生成,进程具有独立性,进程B无法知道进程A创建的共享内存的key值,因此进程B无法访问进程A创建的共享内存,从而无法建立通信。

二、shmflg

  1. 概念:是一组标志位,用于指定shmget函数的行为和设置共享内存的权限。

3.4. shmat — 进程挂接共享内存

void* shmat(int shmid,const void* shmaddrr,int shmflg);

  1. 功能:将共享内存连接到进程地址空间,从而构建映射。

  2. 返回值:成功时,返回一个共享内存映射到地址空间中起始位置的地址(虚拟地址);失败时,返回-1并设置错误码errno以指示错误原因。

  3. 通过shmaddr的返回值,以及在shmget中设定的共享内存大小,就可以访问共享内存中任意位置的数据。

  4. 参数:shmid:共享内存的标识符;shmaddr:指定映射到地址空间的具体起始位置,通常设置为NULL让系统自动选择一个虚拟地址; shmflg:控制连接的标志位。

3.5. shmdt — 断开共享内存连接

int shmdt(const void* shmaddr);

  1. 功能:断开共享内存与调用进程的地址空间的连接,从而解除映射,并没有直接删除共享内存。

  2. 参数shmaddr:之前通过shmat连接共享内存的起始虚拟地址。

  3. 返回值:成功时,返回0;失败时,返回-1并设置错误码errno以指示错误原因。

3.6. shmctl — 删除共享内存

int shmctl(int shmid,int cmd,struct shmid_ds* buf);

  • 功能:用来控制共享内存的各种属性,如:获取属性、设置属性、删除共享内存。

  • 返回值:成功时,返回0;失败时,返回-1并设置错误码errno以指示错误原因。

  • 参数:shmid:共享内存的标识符;cmd:要执行的操作。buf:指向一个保存着共享内存的模式状态和访问权限的数据结构shmid_ds,用于传递或接收共享内存的属性信息。

3.7. 应用场景 — server&client通信

#pragma once

#include
#include
#include
#include
#include
#include
#include
#include
#include


using namespace std;

#define PathName "/root/110" //在文件系统中存在的文件路径
#define Proj_Id 125 
#define Size 4096 //共享内存大小,通常以4kb为基本单位,建议申请的大小为4kb的整数倍

const string ToHex(key_t key) //将整数转化为十六进制
{
    char buffer[256];
    snprintf(buffer, sizeof(buffer), "0x%x", key);
    return buffer;
}

key_t GetShmKeyorDie() //获取key值
{   
    int key = ftok(PathName, Proj_Id);
    if(key == -1) 
    {
        cerr << "ftok failed, errno: " << errno << "error reason: " << strerror(errno) << endl;
        exit(1);
    }
    return key;
}

int CreatShmorDie(key_t key, int size, int flag) //1.创建共享内存
{
    int shmid = shmget(key, size, flag);
    if(shmid == -1)
    {
        cerr << "shmget failed, errno: " << errno << "error reason: " << strerror(errno) << endl;
        exit(2);
    }
    return shmid; //共享内存的标识符
}

//Tips:使用共享内存通信,一定是一个进程创建新的共享内存,另一个进程直接获取共享内存
int CreatShm(key_t key)  //服务端,创建共享内存
{
    umask(0);
    return CreatShmorDie(key, Size, IPC_CREAT|IPC_EXCL|0666); //设置权限
}

int GetShm(key_t key) //客户端,使用共享内存
{
    return CreatShmorDie(key, Size, IPC_CREAT);
}

void* AttShm(int shmid) //2.进程挂接共享内存,构建映射
{
    void* addr = shmat(shmid, nullptr, 0); //shmaddr为null,由OS自动生成虚拟地址
    if(addr == NULL)
    {
        cerr << "shmat failed, errno: " << errno << "error reason: " << strerror(errno) << endl;
        return nullptr;
    }
    return addr;
}

void DetachShm(void* addr) //4.断开共享内存的连接,解除映射
{
    int n = shmdt(addr); 
    if(n == -1)
        cerr << "shmdt failed, errno: " << errno << "error reason: " << strerror(errno) << endl;
}

void DelShm(int shmid) //5.删除共享内存
{
    int n = shmctl(shmid, IPC_RMID, nullptr);
    if(n == -1)
        cerr << "shmctl failed, errno: " << errno << "error reason: " << strerror(errno) << endl;
    else
        cout << "shmctl delete success!" << endl;
}

void ShmDebug(int shmid)  //获取共享内存的属性信息
{
    struct shmid_ds shmds; 
    int n = shmctl(shmid, IPC_STAT, &shmds);
    if(n == -1)
        cerr << "shmctl failed, errno: " << errno << "error reason: " << strerror(errno) << endl;
    else
    {
        cout << "nattch" << shmds.shm_nattch << endl;
        cout << "key" << shmds.shm_perm.__key << endl;
        cout << "attch time" << shmds.shm_atime << endl;
        cout << "detach time" << shmds.shm_dtime << endl;
    }
}
#include"Shm.hpp"
#include"name_pipe.hpp"

int main()
{
    //获取key值
    int key = GetShmKeyorDie(); 
    cout << "key: " << ToHex(key) << endl;

    //1.创建共享内存
    int shmid = CreatShm(key);
    cout << "shmid: " << shmid << endl;

    //2.进程连接到共享内存,构建映射
    char* addr = (char*)AttShm(shmid);

    //3.进程间通信 
    //共享内存不提供进程间协同的任何机制(同步、互斥机制,用来保护共享资源)
    Fifo fifo(Path); //管道内部自带同步、互斥机制
    Sysn sn; 
    sn.OpenReadorDie(); //以只读的方式打开管道
    for(; ;)
    {
        if(sn.Wait()) //等待客户端写完
        {
            cout << "shm content: " << addr << endl; 
            sleep(1);
        }
        else break; 
    }

    //4.断开共享内存的连接,解除映射
    DetachShm(addr);

    //5.删除共享内存
    DelShm(shmid);

    return 0;
}
#include"Shm.hpp"
#include"name_pipe.hpp"

int main()
{
    //获取key值
    key_t key = GetShmKeyorDie();
    cout << "key: " << ToHex(key) << endl;

    //1.获取共享内存
    int shmid = GetShm(key);
    cout << "shmid: " << shmid << endl;

    //2.进程连接到共享内存,构建映射
    char* addr = (char*)AttShm(shmid);

    //3.进程间通信 
    Sysn sn;
    sn.OpenWriteorDie(); //以只写的方式打开管道
    memset(addr, '0', 1);
    for(char ch = 'A'; ch < 'Z'; ch++)
    {
        addr[ch - 'A'] = ch;
        sleep(1);
        sn.Wakeup(); //写入完成,唤醒服务端
    }

    //4.断开共享内存的连接,解除映射
    DetachShm(addr);

    //5.删除共享内存
    DelShm(shmid);

    return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include



using namespace std;

#define Mode 0666 //指定命名管道的权限
#define Path "./fifo" //路径名

class Fifo
{
public:
    Fifo(const string& path) 
        :_path(path)
    {
        umask(0);
        int n = mkfifo(Path, Mode); //创建命名管道
        if(n == 0) 
        {
            cout << "mkfifo success!" << endl;
        }
        else
        {
            cout << "mkfifo failed! errno: " << errno << "errdesc: " << strerror(errno) << endl; 
        }
    }

    ~Fifo() 
    {
        int n = unlink(Path); //删除命名管道
        if(n == 0)
        {
            cout << "remove file success!" << endl;
        }
        else
        {
            cout << "remove file failed! errno: " << errno << "errdesc: " << strerror(errno) << endl; 
        }

    }

private:
    string _path;
};

class Sysn //在共享内存中使用管道(包含同步、互斥机制),保护共享资源
{
public:
    Sysn():wfd(-1),rfd(-1)
    { }

    void OpenWriteorDie() //以只写的方式打开管道
    {
        wfd = open(Path, O_WRONLY);
        if(wfd < 0)
            exit(4);
    }

    void OpenReadorDie() //以只读的方式打开管道
    {
        rfd = open(Path, O_RDONLY);
        if(rfd < 0)
            exit(5);
    }

    bool Wait() //服务福端等待客服端写入完成
    {
        int flag = true;
        int c = 0;
        int n = read(rfd, &c, sizeof(c));
        if(n == sizeof(c))
            cout << "Server wake, begin read shm!" << endl;
        else if(n == 0)
            flag = false;
        else
            flag = false;

        return flag;
    }

    void Wakeup() //客户端写完,唤醒服务端
    {
        int c = 0;
        int n = write(wfd, &c, sizeof(c));
        if(n == -1)
        {
            cerr << "write failed" <<  endl;
            exit(3);
        }
        cout << "Server Wake......" << endl;
    }

private:
    int wfd;
    int rfd;
};

3.8. 命令行查看共享内存

  1. ipcs
  • ipcs:是显示和管理系统中进程间通信(IPC)资源的工具,包括共享内存、消息队列、信号量集。

  1. 选项:-m:显示共享内存相关的信息、-q:显示消息队列相关的信息、-s:查看信号量级相关的信息。

  1. key和shmid的区别:都是确保共享内存的唯一性和可访问性的重要机制。

key在内核中用于标识共享内存,确保其在系统内的唯一性,即:key在内核层面上保证了共享内存的唯一性。

shmid是在成功创建共享内存后由系统返回,用于在用户层面上唯一地标识共享内存,并作为后续对共享内存操作的参数,即:shmid在用户层面上提供了对共享内存的唯一标识和操作接口。

  1. ipcrm [-m|-q|-s] shmid
  • 功能:删除已存在的IPC资源对象,包括共享内存、消息队列、信号量集。

3.9. 优缺点

  1. 优点:共享内存是所有进程间通信(IPC)方式中速度最快的。

减少拷贝次数:在管道通信中,数据通常要经过至少两次拷贝,数据从一个进程的缓冲区写入管道,然后从管道中读取到另一个进程的缓冲区中,这涉及两次数据在不同内存区域之间的复制操作。在共享内存中允许多个进程直接访问同一块内存区域,当一个进程将数据写入到共享内存中,其他进程可以立即看到,最多只会经历一次从进程的用户空间到共享内存的拷贝。

直接访问:进程可以直接对共享内存进行读写操作,无需通过OS进行数据中转,这大大减少了内核参与数据传输的开销,提高了通信效率。

  1. 缺点:共享内存不提供进程间协同的任何机制。

  2. 这会导致多个进程同时访问共享内存区域时,出现数据不一致和数据竞争等问题。因为没有内置的同步和互斥手段,不同进程可能在不可预测的时间点对共享内存进行读写操作,从而破坏数据的完整性。例如,一个进程正在写入数据时,另一个进程可能同时在读取,可能会读取到不完整的数据;或者两个进程同时写入,可能会导致数据覆盖混乱。所以需要额外的机制(管道、信号量等)来保证数据的完整性和一致性。

进程间协同机制:是确保多个进程在访问公共资源时能够正确地同步、互斥以及协调彼此的操作。协调彼此的操作则涉及更复杂的交互,例如一个进程等待另一个进程完成特定任务后再继续执行。

管道在操作系统中自带协同机制。如:管道的读写操作具有原子性,一次读写要么全部完成,要么全部失败,保证了数据的完整性。同时,阻塞机制也起到了协同的作用,当缓冲区满时,写操作被阻塞,防止数据溢出;当缓冲区为空时,读操作被阻塞,在一定程度上实现了同步和互斥的效果。

4. 消息队列

4.1. 原理与概念

  1. 消息队列:一种进程间通信(IPC)的机制,允许多个进程通过发送和接收带有类型的数据块(消息)进行通信,这些消息在队列中按照先进先出(FIFO)的顺序存储。

发送进程将消息添加到队列的末尾,接收进程从队列的头部读取信息。

💡Tips:消息队列的生命周期随内核,即:System V IPC资源的生命周期随内核!!!

  1. 特点

支持异步通信:是指在进行数据传输时,发送方和接收方无需同步,即:它们可以独立的工作,彼此之间无需等待对方的回应。如:发送方发送消息后继续执行,无需等待接收方的回应,接收方可以在任何时间接收消息,同时会触发一个事件来通知发送方,从而达到异步通信的目的。

提供了可靠的消息传递机制,确保了数据不会丢失。如:即使接收方暂时无法处理消息,消息也会保存到队列中,直到接收方读取成功。

灵活的消息格式:消息队列中的消息可以包含不同类型的数据,如:文本、二进制等。

  1. 基本组件:每个消息队列都有唯一的标识符(msgqid)、消息队列中每个消息都包含一个类型字段和数据字段。

消息中的类型字段可以用于标识消息的类型,以便接收进程可以根据类型来筛选和处理消息,而数据字段则包含实际要传递的数据。

  1. 发送方和接收方通过使用相同的key值来创建或获取消息队列,它们就可以访问到同一个消息队列,从而实现进程间通信。消息队列特别适用于异步消息传递和任务队列等场景。

4.2. 消息队列函数

  1. 创建或获取消息队列 —— msgget函数

key_t key = ftok(".", MSG_KEY);
int msgid = msgget(key, IPC_CREAT|0666);
  1. 发送消息到消息队列 — msgsnd函数

Message msg; //结构体,消息包含类型和数据
msg.mtype = 1; // 消息类型为 1
strcpy(msg.mtext, "Hello, World!"); //消息数据
if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) {
    perror("msgsnd");
    exit(1}
  1. 从消息队列接收消息 — msgrcv函数

Message msg;
if (msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0) == -1) {
    perror("msgrcv");
    exit(2);
}
printf("Received message: %s
", msg.mtext);
  1. 控制消息队列

if (msgctl(msgid, IPC_RMID, NULL) == -1) {
    perror("msgctl");
    exit(3);
}
struct msqid_ds {
    struct ipc_perm msg_perm;     /* Ownership and permissions */
    time_t msg_stime;    /* Time of last msgsnd(2) */
    time_t msg_rtime;    /* Time of last msgrcv(2) */
    time_t msg_ctime;    /* Time of last change */
    unsigned long __msg_cbytes; /* Current number of bytes in
                                                queue (nonstandard) */
    msgqnum_t msg_qnum;     /* Current number of messages
                                                in queue */
    msglen_t msg_qbytes;   /* Maximum number of bytes
                                                allowed in queue */
    pid_t msg_lspid;    /* PID of last msgsnd(2) */
    pid_t msg_lrpid;    /* PID of last msgrcv(2) */
};

The ipc_perm structure is defined as follows (the highlighted fields are settable using IPC_SET):
           struct ipc_perm {
        key_t  __key;       /* Key supplied to msgget(2) */
        uid_t uid;         /* Effective UID of owner */
        gid_t gid;         /* Effective GID of owner */
        uid_t cuid;        /* Effective UID of creator */
        gid_t cgid;        /* Effective GID of creator */
        unsigned short mode;        /* Permissions */
        unsigned short __seq;       /* Sequence number */
};

5. System V中IPC资源在内核中的设计

一、IPC资源的管理

  1. 在OS中,通过维护一个数组来管理不同的IPC资源,如:共享内存、消息队列、信号量。

  2. 每种IPC资源都有其特定的数据结构(如:shmid_ds、msqid_ds、semid_ds等),这些数据结构的第一个成员都是以ipc_perm结构体作为开头。

二、多态实现

  1. ipc_perm包含了IPC资源共有的属性,内核层面上称为kern_ipc_perm、用户层面上称为ipc_perm,所以可以将ipc_perm视为基类,不同的IPC资源数据结构(如:shmid_ds、msqid_ds等)作为ipc_perm的子类,扩展了额外的特定于该资源的属性。

  2. 通过将数组的元素类型定为ipc_perm*,OS就可以实现对不同IPC资源的统一管理和访问。当需要访问特定资源的额外属性时,可以通过强制类型转化来实现,如:(shmid_ds*)array[i]->额外属性。

三、资源的标识和访问

  1. 每个IPC资源在创建时都会分配唯一的标识符(如:shmid、msgid等),这个标识符实际上就是数组的下标。

  2. 标识符的增长是线性递增的,即使资源被释放,新的资源也会获得比上一个资源更大的标识符,为了避免数组越界,OS提供了回绕机制。

6. 信号量

6.1. 储备知识

  1. 在多执行流场景下,共享资源可能同时被多个执行流尝试访问、修改,如果不加以保护,这可能会导致数据不一致、资源竞争和死锁等问题。

常见的保护机制主要包括同步和互斥机制。同步机制确保执行流按照预定的顺序进行交互,互斥机制确保共享资源在任何一个时刻只能被一个执行流访问。

  1. 临界资源:被保护起来且任何时刻只允许一个执行流访问的公共资源,称为临界资源。eg:一个全局变量在多个线程同时读写时,如果不加以保护,可能会出现数据错误,这个全局变量就称为临界资源。

  2. 临界区:访问临界资源的代码称为临界区。 非临界区:除临界区之外的代码称为非临界区。

程序员需要特别关注和保护临界区,以确保在任何时刻只有一个执行流,能够进入临界区访问临界资源,以防止其他执行流同时访问。

  1. 保护临界资源,本质是保护临界区,确保在任何时刻只有一个执行流能够访问临界区,从而保护数据的一致性和正确性。

  2. 原子性:一个操作被认为是原子的,此操作要么完全执行成功,要么完全不执行,不存在中间状态,即:此操作不可分割(一旦开始执行,它必须连续执行完成,中途不能被打断),不能被其他执行流中断。

在并发编程中,原子性用于确保多个线程或进程对共享资源进行操作,不会导致数据不一致、不确定的结果。

6.2. 原理与概念

信号量在进程间通信IPC中扮演着重要的角色,尽管它的目的不是直接传递字符串或数据内容,而是通过维护一个计数器来实现对共享资源的协同访问。

  1. 信号量:是一种用于控制多个进程对共享资源访问的同步机制,主要用于解决互斥和同步问题,确保在任何时候只有有限数量的进程可以访问特定的资源。
  • 本质是一个整形计数器,表示可用的临界资源数目。
  1. 当进程或线程需要访问临界资源时:都必须先申请信号量 -> 再进行访问 -> 最后释放信号量。
  2. 信号量核心操作:PV操作,是原子性操作,既可以改变信号量值,又可以用于保护信号量这个共享资源,确保多个进程能够正确地协调对其他共享资源的访问,实现对进程间同步和互斥的控制。

P操作:用于申请临界资源。如果信号量值>0,则将其-1,并允许进程继续执行;如果信号量值=0,则进程被阻塞,等待其他进程释放资源。

V操作:用于释放临界资源。将信号量值+1。

本文地址:https://www.vps345.com/12310.html

搜索文章

Tags

docker 容器 运维 java-rabbitmq java 智能驾驶 BEVFusion Ubuntu 服务器带宽 上行带宽 上行速率 什么是上行带宽? PV计算 带宽计算 流量带宽 macos windows linux 服务器 嵌入式硬件 #docker #centos #容器 网络 远程连接 vscode pytorch tensorflow #windows #自动化 #运维 ubuntu 无人机 机器人 github 流量攻击 DDOS攻击 服务器被攻击怎么办 源IP ide AI Dify 大模型应用 CC攻击 攻击怎么办 安全 ubuntu24.04 todesk 云原生 c# 开发语言 网络协议 网络安全 ssh漏洞 ssh9.9p2 CVE-2025-23419 ai nlp ssh remote-ssh centos 人工智能 python c++ php #git #ssh #windows 具身智能 强化学习 华为 边缘计算 conda ROS 自动驾驶 经验分享 wireshark #linux #命令 #网络 IPMI ollama llm #macos #EasyConnect 远程工作 harmonyos react native tomcat 部署 #harmonyos #android #ios debian wps 安卓 语言模型 AI大模型 DeepSeek agi micropython esp32 单片机 mqtt 物联网 #ubuntu #linux 深度学习 #java #华为 数据库 mysql adb 自动化 n8n LLM 大模型面经 大模型 职场和发展 Deepseek 大模型学习 中间件 web安全 可信计算技术 安全架构 网络攻击模型 存储维护 NetApp存储 EMC存储 虚拟机 AIGC comfyui comfyui教程 网络药理学 生信 分子对接 autodock mgltools PDB PubChem kylin r语言 数据挖掘 数据可视化 数据分析 机器学习 快捷键 旋转屏幕 自动操作 #javascript #开发语言 #ecmascript flutter Google pay Apple pay #jenkins #人工智能 #云原生 ddos CosyVoice 持续部署 jenkins Playwright pythonai PlaywrightMCP prometheus grafana svn zabbix 3d golang 算法 开源 dity make intellij-idea Linux 维护模式 #区块链 #智能合约 服务器安全 网络安全策略 防御服务器攻击 安全威胁和解决方案 程序员博客保护 数据保护 安全最佳实践 Agent llama CrewAI bash 编辑器 pip html http json css django fastapi 后端 智能路由器 自然语言处理 小程序 ssl git web3 区块链 区块链项目 华为云 华为od YOLO gpu算力 MVS 海康威视相机 Java进程管理 DevOps自动化 脚本执行 跨平台开发 远程运维 Apache Exec JSch rag ragflow 大模型部署 springsecurity6 oauth2 授权服务器 前后端分离 DevEco Studio HarmonyOS OpenHarmony 真机调试 unity GameFramework HybridCLR Unity编辑器扩展 自动化工具 性能优化 YOLOv8 NPU Atlas800 A300I pro MCP onlyoffice 在线office 游戏引擎 学习 c语言 计算机网络 智能合约 压力测试 哈希算法 MacMini Mac 迷你主机 mini Apple 鸿蒙 混合开发 环境安装 JDK linux环境变量 阿里云 云计算 spring boot spring bug 运维开发 gnu unix iot 计算机视觉 opencv 目标检测 rk3588 npu rknn-toolkit2 群晖 低代码 1024程序员节 单例模式 chatgpt 飞牛NAS 飞牛OS MacBook Pro kvm qemu libvirt 课程设计 AI编程 visual studio code 负载均衡 Cline ESXi Dell HPE 联想 浪潮 GCC crosstool-ng 电路仿真 multisim 硬件工程师 硬件工程师学习 电路图 电路分析 仪器仪表 typescript 微信 设计模式 nvcc cuda A100 nginx prompt AI提示词优化 搜索引擎 程序员 SSH Linux Xterminal rtsp h.265 vite Svelte 实时音视频 实时互动 技能大赛 qt linuxdeployqt 打包部署程序 appimagetool 爬虫 open webui dash 正则表达式 网络工程师 华为认证 stm32 tcp/ip 硬件工程 Qwen3 qwen3 32b vllm 本地部署 milvus 向量数据库 word图片自动上传 word一键转存 复制word图片 复制word图文 复制word公式 粘贴word图文 粘贴word公式 Kylin-Server 国产操作系统 服务器安装 CUDA PyTorch aarch64 编译安装 HPC android studio 交互 websocket android 银河麒麟 信创国产化 达梦数据库 mybatis appium 软件测试 自动化测试 功能测试 程序人生 apache pdf xml uniapp vue ansible playbook 自动化运维 vmamba mamba ffmpeg 音视频 视频编解码 redis uni-app m3u8 HLS 移动端H5网页 APP安卓苹果ios 监控画面 直播视频流 #激光雷达 #览沃 #ubuntu22.04 #ros2 #大疆 kubernetes k8s 程序 编程 内存 性能分析 yolov5 postgresql 动态库 GCC编译器 -fPIC -shared elasticsearch dify dify部署 rust 前端 okhttp springboot容器部署 springboot容器化部署 微服务容器化负载均衡配置 微服务容器多节点部署 微服务多节点部署配置负载均衡 ruoyi 交换机 硬件 设备 GPU PCI-Express iventoy VmWare OpenEuler pgpool gpt transformer chrome chrome devtools selenium chromedriver mac 笔记 DevOps 大数据 软件交付 数据驱动 应用场景 数据安全 Docker Docker Compose Kubernetes rpc 远程过程调用 Windows环境 vue.js javascript 服务器配置 fpga开发 图像处理 其他 deepseek 截图 录屏 gif 工具 searxng SenseVoice 远程桌面 嵌入式 linux驱动开发 arm开发 鸿蒙系统 hdc 鸿蒙NEXT 进程信号 智能体开发 三维重建 oceanbase 传统数据库升级 银行 MS Materials rc.local 开机自启 systemd 麒麟 FunASR ASR LVS 蓝桥杯 openjdk Claude Desktop Claude MCP Windows Cli MCP 计算机学习路线 编程语言选择 王者荣耀 HTTP 服务器控制 ESP32 DeepSeek WSL2 上安装 Ubuntu openssl 计算机外设 数据集 MobaXterm 文件传输 node.js 华为机试 C++ Java Python LLM Web APP Streamlit HTTP状态码 客户端错误 服务器端错误 API设计 智能手机 大模型压力测试 EvalScope 多线程服务器 Linux网络编程 硬件架构 系统架构 EasyConnect glibc UOS 开机自启动 桌面快捷方式 进程间通信 vue3 安全威胁分析 安全性测试 AutoDL Qwen2.5-VL servlet Docker Hub docker pull 镜像源 daemon.json rabbitmq 知识图谱 大模型教程 科技 Windows ai工具 语音识别 视频平台 录像 RTSP 视频转发 性能测试 视频流 存储 企业微信 oracle 关系型 分布式 监控 安卓模拟器 GPU训练 wsl 多线程 进程 pthread 系统 webpack 策略模式 mac安装软件 mac卸载软件 mac book 鲲鹏 昇腾 金融 openEuler 欧拉系统 嵌入式Linux IPC FTP 服务器 llama3 Chatglm 开源大模型 chatbox 麒麟OS 软件工程 软件构建 burpsuite 安全工具 mac安全工具 burp安装教程 渗透工具 开发工具 基础指令 指令 LLMs GenAI LLM 推理优化 LLM serving langchain deep learning 政务 分布式系统 监控运维 Prometheus Grafana pygame 相机 cron crontab日志 word microsoft coze SSE mcu EVE-NG 操作系统 openwrt USB网络共享 主从复制 Portainer搭建 Portainer使用 Portainer使用详解 Portainer详解 Portainer portainer 换源 国内源 Debian Kali 渗透 #embedding #网络 #dify MCP server agent C/S 驱动开发 嵌入式实习 DNS dubbo 三级等保 服务器审计日志备份 大大通 第三代半导体 碳化硅 elk 安全漏洞 信息安全 信息与通信 飞腾处理器 国产化 YOLOv12 神经网络 docker desktop image MLLMs VLM gpt-4v 毕设 maven GIS 遥感 WebGIS pycharm 架构 个人开发 程序化交易 量化交易 高频交易 jvm muduo 网络库 云计算面试题 yum apt ui HarmonyOS Next arkUI arkTs SecureCRT 环境部署 工作流 workflow 信号处理 flash-attention 报错 计算生物学 生物信息学 生物信息 基因组 ShapeFile GeoJSON Nginx fiddler Apache Flume 数据采集 安装部署 配置优化 高级功能 大数据工具集成 工作流自动化工具 bushujiaocheng 部署教程 算家云 AI算力 租算力 到算家云 kind xrdp 环境迁移 微信开放平台 flask 微信公众平台 微信公众号配置 matlab wsl2 CH340 串口驱动 CH341 uart 485 harmonyOS面试题 iNode Macos 缓存 eureka spring cloud 知识库 本地化部署 网页服务器 web服务器 visualstudio Autoware 辅助驾驶 FTP服务器 学习方法 stm32项目 系统安全 统信 虚拟机安装 Deepseek-R1 私有化部署 推理模型 hadoop big data 前端框架 Cursor Bug解决 Qt platform OpenCV 流程图 mermaid ros 树莓派项目 rpa ragflow 源码启动 devops 防火墙 ufw iBMC UltraISO 集成学习 集成测试 jupyter 云服务器 web3.py tcpdump element-ui 上传视频并预览视频 vue上传本地视频及进度条功能 vue2选择视频上传到服务器 upload上传视频组件插件 批量上传视频 限制单个上传视频 gitee gitee go cursor latex RTX5090 torch2.7.0 Ollama RAGFlow 本地知识库部署 DeepSeek R1 模型 环境配置 Vmamba 线程 电脑 卷积神经网络 镜像 nohup 异步执行 ACL 流量控制 基本ACL 网络管理 规则配置 游戏 H3C 大模型入门 服务器无法访问 ip地址无法访问 无法访问宝塔面板 宝塔面板打不开 https 反向代理 外网访问 内网穿透 端口映射 Windsurf 话题通信 服务通信 Chatbox mariadb Claude 计算机系统 网络编程 cmake react.js 网络结构图 yaml Ultralytics 可视化 QQ bot 程序员创富 gcc centos 7 安装MySQL 物理地址 页表 虚拟地址 RAG Multi-Agent 百度 paddlepaddle 雨云 NPS IMM 统信操作系统 游戏服务器 Minecraft 宝塔面板 数据库架构 数据管理 数据治理 数据编织 数据虚拟化 代码调试 ipdb tidb GLIBC jar windows 服务器安装 glm4 umeditor粘贴word ueditor粘贴word ueditor复制word ueditor上传word图片 电子信息 通信工程 毕业 lsb_release /etc/issue /proc/version uname -r 查看ubuntu版本 nvm node vim 测试工具 微服务 数据结构 eclipse Linux Vim IPv4/IPv6双栈 双栈技术 网路规划设计 ensp综合实验 IPv4过渡IPv6 IPv4与IPv6 烟雾检测 yolo检测 消防检测 NAS Termux Samba Dell R750XS triton 模型分析 UOS1070e webrtc NVML nvidia-smi mcp mcp协议 go-zero mcp服务器 vmware tools VMware 生成对抗网络 抽象工厂模式 sequoiaDB 华为鸿蒙系统 ArkTS语言 Component 生命周期 条件渲染 Image图片组件 RockyLinux 迁移 openeuler list 远程 命令 执行 sshpass 操作 perl arm Alist rclone mount 挂载 网盘 论文笔记 开源软件 记账软件 springboot 容器部署 udp HCIE 数通 RAID RAID技术 磁盘 open Euler dde deepin 统信UOS 智能硬件 sql 游戏程序 Java Applet URL操作 服务器建立 Socket编程 网络文件读取 grub 版本升级 扩容 Pyppeteer Spring AI 大模型应用开发 AI 应用商业化 trae cudnn nvidia sdkman nftables vmware chromium dpi 抓包工具 k8s部署 MySQL8.0 高可用集群(1主2从) GPUGEEK 考研 线程互斥与同步 框架搭建 RustDesk自建服务器 rustdesk服务器 docker rustdesk 自定义客户端 SAS 常用命令 文本命令 目录命令 opensearch helm 弹性计算 裸金属服务器 弹性裸金属服务器 虚拟化 服务器扩容没有扩容成功 ftp服务 文件上传 PyQt PySide6 ipython 软件需求 UEFI Legacy MBR GPT U盘安装操作系统 archlinux kde plasma 实时内核 Obsidian Dataview 5G 文档 zephyr #服务器 #c语言 #git #vim seatunnel PX4 #centos #vscode #ubuntu MQTT mosquitto 消息队列 HP Anyware AI-native 7-zip gitlab 源代码管理 微信小程序 notepad++ 矩阵乘法 3D深度学习 NFS embedding virtualenv g++ g++13 paddle shell libreoffice word转pdf 安装 腾讯云大模型知识引擎 rnn docker compose 终端工具 远程工具 deepseek-v3 ktransformers 代理模式 密码学 树莓派 Navidrome 性能监控 gemini gemini国内访问 gemini api gemini中转搭建 Cloudflare ip 重启 排查 系统重启 日志 原因 我的世界服务器搭建 minecraft ArkTs ArkUI ROS2 iTerm2 IP地址 IPv4 IPv6 端口号 计算机基础 yolov8 ecmascript KVM 网络建设与运维 网络搭建 神州数码 神州数码云平台 云平台 性能调优 安全代理 jellyfin nas rocketmq RagFlow C语言 升级 CVE-2024-7347 漏洞 僵尸世界大战 游戏服务器搭建 ESP32 我的世界 我的世界联机 数码 ISO镜像作为本地源 html5 less jmeter 分布式账本 信任链 共识算法 虚拟显示器 远程控制 python2 maxkb ARG ollama api ollama外网访问 代码复审 codereview code-review Kali Linux lvgl8.3 lvgl9.2 lvgl lvgl安装 拓扑图 ai小智 语音助手 ai小智配网 ai小智教程 esp32语音助手 diy语音助手 etcd cfssl adobe rust腐蚀 分布式训练 上传视频至服务器代码 vue3批量上传多个视频并预览 如何实现将本地视频上传到网页 element plu视频上传 ant design vue vue3本地上传视频及预览移除 hive ranger MySQL8.0 p2p bigdata OpenGL 图形渲染 CPU架构 服务器cpu ECS API Uvicorn xcode 命名管道 客户端与服务端通信 cocoapods notepad 隐藏文件 zookeeper 火绒安全 mybase easyTier 组网 渗透测试 系统内核 Linux版本 nac 802.1 portal eNSP 企业网络规划 华为eNSP 网络规划 ip命令 新增网卡 新增IP 启动网卡 前端面试题 go jdk LSTM 仙盟大衍灵机 东方仙盟 仙盟创梦IDE 计算机八股 物联网开发 odoo 服务器动作 Server action ukui 麒麟kylinos thingsboard 云服务 midjourney AI写作 KylinV10 麒麟操作系统 Vmware Netty ios AI员工 若依 内存不足 outofmemory Key exchange 主包过大 MacOS 向日葵 CPU 使用率 系统监控工具 linux 命令 stable diffusion AI作画 burp suite 抓包 打不开xxx软件 无法检查其是否包含恶意软件 arcgis 产品经理 vnc FS 文件系统 bootfs rootfs linux目录 鸿蒙项目 ShenTong 人工智能生成内容 docker搭建nacos详解 docker部署nacos docker安装nacos 腾讯云搭建nacos centos7搭建nacos 文心一言 Mermaid 可视化图表 自动化生成 postgres Docker Desktop Dify重启后重新初始化 小智 创业创新 面试 dns是什么 如何设置电脑dns dns应该如何设置 VSCode 豆瓣 追剧助手 迅雷 音乐服务器 音流 string模拟实现 深拷贝 浅拷贝 经典的string类问题 三个swap tailscale derp derper 中转 CDN .netcore .net core .net NFC 近场通讯 智能门锁 rsync LangGraph CLI JavaScript langgraph.json 数学建模 桌面环境 sqlserver yum换源 kernel function address 函数 地址 内核 can 线程池 DocFlow 虚拟局域网 ros2 moveit 机器人运动 kali 共享文件夹 网卡 显卡驱动持久化 GPU持久化 卸载 软件 列表 Crawlee perf 健康医疗 单一职责原则 express CORS 跨域 虚幻 python3.11 pyside6 界面 Python 视频爬取教程 Python 视频爬取 Python教程 Python 视频教程 客户端-服务器架构 点对点网络 服务协议 网络虚拟化 网络安全防御 毕业设计 struts 物联网嵌入式开发实训室 物联网实训室 嵌入式开发实训室 物联网应用技术专业实训室 状态模式 源码 anaconda fstab Charles vsxsrv 环境变量 Android ANDROID_HOME zshrc 开发环境 微软 Logstash 日志采集 OpenSSH 网络用户购物行为分析可视化平台 大数据毕业设计 yum源切换 更换国内yum源 监控k8s集群 集群内prometheus miniapp 调试 debug 断点 网络API请求调试方法 云原生开发 接口优化 k8s二次开发 zip unzip edge 网络爬虫 软考设计师 中级设计师 SQL 软件设计师 gru nohup后台启动 unionFS OverlayFS OCI docker架构 写时复制 Docker 部署es9 Docker部署es Docker搭建es9 Elasticsearch9 Docker搭建es #人工智能 #深度学习 #机器学习 #考研 #计算机视觉 Trae IDE AI 原生集成开发环境 Trae AI dell服务器 minio kafka 黑客 计算机 游戏开发 网站搭建 serv00 博客 saltstack 机柜 1U 2U postman aws centos-root /dev/mapper yum clean all df -h / du -sh 京东云 protobuf 序列化和反序列化 ubuntu20.04 开机黑屏 linux内核 gpt-3 miniconda minicom 串口调试工具 增强现实 沉浸式体验 技术实现 案例分析 AR 宝塔面板无法访问 tar kubeless 超级终端 多任务操作 提高工作效率 issue rdp 实验 大模型微调 微信小程序域名配置 微信小程序服务器域名 微信小程序合法域名 小程序配置业务域名 微信小程序需要域名吗 微信小程序添加域名 云电竞 云电脑 HTML audio 控件组件 vue3 audio音乐播放器 Audio标签自定义样式默认 vue3播放音频文件音效音乐 自定义audio播放器样式 播放暂停调整声音大小下载文件 大模型推理 服务器繁忙 PVE 网工 聊天室 bonding 链路聚合 状态管理的 UDP 服务器 Arduino RTOS 剧本 React Next.js 开源框架 aac 开发效率 Windmill 进程控制 Echarts图表 折线图 柱状图 异步动态数据 鸿蒙开发 可视化效果 ArkTS css3 js gstreamer 流媒体 HP打印机 TRAE AI代码编辑器 3GPP 卫星通信 DBeaver 数据仓库 kerberos seleium WSL ip协议 opengl 脚本 android-studio 冯诺依曼体系 大语言模型 lvs Agentic Web NLWeb 自然语言网络 微软build大会 STP 生成树协议 PVST RSTP MSTP 防环路 网络基础 armbian u-boot 技术 react next.js 部署next.js nuxt3 文件分享 WebDAV outlook dba 图形化界面 IM即时通讯 剪切板对通 HTML FORMAT AP配网 AK配网 小程序AP配网和AK配网教程 WIFI设备配网小程序UDP开 massa sui aptos sei Featurize Mobilenet 分割 移动开发 ArcTS 登录 ArcUI GridItem 稳定性 看门狗 docker-compose Ubuntu 22.04 MySql 算力租赁 安装教程 Ubuntu20.04 2.35 软件商店 信创 livecd systemtools SystemV 更换镜像源 charles SSH 服务 SSH Server OpenSSH Server 车载系统 Open WebUI mcp-proxy mcp-inspector fastapi-mcp sse WSL2 ubuntu安装 linux入门小白 计算机科学与技术 远程服务 java-ee 局域网 数据链路层 AD域 计算虚拟化 弹性裸金属 致远OA OA服务器 服务器磁盘扩容 asp.net大文件上传 asp.net大文件上传源码 ASP.NET断点续传 asp.net上传文件夹 asp.net上传大文件 .net core断点续传 .net mvc断点续传 wordpress 无法访问wordpess后台 打开网站页面错乱 linux宝塔面板 wordpress更换服务器 显示器 localhost janus linq #服务器 neo4j 数据库开发 database 灵办AI initramfs Linux内核 Grub 星河版 mac设置host 磁盘挂载 新盘添加 partedUtil orbslam2 ubuntu22.04 tftp nfs excel x64 SIGSEGV xmm0 numpy OpenManus Typore autoware Masshunter 质谱采集分析软件 使用教程 科研软件 ajax lstm LSTM-SVM 时间序列预测 二级页表 v10 mount挂载磁盘 wrong fs type LVM挂载磁盘 Centos7.9 SSL证书 unity3d 无桌面 命令行 模拟退火算法 gaussdb 腾讯云 llama.cpp 客户端 大模型训练/推理 推理问题 mindie 商用密码产品体系 sqlite 媒体 flink DICOM cn2 带宽 chrome 浏览器下载 chrome 下载安装 谷歌浏览器下载 Qwen2.5-coder 离线部署 ArtTS 系统开发 binder framework 源码环境 openvpn server openvpn配置教程 centos安装openvpn 华为证书 HarmonyOS认证 华为证书考试 GPU环境配置 Ubuntu22 Anaconda安装 Ardupilot 代码 对比 meld Beyond Compare DiffMerge npm RAGflow 鸿蒙面试 面试题 模块测试 homebrew windows转mac ssh密匙 Mac配brew环境变量 #IntelliJ IDEA #Java #Kotlin 热榜 怎么卸载MySQL MySQL怎么卸载干净 MySQL卸载重新安装教程 MySQL5.7卸载 Linux卸载MySQL8.0 如何卸载MySQL教程 MySQL卸载与安装 单元测试 测试用例 ue4 着色器 ue5 gromacs 分子动力学模拟 MD 动力学模拟 监控k8s 监控kubernetes 7z powerpoint Xshell 文件共享 切换root nacos rustdesk 银河麒麟高级服务器 外接硬盘 Kylin C++软件实战问题排查经验分享 0xfeeefeee 0xcdcdcdcd 动态库加载失败 程序启动失败 程序运行权限 标准用户权限与管理员权限 毕昇JDK Jellyfin 硅基流动 ChatBox 日志分析 系统取证 5090 显卡 AI性能 linux cpu负载异常 Cache Aside Read/Write Write Behind SRS make命令 makefile文件 prometheus数据采集 prometheus数据模型 prometheus特点 版本 c/c++ 串口 resolv.conf NVM Node Yarn PM2 brew swift 药品管理 团队开发 VLAN 企业网络 自动化任务管理 easyui mongodb 私有化 cnn VGG网络 卷积层 池化层 开放端口 访问列表 Typescript authorized_keys 密钥 Spring Boot 全文检索 es pppoe radius spark HistoryServer Spark YARN jobhistory pillow tcp gitea frp 内网服务器 内网代理 内网通信 数据库系统 Headless Linux 信息收集 即时通信 NIO Anolis nginx安装 linux插件下载 firefox SWAT 配置文件 服务管理 网络共享 LDAP AD 域管理 录音麦克风权限判断检测 录音功能 录音文件mp3播放 小程序实现录音及播放功能 RecorderManager 解决录音报错播放没声音问题 gunicorn 锁屏不生效 fpga 概率论 过期连接 材料工程 服务发现 智慧农业 开源鸿蒙 IP 地址 管道 pipe函数 匿名管道 管道的大小 匿名管道的四种情况 #chrome #mac #拓展程序 #禁用 深度求索 私域 Linux24.04 firewalld 路径解析 PPI String Cytoscape CytoHubba rime top Linux top top命令详解 top命令重点 top常用参数 大屏端 裸机装机 linux磁盘分区 裸机安装linux 裸机安装ubuntu 裸机安装kali 裸机 MAVROS 四旋翼无人机 企业风控系统 互联网反欺诈 DDoS攻击 SQL注入攻击 恶意软件和病毒攻击 risc-v Quixel Fab Unity UE5 游戏商城 虚幻引擎 去中心化 进程状态 僵尸进程 MySQL autodl cpu 实时 使用 在线预览 xlsx xls文件 在浏览器直接打开解析xls表格 前端实现vue3打开excel 文件地址url或接口文档流二进 模型联网 CherryStudio api 国标28181 视频监控 监控接入 语音广播 流程 SIP SDP X11 Xming vue-i18n 国际化多语言 vue2中英文切换详细教程 如何动态加载i18n语言包 把语言json放到服务器调用 前端调用api获取语言配置文件 samba 宝塔 笔灵AI AI工具 es6 qt6.3 g726 华为昇腾910b3 finebi 网络接口 时间间隔 所有接口 多网口 实时传输 flinkcdc mcp client mcp server 模型上下文协议 C 进程地址空间 edge浏览器 沙盒 pyicu 推荐算法 pycharm安装 harmonyosnext NVIDIA显卡安装 Ubuntu开机黑屏 ubuntu24.04.1 openstack Xen Hyper-V Reactor Node-Red 编程工具 流编程 deekseek intellij idea 设置代理 实用教程 Apache Beam 批流统一 案例展示 数据分区 容错机制 LVM 磁盘分区 lvresize 磁盘扩容 pvcreate 图搜索算法 client-go OS NVIDIA 转换 CAN 多总线 模拟器 pnet pnetlab 网络配置 路由配置 lsof linux命令 磁盘监控 磁盘镜像 服务器镜像 服务器实时复制 实时文件备份 云桌面 AD域控 证书服务器 Web服务器 多线程下载工具 PYTHON solidworks安装 web lua teamspeak 显卡驱动 nvidia驱动 Tesla显卡 高考 省份 年份 分数线 数据 iftop 网络流量监控 Hive环境搭建 hive3环境 Hive远程模式 进程优先级 调度队列 进程切换 kotlin iphone 动静态库 milvus安装 Metastore Catalog illustrator 互联网医院 RoboVLM 通用机器人策略 VLA设计哲学 vlm fot robot 视觉语言动作模型 Docker引擎已经停止 Docker无法使用 WSL进度一直是0 镜像加速地址 RBAC 显示过滤器 ICMP Wireshark安装 DeepSeek r1 蓝牙 深度强化学习 深度Q网络 Q_Learning 经验回收 汇编 csapp 缓冲区 #redis 流式接口 rsyslog pyqt dns db 浪潮信息 AI服务器 YashanDB 崖山数据库 yashandb logstash gitlab服务器 深度优先 排序算法 零售 log4j AudioLM scrapy 邮件APP 免费软件 Xinference CUPS 打印机 Qt5 csrf 苹果电脑装windows系统 mac安装windows系统 mac装双系统 macbook安装win10双 mac安装win10双系统 苹果电脑上安装双系统 mac air安装win 软硬链接 文件 北亚数据恢复 数据恢复 服务器数据恢复 数据库数据恢复 oracle数据恢复 更新apt 安装hadoop前的准备工作 离线部署dify 办公自动化 pdf教程 卡死 iperf3 带宽测试 docker搭建pg docker搭建pgsql pg授权 postgresql使用 postgresql搭建 mq Helm k8s集群 ros1 Noetic 20.04 apt 安装 考试 软考 webview RDP 进程池实现 百度云 BCLinux 智能体 开发 Jenkins流水线 声明式流水线 软件安装 Linux权限 xshell 权限掩码 粘滞位 量子计算 嵌入式实时数据库 数字化转型 驱动器映射 批量映射 win32wnet模块 网络驱动器映射工具 shell编程 sse_starlette Starlette FastAPI Server-Sent Eve 服务器推送事件 xop RTP RTSPServer 推流 视频 直播推流 mock mock server 模拟服务器 mock服务器 Postman内置变量 Postman随机数据 项目部署到linux服务器 项目部署过程 XCC Lenovo 信创终端 中科方德 Carla ECS服务器 串口服务器 万物互联 工业自动化 工厂改造 MultiServerMCPC load_mcp_tools load_mcp_prompt 客户端/服务器架构 分布式应用 三层架构 Web应用 跨平台兼容性 SFTP SFTP服务端 cs144 uni-popup报错 连接服务器超时 点击屏幕重试 uniapp编译报错 uniapp vue3 imported module TypeError HarmonyOS5 教程 Ubuntu共享文件夹 共享目录 Linux共享文件夹 Mac内存不够用怎么办 mysql安装报错 windows拒绝安装 beautifulsoup termux 环境搭建 线程同步 线程互斥 条件变量 chrome历史版本下载 chrominum下载 dnf uni-app x 空Ability示例项目 讲解 上架 pyautogui vr Zoertier 内网组网 2024 2024年上半年 下午真题 答案 WireGuard 异地组网 漏洞报告生成 axure 轮播图 写时拷贝 Linux的进程调度队列 活动队列 双系统 多系统 Apache OpenNLP 句子检测 分词 词性标注 核心指代解析 冯诺依曼体系结构 Makefile Make dataworks maxcompute #apache #kafka #flink #运维 #openssh升级 #银河麒麟V10 SP10 ecm bpm iis 远程看看 远程协助 大数据平台 网络穿透 asm lighttpd安装 Ubuntu配置 Windows安装 服务器优化 CNNs 图像分类 规格说明书 设计规范 证书 签名 ueditor导入word GaN HEMT 氮化镓 单粒子烧毁 辐射损伤 辐照效应 VMware安装mocOS macOS系统安装 本地部署AI大模型 可执行程序 OpenCore devmem linux/cmake 实习 DenseNet 读写锁 Isaac Sim 虚拟仿真 GRE Reactor反应堆 学习路线 可用性测试 LLaMA-Factory NLP 客户端和服务器端 Nginx报错413 Request Entity Too Large 的客户端请求体限制 CKA pandas matplotlib 分类 弹性 pytorch3d kylin v10 麒麟 v10 oneapi audio vue音乐播放器 vue播放音频文件 Audio音频播放器自定义样式 播放暂停进度条音量调节快进快退 自定义audio覆盖默认样式 nextjs reactjs kamailio sip VoIP TCP服务器 qt项目 qt项目实战 qt教程 WebRTC BMC 带外管理 思科模拟器 思科 Cisco 服务器管理 配置教程 网站管理 服务器ssl异常解决 框架 pxe socket http状态码 请求协议 科勘海洋 数据采集浮标 浮标数据采集模块 接口隔离原则 TCP 多进程 TCP回显服务器 VMware安装Ubuntu Ubuntu安装k8s 黑苹果 sonoma 自动更新 fd 文件描述符 用户缓冲区 软链接 硬链接 网络文件系统 免密 公钥 私钥 photoshop JAVA 进程等待 内存泄漏 编译器 libtorch P2P HDLC RAGFLOW System V共享内存 进程通信 Alexnet compose IO VM虚拟机 python高级编程 Ansible elk stack Linux的进程概念 Linux系统编程 MinerU 直播 #java #maven #java-ee #spring boot #jvm #tomcat IIS Hosting Bundle .NET Framework vs2022 银河麒麟桌面操作系统 Kylin OS TrinityCore 魔兽世界 token sas IIS服务器 IIS性能 日志监控 备份SQL Server数据库 数据库备份 傲梅企业备份网络版 ABAP VNC 飞牛 大文件分片上传断点续传及进度条 如何批量上传超大文件并显示进度 axios大文件切片上传详细教 node服务器合并切片 vue3大文件上传报错提示错误 vu大文件秒传跨域报错cors RK3568 ftp 滑动验证码 反爬虫 前端项目部署 微前端 deepseek r1 中兴光猫 换光猫 网络桥接 自己换光猫 ci/cd Maven Linux find grep 权限 powerbi SPI debezium 数据变更 数据迁移 进程程序替换 execl函数 execv函数 execvp函数 execvpe函数 putenv函数 数码相机 全景相机 设备选择 实用技巧 数字空间 openssh 源码软件 electron #算法 #数据清洗 docker部署翻译组件 docker部署deepl docker搭建deepl java对接deepl 翻译组件使用 bat 论文阅读 qt5 客户端开发 LInux 飞书 Invalid Host allowedHosts Flask Waitress Gunicorn uWSGI 孤岛惊魂4 echarts 信息可视化 网页设计 DeepSeek行业应用 Heroku 网站部署 freebsd 联想开天P90Z装win10 MQTT协议 消息服务器 联机 僵尸毁灭工程 游戏联机 开服 Webserver 异步 零日漏洞 CVE 全栈 raid OSB Oracle中间件 SOA proto actor actor model Actor 模型 大学大模型可视化教学 全球气象可视化 大学气象可视化 观察者模式 Ubuntu Server Ubuntu 22.04.5 Linux的基础指令 键盘 ruby 英语 电脑桌面出现linux图标 电脑桌面linux图标删除不了 电脑桌面Liunx图标删不掉 linux图标删不掉 大版本升 升级Ubuntu系统 设备树 STL firewall vm tar.gz tar.xz linux压缩 VUE Mysql sublime text podman 美食 根目录 #字体 #安装 #微软雅黑 #office Python基础 Python技巧 自动化编程 camera Arduino 输入法 qps 高并发 GeneCards OMIM TTD autogen openai visual studio d3d12 蜂窝网络 频率复用 射频单元 无线协议接口RAN 主同步信号PSS 本地知识库 BMS 储能 WebFuture 容器化 #大数据 #python #毕业设计 #Hadoop #SPark #数据挖掘 c EMQX 通信协议 CPU 存储数据恢复 raid5数据恢复 磁盘阵列数据恢复 netty 音乐库 阿里云ECS 小番茄C盘清理 便捷易用C盘清理工具 小番茄C盘清理的优势尽显何处? 教你深度体验小番茄C盘清理 C盘变红?!不知所措? C盘瘦身后电脑会发生什么变化? client close PTrade QMT 量化股票 工厂方法模式 电子信息工程 相机标定 jvm调优 LRU策略 内存增长 垃圾回收 JavaWeb 回显服务器 Echo bcompare HiCar CarLife+ CarPlay QT RK3588 direct12 cuda驱动 vr看房 在线看房系统 房产营销 房产经济 三维空间 调试方法 Valgrind 内存分析工具 实战项目 入门 精通 Ubuntu22.04 #pytorch 金仓数据库 2025 征文 数据库平替用金仓 ssh远程登录 运维监控 lio-sam SLAM ceph web环境 Serverless 内存管理 软路由 TraeAgent #python3.11 #docker zotero 同步失败 ocr 做raid 装系统 黑客技术 windows日志 银河麒麟操作系统 端口测试 上传视频文件到服务器 uniApp本地上传视频并预览 uniapp移动端h5网页 uniapp微信小程序上传视频 uniapp app端视频上传 uniapp uview组件库 mvc 漫展 笔记本电脑 SQI iOS Server Trust Authentication Challenge HTTP3 全双工通信 多路复用 实时数据传输 mysql离线安装 mysql8.0 Linux PID Linux无人智慧超市 LInux多线程服务器 QT项目 LInux项目 单片机项目 MAC export env 变量 视觉检测 Linux的进程控制 #tomcat #架构 #servlet composer QT 5.12.12 QT开发环境 Ubuntu18.04 免费域名 域名解析 Doris搭建 docker搭建Doris Doris搭建过程 linux搭建Doris Doris搭建详细步骤 Doris部署 rtc 隐藏目录 管理器 通配符 命令模式 桥接模式 windows虚拟机 虚拟机联网 Playwright MCP 自动化测试框架 开启关闭防火墙 dnn mysql 8 mysql 8 忘记密码 c盘 磁盘清理 UDP的API使用 宝塔面板访问不了 宝塔面板网站访问不了 宝塔面板怎么配置网站能访问 宝塔面板配置ip访问 宝塔面板配置域名访问教程 宝塔面板配置教程 live555 源码剖析 rtsp实现步骤 流媒体开发 银河麒麟服务器操作系统 系统激活 swoole uni-file-picker 拍摄从相册选择 uni.uploadFile H5上传图片 微信小程序上传图片 LORA 半虚拟化 硬件虚拟化 Hypervisor 镜像下载 配置原理 跨域请求 机架式服务器 1U工控机 国产工控机 Scoket 套接字 英语六级 加密 医疗APP开发 app开发 移动端开发 GKI KMI 热键 linux常用命令 MAC地址 virtualbox VMware Tools vmware tools安装 vmwaretools安装步骤 vmwaretools安装失败 vmware tool安装步骤 vm tools安装步骤 vm tools安装后不能拖 vmware tools安装步骤 电脑操作 Arduino下载开发板 esp32开发板 esp32-s3 电子器件 二极管 三极管 青少年编程 编程与数学 机器人操作系统 打包工具 重构 #YOLO #目标检测 #自动化 wsgiref Web 服务器网关接口 OD机试真题 华为OD机试真题 服务器能耗统计 智能音箱 智能家居 智能电视 免费 教育电商 pyscenic 生信教程 DELL R730XD维修 全国服务器故障维修 多媒体 华为OD机考 机考真题 需要广播的服务器数量 SPP #c++ 小游戏 五子棋 检索增强生成 文档解析 大模型垂直应用 USB转串口 Redis Desktop 支付 微信支付 开放平台 IP配置 netplan grep 数据库管理 泰山派 根文件系统 编译 烧录 PATH 命令行参数 main的三个参数 react Native 机床 仿真 课件 虚拟现实 教学 课程 IMX317 MIPI H265 VCU docker run 数据卷挂载 交互模式 springboot远程调试 java项目远程debug docker远程debug java项目远程调试 springboot远程 Sealos 输入系统 AzureDataStudio 服务注册与发现 SSM 项目实战 页面放行 gin #llama #kimi DeepSeek-R1 API接口 vasp安装 Ubuntu 24.04.1 轻量级服务器 laravel ldap java-zookeeper cocos2d 3dcoat openvino 网络带宽 问题排查 Lenovo System X GNOME blender three.js 数字孪生 决策树 医药 信号 shell脚本免交互 expect linux免交互 一切皆文件 iptables GoogLeNet AnythingLLM AnythingLLM安装 目标跟踪 OpenVINO 推理应用 rancher 大模型技术 本地部署大模型 finalsheel llamafactory 微调 Qwen DrissionPage AOD-PONO-Net 图像去雾技术 muduo库 思科实验 高级网络互联 链表 #bright data VM搭建win2012 win2012应急响应靶机搭建 攻击者获取服务器权限 上传wakaung病毒 应急响应并溯源 挖矿病毒处置 应急响应综合性靶场 gateway Clion Nova ResharperC++引擎 Centos7 远程开发 匿名FTP 邮件传输代理 SSL支持 chroot监狱技术 GPU状态 AList webdav fnOS 开发人员主页 图文教程 VMware虚拟机 macOS系统安装教程 macOS最新版 虚拟机安装macOS Sequoia mac cocoapods macos cocoapods 文件权限 CTE AGE 单用户模式 wget 端口 #华为 #harmonyos #手机 Ubuntu DeepSeek DeepSeek Ubuntu DeepSeek 本地部署 DeepSeek 知识库 DeepSeek 私有化知识库 本地部署 DeepSeek DeepSeek 私有化部署 Ubuntu 24 常用命令 Ubuntu 24 Ubuntu vi 异常处理 聚类 WebVM 国产数据库 瀚高数据库 下载安装 4 - 分布式通信、分布式张量 本地环回 bind SoC 原子操作 AXI 服务 ping++ 温湿度数据上传到服务器 Arduino HTTP 内网渗透 靶机渗透 EtherCAT转Modbus EtherCAT转485网关 ECT转485串口服务器 ECT转Modbus485协议 ECT转Modbus串口网关 ECT转Modbus串口服务器 Putty 花生壳 web开发 网络IO 队列 数据库占用空间 服务器租用 物理机 进度条 keepalived csrutil mac恢复模式进入方法 恢复模式 win向maOS迁移数据 导航栏 PostgreSQL15数据库 进程创建 进程退出 uboot 部署方案 IMX6ULL 蓝耘科技 元生代平台工作流 ComfyUI curl redhat 电视剧收视率分析与可视化平台 copilot 图片增强 增强数据 su sudo sudo原理 su切换 post.io 企业邮箱 搭建邮箱 迭代器模式 PCB fork 进程管理 vb #YOLOv13 网卡的名称修改 eth0 ens33 vscode1.86 1.86版本 ssh远程连接 ssrf 失效的访问控制 filezilla 无法连接服务器 连接被服务器拒绝 vsftpd 331/530 file server http server web server VPS googlecloud rtsp服务器 rtsp server android rtsp服务 安卓rtsp服务器 移动端rtsp服务 大牛直播SDK C# MQTTS 双向认证 emqx 动态规划 deepseek-r1 大模型本地部署 deepseak 豆包 KIMI 腾讯元宝 软件开发 文件存储服务器组件 宠物 免费学习 宠物领养 宠物平台 支持向量机 建站 VR手套 数据手套 动捕手套 动捕数据手套 分析解读 嵌入式系统开发 systemctl Mac部署 Ollama模型 Openwebui 配置教程 AI模型 容器清理 大文件清理 空间清理 I/O 设备管理 telnet 远程登录 集成 nano wpf dsp开发 xfce #python #信息可视化 磁盘满 DOIT 四博智联 asp.net大文件上传下载 网站 网络原理 券商 股票交易接口api 类型 特点 股票量化接口 股票API接口 vCenter服务器 ESXi主机 监控与管理 故障排除 日志记录 asp.net 快速入门 #开发语言 序列化反序列化 代理服务器 基础环境 Cookie diskgenius 高德地图 鸿蒙接入高德地图 HarmonyOS5.0 sublime text3 octomap_server 原创作者 deployment daemonset statefulset cronjob K8S k8s管理系统 2025一带一路金砖国家 金砖国家技能大赛 技能发展与技术创新大赛 首届网络系统虚拟化管理与运维 比赛样题 高效远程协作 TrustViewer体验 跨设备操作便利 智能远程控制 ardunio BLE W5500 OLED u8g2 充电桩 欧标 OCPP 小智AI服务端 xiaozhi TTS 主板 电源 nosql Web应用服务器 三次握手 惠普服务器 惠普ML310e Gen8 惠普ML310e Gen8V2 腾讯云服务器 轻量应用服务器 linux系统入门 磁盘IO iostat conda配置 conda镜像源 权限命令 特殊权限 wait waitpid exit 用户管理 jdk11安装 jdk安装 openjdk11 openjdk11安装 Python学习 Python编程 elementui 苹果 vscode-server ubuntu18.04 影刀 #影刀RPA# linux安装配置 流水线 脚本式流水线 问题解决 import save load 迁移镜像 富文本编辑器 scapy netlink libnl3 能效分析 time时间函数 #adb #数据库开发 #mysql #sql Socket hibernate 游戏机 移动云 java-rocketmq 服务器部署 本地拉取打包 Qualcomm WoS QNN AppBuilder 鼠标 #提示词注入 #防护 #安全 #大模型 mm-wiki搭建 linux搭建mm-wiki mm-wiki搭建与使用 mm-wiki使用 mm-wiki详解 ebpf Linux环境 ubuntu24 vivado24 抗锯齿 NLP模型 IPv6测试 IPv6测速 IPv6检测 IPv6查询 linux子系统 忘记密码 proxy_pass openGauss 个人博客 code-server EtherNet/IP串口网关 EIP转RS485 EIP转Modbus EtherNet/IP网关协议 EIP转RS485网关 EIP串口服务器 聊天服务器 创意 社区 VMware创建虚拟机 代码托管服务 数字证书 签署证书 vSphere vCenter 金仓数据库概述 金仓数据库的产品优化提案 站群服务器 messages dmesg 多端开发 智慧分发 应用生态 鸿蒙OS Maxkb RAG技术 Linux的基础开发工具 GRANT REVOKE C/C++ Unlocker 分布式总线 体验鸿蒙电脑操作系统 Windows电脑能装鸿蒙吗 #数据库 SSH 密钥生成 SSH 公钥 私钥 生成 efficientVIT YOLOv8替换主干网络 TOLOv8 实战案例 钉钉 Docker快速入门 源代码 registries TiDB测试集群 阻塞队列 生产者消费者模型 服务器崩坏原因 junit 大文件秒传跨域报错cors DigitalOcean GPU服务器购买 GPU服务器哪里有 GPU服务器 Dedicated Host Client 无头主机 算力 banner slave 材质 贴图 基础入门 cmos 高级IO epoll MDK 嵌入式开发工具 cpolar java毕业设计 微信小程序医院预约挂号 医院预约 医院预约挂号 小程序挂号 影视app bpf bpfjit pcap 若依框架 leetcode #VMware #虚拟机 #apache CentOS TCP协议 软负载 飞牛nas fnos 工具分享 高可用 回归 图论 coze扣子 AI口播视频 飞影数字人 coze实战 ipv6 光猫设置 路由器设置 WIFI7 无线射频 高通 射频校准 射频调试 射频匹配 SVN Server tortoise svn UDP 同步 备份 XFS xfs文件系统损坏 I_O error Spring Security 雨云服务器 Erlang OTP gen_server 热代码交换 事务语义 备选 调用 示例 IDEA skynet 西门子PLC 通讯 弹性服务器 行情服务器 股票交易 速度慢 切换 caddy bootstrap 支付宝小程序 云开发 粘包问题 服务网格 istio EMUI 回退 降级 trea idea AppLinking 应用间跳转 云盘 安全组 pi0 lerobot aloha act jina 浏览器开发 AI浏览器 k8s集群资源管理 烟花代码 烟花 元旦 并查集 自学笔记 小米 澎湃OS openresty nacos容器环境变量 docker启动nacos参数 nacos镜像下载 搜狗输入法 中文输入法 network NetworkManager ROS1/ROS2 dockerfile Wayland rtsp转rtmp 海康rtsp转rtmp 摄像头rtsp到rtmp rtsp转发 rtsp摄像头转rtmp rtsp2rtmp #stm32 #单片机 #freeRTOS #经验分享 #笔记 #c++ rtp iDRAC R720xd 干货分享 黑客工具 密码爆破 繁忙 解决办法 替代网站 汇总推荐 AI推理 gradle 蓝桥杯C++组 华为OD 可以组成网络的服务器 ueditor导入pdf ueditor导入ppt AWS 事件驱动 自定义登录信息展示 motd 美化登录 大厂程序员 硅基计算 碳基计算 认知计算 生物计算 AGI 系统架构设计 软件哲学 程序员实现财富自由 RustDesk 搭建服务器 访问公司内网 Linux awk awk函数 awk结构 awk内置变量 awk参数 awk脚本 awk详解 DIFY wifi驱动 杂质 时序数据库 iotdb 子网掩码 公网IP 私有IP GRUB引导 Linux技巧 容器技术 lb 协议 anythingllm open-webui docker国内镜像 MinIO 通用环境搭建 麒麟kos 网络检测 ping #openssh #kubernetes #数据结构 #chrome opcua opcda KEPServer安装 WinRM TrustedHosts 服务器时间 服务器主板 AI芯片 ECT转Modbus协议 EtherCAT转485协议 ECT转Modbus网关 像素流送api 像素流送UE4 像素流送卡顿 像素流送并发支持 错误代码2603 无网络连接 2603 实时云渲染 云渲染 3D推流 MCP 服务器 JADX-AI 插件 光电器件 LED bug定位 缺陷管理 算法协商 故障排查 #vscode #编辑器 #ide 小艺 Pura X termius iterm2 uv Linux的权限 Tabs组件 TabContent TabBar TabsController 导航页签栏 滚动导航栏 Bandizip Mac解压 Mac压缩 压缩菜单 互联网实用编程指南 MateBook CodeBuddy首席试玩官 桶装水小程序 在线下单送水小程序源码 桶装水送货上门小程序 送水小程序 订水线上商城 程序地址空间 CAN总线 #数据结构 #链表 多路转接 产测工具框架 管理框架 cd 目录切换 手机 Web3 Telegram HBase分布式集群 HBase环境搭建 HBase安装 HBase完全分布式环境 NAT 简单工厂模式 dockercompose安装 compose.yml文件详解 dockercompose使用 pavucontrol 蓝牙耳机 人工智能作画 #n8n #n8n工作流 #n8n教程 #n8n本地部署 #n8n自动化工作流 #n8n使用教程 #n8n工作流实战案例 #debian Radius 并集查找 换根法 树上倍增 MNN 显示管理器 lightdm gdm 高效日志打印 串口通信日志 服务器日志 系统状态监控日志 异常记录日志 hugo VS Code zerotier qwen2vl 环境 非root anonymous rtmp 独立服务器 js逆向 软件高CPU占用 ProcessExplorer Process Hacker System Informer Windbg 线程的函数调用堆栈 #合成孔径雷达 #GAMMA #InSAR #游戏 #云计算 捆绑 链接 谷歌浏览器 youtube google gmail 软件卸载 系统清理 多产物 空间 查错 子系统 ps命令 线程安全 应急响应 CTF EulerOS 版本对应 Linux 发行版 企业级操作系统 RHEL 开源社区 南向开发 北向开发 MVVM 鸿蒙5.0 备忘录应用 ai编程 k8s资源监控 annotations自动化 自动化监控 监控service 监控jvm AI Agent 字节智能运维 WebUI DeepSeek V3 fabric BitTorrent 搜索 mcp-server RTMP 应用层 windwos防火墙 defender防火墙 win防火墙白名单 防火墙白名单效果 防火墙只允许指定应用上网 防火墙允许指定上网其它禁止 MI300x 能力提升 面试宝典 IT信息化 流量运营 加解密 Yakit yaklang 互信 WebServer oracle fusion oracle中间件 c/s 矩池云 数据下载 数据传输 access blocked 破解 MQTT Broker GMQT alphafold3 pve 视频直播物理服务器租用 物理服务器 物理机租用 HarmonyOS NEXT 原生鸿蒙 查看显卡进程 fuser vpn 终端 时间轮 文件清理 系统完整性 越狱设备 webgis cesium HarmonyOS 5开发环境 CUDA Toolkit 分布式锁 HDC2025 HarmonyOS 6 #技能认证 机械臂 CAD瓦片化 栅格瓦片 矢量瓦片 Web可视化 DWG解析 金字塔模型 红黑树封装map和set 影刀证书 分享 huggingface #udp #网络通信 #网络协议 #Socket webstorm 根服务器 需求分析 软件定义数据中心 sddc AI agent SEO KingBase sqlite3 Qt QModbus OpenManage 流量 aiohttp asyncio 视频服务器 BIO Java socket Java BIO Java NIO Java 网络编程 cordova 跨域开发 集群 科研绘图 生信服务器 tengine web负载均衡 WAF alias unalias 别名 springcloud 微信分享 Image wxopensdk 多层架构 解耦 safari CentOS Stream fonts-noto-cjk lvm retry 重试机制 提示词 Bluetooth 配对 对话框showDialog showActionMenu 操作列表ActionSheet CustomDialog 文本滑动选择器弹窗 消息提示框 警告弹窗 嵌入式软件 RTOS 系统升级 16.04 Termius Vultr 远程服务器 #http IO模型 李心怡 selete 解决方案 静态IP solr 知行EDI 电子数据交换 知行之桥 EDI mapreduce 定义 核心特点 优缺点 适用场景 恒玄BES ICMPv6 docker安装mysql win下载mysql镜像 mysql基本操作 docker登陆私仓 docker容器 deepseek与mysql AI控制浏览器 Browser user Cilium 物理层 requests python库 #mcp #浏览器自动化 #AI NAT转发 NAT Server asi_bench 多个客户端访问 IO多路复用 TCP相关API 服务器部署ai模型 宕机切换 服务器宕机 IPMITOOL 硬件管理 技术共享 浏览器自动化 负载测试 VPN wireguard accept 雾锁王国 国产芯片 元服务 应用上架 regedit 开机启动 模拟实现 ubantu 底层实现 Linux指令 路径规划 Windows应急响应 webshell 网络攻击防御 网络攻击 CKEditor5 Eigen CMake 自动化编译工具 etl 代理 docker部署Python dock 加速 端口聚合 win11 windows11 网易邮箱大师 数字比特流 模拟信号 将二进制数据映射到模拟波形上 频谱资源 振幅频率相位 载波高频正弦波 containerd usb typec BiSheng 线程同步与互斥 社交电子 clickhouse 架构与原理 域名服务 DHCP 符号链接 配置 vue在线预览excel和编辑 vue2打开解析xls电子表格 浏览器新开页签或弹框内加载预览 文件url地址或接口二进制文档 解决网页打不开白屏报错问题 RNG 状态 可复现性 随机数生成 eventfd 高性能 ESP8266简单API服务器 Arduino JSON webserver SpringBoot proteus 跨平台 Office qtcreator 顽固图标 启动台 端口开放 clipboard 剪贴板 剪贴板增强 Navigation 路由跳转 鸿蒙官方推荐方式 鸿蒙原生开发 命令键 tvm安装 深度学习编译器 黑马 苍穹外卖 PDF 图片 表格 文档扫描 发票扫描 vmvare nmcli linux上传下载 docker命令大全 CLion hosts hosts文件管理工具 代理配置 企业级DevOps 机床主轴 热误差补偿 风电齿轮箱 故障诊断 物理-数据融合 预测性维护 进程操作 理解进程 #php Wi-Fi 超融合 代码规范 AimRT #STC8 #STM32 shard 机器人仿真 模拟仿真 事件分析 边缘服务器 利旧 AI识别 Windows 11 重装电脑系统 cangjie Java 日志框架 Log4j2 Logback SLF4J 结构化日志 企业级应用 哥sika 泛微OA KingbaseES #ai #AI编程 webgl 玩机技巧 软件分享 软件图标 Ark-TS语言 macOS 玩游戏 Github加速 Mac上Github加速 Chrome浏览器插件 coffeescript English 云解析 云CDN SLS日志服务 云监控 FreeLearning infini-synapse mysql8.4.5 Bilibili B站 WLAN 达梦 DM8 5分钟快速学 docker入门 rxjava 改行学it 线性代数 #目标跟踪 #计算机网络 #tcp/ip 无法解析服务器的名称或地址 SSL 域名 矩阵 田俊楠 工业4.0 云耀服务器 WINCC EF Core 客户端与服务器评估 查询优化 数据传输对象 查询对象模式 AI导航站 labview Web测试 openlayers bmap tile server 开闭原则 #c# #OPCUA av1 电视盒子 机顶盒ROM 魔百盒刷机 移动魔百盒 Attention 历史版本 下载 macbook 接口返回 nginx默认共享目录 Windows Hello 摄像头 指纹 生物识别 学习笔记 HarmonyOS SDK Map Kit 地图 redisson FreeFileSync 定时备份 figma 交叉编译 scikit-learn UFW MobileNetV3 VAD 视频异常检测 VAR 视频异常推理 推理数据集 强化微调 GRPO 扩展错误 Jenkins 配置凭证 #神经网络 #爬虫 HAProxy 直流充电桩 相差8小时 UTC 时间 sysctl.conf vm.nr_hugepages xss 执法记录仪 智能安全帽 smarteye 迁移指南 win服务器架设 windows server 海康 Async注解 动态域名 风扇散热策略 曙光 海光 宁畅 中科可控 jQuery 云服务器租用 udp回显服务器 #飞算Java炫技赛 #Java开发 MacOS录屏软件 合成模型 扩散模型 图像生成 ollama下载加速 Ubuntu 24.04 搜狗输入法闪屏 Ubuntu中文输入法 gerrit C++11 lambda 包装类 视频号 Win10修改MAC skywalking #comfyui 查看 ss 生活 医院门诊管理系统 分布式数据库 集中式数据库 业务需求 选型误 sql注入 触觉传感器 GelSight GelSightMini GelSight触觉传感器 docker search docker 失效 docker pull失效 docker search超时 概率与统计 随机化 位运算 几何计算 数论 系统架构设计师 #iotdb #时序数据库 #自然语言处理 #语言模型 #nginx #性能优化 #科技 h.264 查询数据库服务IP地址 SQL Server jetty undertow Nuxt.js ux URL chfs ubuntu 16.04 搭建个人相关服务器 服务器正确解析请求体 联网 easyconnect 火山引擎 站群 多IP 静态NAT Modbustcp服务器 CSDN开发云 zipkin funasr asr 语音转文字 EasyTier navicat threejs 3D 强制清理 强制删除 mac废纸篓 极限编程 ubuntu 18.04 自定义shell当中管道的实现 匿名和命名管道 红黑树 本地不受DeepSeek 亲测 恢复 #WSL #分区 语法 Trae叒更新了? idm isaacgym 共享 设置 电子学会 myeclipse Searxng 视频会议 工作流自动化 AI智能体 scala #qt #图像处理 #nginx #数据库 #端口 #database #macos 内网环境 cpp-httplib 业界资讯 hexo 安防软件 授时服务 北斗授时 充电桩平台 充电桩开源平台 rtcp OpenAI FreeRTOS siteground siteground安装wp 一键安装wordpress 服务器安装wordpress bert 食用文档 #MCP android-ndk 九天画芯 铁电液晶 显示技术 液晶产业 技术超越 vsode 黑屏 mac完美终端 #OCCT #Qt #nacos xpath定位元素 uprobe 手动分区 FCN #iotdb #重构 #安全 #web安全 压测 佛山戴尔服务器维修 佛山三水服务器维修 Unity插件 SysBench 基准测试 TrueLicense 报警主机 豪恩 VISTA120 乐可利 霍尼韦尔 枫叶 时刻 gpu 参数服务器 分布式计算 数据并行 协作 FS100P 转流 rtsp取流 rtmp推流 虚拟主机 物理服务器租用 broadcom RHCE 智能手表 Pura80 WATCH 5 GDB调试 Ubuntu环境 四层二叉树 断点设置 nvm安装 #mobaxterm #termius #electerm #tabby #termcc #rockylinux #rhel #操作系统 #系统安装 #ansible #role #galaxy #ansible-galaxy linux 命令 sed 命令 ELF加载 仓库 实时语音识别 流式语音识别 敏捷开发 #时序数据库 #excel #Linux #Ubuntu #ubuntu24 #ubuntu2404 #ubuntu安装 #sudo #PG处理POI分类数据 #Java处理POI分类数据 #ApachePOI数据处理 #高德POI分类数据存储 #POI数据分类存储 网络犯罪 人工智能 #大数据 vscode 1.86 sentinel 制造 小亦平台 运维问题解决方法 gaussdb问题解决 #阿里云 效率 #矫平机 #校平机 #铁 #钢 #kali proxy模式 PP-OCRv5 ubuntu20.04 OCR NGINX POD #redis #缓存 #web安全 #网络安全 #渗透测试 #计算机 #转行 #职场发展 #干货分享 #电脑上不了网 #IP设置 #网卡驱动 #路由器设置 #wifi设置 #网络防火墙 #无法连接到这个网络 #飞书 高效I/O 模板 泛型编程 能源 选择排序 地平线5 机架式 IDC java18 whistle mujoco IT 护眼模式 激光雷达 镭眸 汽车 arkts arkui 路由器 ohmyzsh #小程序 #DevEco Studio #HarmonyOS Next #conda #信息可视化 #qml 项目部署 智能问答 Milvus Modbus TCP pow 指数函数 优化 最新微服务 #物联网 #算法 #洛谷 #强连通分量 #缩点 #vue.js #前端 #云原生 #阿里云 #gpt #chatgpt 恒源云 AISphereButler authing 低成本 开启黑屏 tty2 物理机服务器 统信uos Mac软件 实时日志 logs NTP服务器 安全整改 cp 进度显示 #华为云 #云服务部署 #搭建AI #Flexus X实例 watchtower homeassistant 基本指令 N8N 集合 List OpenTiny 中文分词 vue2 #架构 #分布式 #单机架构 #微服务 服务器托管 云托管 数据中心 idc机房 pikachu靶场 XSS漏洞 XSS DOM型XSS dos 批处理 日期 重置密码 #postgresql #kubernetes #sql #学习 #自动化测试 #软件测试 电商平台 mobaxterm #其他 风扇控制软件 #shell #脚本 #计算机网络 #网络攻击模型 #端口占用 #系统详情 集群管理 微信自动化工具 微信消息定时发送 UDS Bootloader #系统架构 #inlong lrzsz #笔记 #intellij-idea #idea #intellij idea Bluedroid #默认分类 #tensorflow #pip #图论 #深度优先 #vue.js SonarQube #HTML #核心知识点 #web #知识点 #网页开发 #pycharm A2A #mc #服务器搭建 #mc服务器搭建 #mc服务器 #Dify #电脑 #经验分享 fast 责任链模式 #毕设 #租房管理系统 #论文 #虚拟地址 #虚拟地址空间 #写时拷贝 #嵌入式硬件 #部署配置docker #容器化 #后端 #unity #着色器 #jenkins #测评 #CCE #Dify-LLM #Flexus #VNC #jdk #编程 #macos26 #启动台 信奥 几何绘图 三角函数 guava #echarts #https #进程状态 #僵尸进程 #孤儿进程 #挂起 细胞分割 计数自动化 图像分析 #eureka #系统架构 #网络协议 #ip #机器人 #音视频 #AIGC #开源 #Agent #智能运维 #AI开发平台 #AI工具链 #智能路由器 #NAT #信息与通信 #nginx配置 #nginx案例 #nginx详解 #Ollama #agent #向量库 #fastAPI #langchain #tcp/ip #面试 #职场和发展 #iot 连接失败 Mosquitto #aws #搜索引擎 #elasticsearch #全文检索 #进程优先级 #进程切换 #Linux调度算法 #寄存器 WinCC OT与IT SCADA 智能制造 MES #AI编程 #低代码 #物联网 #进程 #fork #深信服运维安全管理系统 #远程命令执行漏洞 #GESP C++ #C++程序竞赛 #c语言 #程序人生 #MCP协议 #typescript #实战指南 #MCP服务器 #gitlab #github #RAG #Cookie #Session #HTTP #截图工具 #实时流处理 #设备故障预测 #Flink #rocketmq #零拷贝 #DeepSeek #蓝耘智算 #微信小程序 #配置教程 #入门教程 #安装教程 #图文教程 #数据库架构 #安全架构 #神经网络 #Linux的进程间通信 #node.js #jvm #驱动 #嵌入式 #信奥赛 #深度学习 #概率论 #统信uos #spring boot #Linux的基础IO #开源 #AI写作 dfs #raid #raid阵列 #github #美食 #django #flask #node.js #硬盘读取 #硬盘读取失败 #MAC电脑读取硬盘 #android #缓冲区 #Linux #需求分析 #区块链 #数据分析 #哈希算法 #散列表 #golang #beego #go1.19 #beautifulsoup #CMake #Debian #CentOS #struts #VMware #VMWare Tool #LoTDB #Apache IoTDB #腾讯云 #list #stl #react.js #javascript #React 编译器 #自动优化 #记忆化技术 #重新渲染优化 #Linux的进程信号 #RBAC桎梏 #角色爆炸 #静态僵化 #授权对象体系 #组织维度 #业务维度 #elasticsearch #intellij-idea #内网穿透 Excel转json Excel转换json Excel累加转json python办公 #leetcode #矩阵 #使用教程 #ruby #unix #哈希表 #gitee #权限