Linux高级编程_30_管道

news2024/11/27 2:35:46

文章目录

    • 管道
      • 作用:
      • 分类:
    • 前置知识:
      • 复制文件描述符
        • dup
        • dup2 【推荐使用】
    • 无名管道
      • 概述:
    • pipe函数
      • 实现: ps -A | grep bash
    • 有名管道:
    • 实现有名管道的聊天
    • 无名管道与有名管道的区别?

管道

作用:

用于进程间通信

  • 信号只能携带少量数据(可以理解为不带数据)
  • 管道可以携带大量数据

分类:

  • 无名管道(管道) 作用于有血缘关系的进程中
  • 有名管道 作用 于 没有血缘关系的进程中

前置知识:

复制文件描述符

文件描述符有 : 0 标准输入 1 标准输出 2 标准错误

dup

作用: 复制已有文件描述符

#include <unistd.h>
int dup(int oldfd);
参数:
	所需复制的文件描述符
返回值
	复制得到的文件描述符
功能:从文件描述符表中,寻找一个最小可能的文件描述符(通过返回值返回)作为
oldfd复制

示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//  dup()  拷贝文件描述符
int main(int argc, char const *argv[])
{
    int fd = open("./test.txt",O_APPEND | O_RDWR | O_CREAT,0666);
    int new_fd = dup(fd);  //将久的文件描述符作为参数  来获得新文件描述符 
    write(new_fd,"hello",10);  //往new_fd这个文件描述符修饰的文件中写hello写入长度为6
    close(new_fd);
    close(fd);
    return 0;
}

示例2:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
    // fd = 3
    int fd = open("./test.txt", O_RDWR | O_APPEND);
    // 最小可用文件描述符1
    close(1);
    // nfd = 1
    int nfd = dup(fd);
    // write(1,"内容",长度);
    printf("nfd = %d\n", nfd);
    return 0;
}
dup2 【推荐使用】
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//   dup2()   拷贝文件描述符  【最常用】
int main(int argc, char const *argv[])
{
    int fd = open("./test.txt",O_APPEND | O_RDWR);
    int new_fd = 1;
    dup2(fd,new_fd);
    printf("new_fd = %d\n",new_fd);
    return 0;
}

无名管道

无名管道 又名 管道 开发实际中说管道一般就是说的无名管道

概述:

作用于有血缘关系的进程中
属于:
	半双工
补充
	单工:指数据传输只支持数据在一个方向上传输
	双工:指二台通讯设备之间,允许有双向的资料传输
	全双工:允许二台设备间同时进行双向数据传输。一般的电话、手机就是全双工的系统,因为在讲话时同时也可以听到对方的声音。
	半双工:允许二台设备间进行双向数据传输,但不能同时进行。因此同一时间只允许一设备传送资料,若另一设备要传送资料,需等原来传送资料的设备传送完成后再处理。
	基于内存
			特点:
                   1,数据只能从管道的一端写入,从另一端读出。
                   2,写入管道中的数据遵循先入先出的规则。
                   3,管道所传送的数据是无格式的,这要求管道的读出方与写入方必须事先约定好数据的格式,如多少字节算一个消息等
                   4,管道在内存中对应一个缓冲区。不同的系统其大小不一定相同,liunx系统64kb
				  5,从管道读数据是一次性操作,数据一旦被读走,它就从管道中被抛弃,释放空间以便写更多的数据
				  6,管道没有名字,只能在具有公共祖先的进程之间使用。
				  7,基于内存
				  8,半双工
                       
  补充:
如管道可用于一个进程和其子孙进程之间的通信。第一个进程创建管道,然后创建子进程,接着子进程再创建第一个进程的孙子进程。
    管道通常用于两个兄弟进程之间的通信——它们的父进程创建了管道,并创建两个子进程。
    总结:在当前进程中创建管道

pipe函数

作用:

创建无名管道

语法:

#include <unistd.h>
int pipe(int fd[2]);
参数:
	fd 为 int 型数组的首元素地址,其存放了管道的文件描述符 fd[0]、fd[1]。
	fd[0]为读而打开,fd[1]为写而打开管道。
		01写
返回值:
		成功:返回 0
		失败:返回-1

示例:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
    // 让子进程A给子进程B发送消息
    // 1,创建无名管道
    int fd[2] = {0};
    pipe(fd);
    // 2,创建子进程
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        if (pid == 0)
        {
            break;
        }
    }
    // 3,分类
    if (i == 0)
    {
        // 子进程A:发送消息给子进程B
        // 因为子进程A是发送消息的,所有该进程中读的文件描述符无用,顾关闭
        // 0,读,1,写
        close(fd[0]);
        char *info = "你好,我是子进程A\n";
        write(fd[1], info, strlen(info));
        close(fd[1]);
    }
    else if (i == 1)
    {
        // 子进程B:接收子进程A发送的消息
        // 因为子进程B是接收消息的,所有其进程中写的文件描述符无用,顾关闭
        close(fd[1]);
        char buf[200] = {0};
        // 注意:读会阻塞当前进程,直到管道中有数据可以读取
        read(fd[0], buf, 200);
        printf("子进程B:%s", buf);
        close(fd[0]);
    }
    else if (i == 2)
    {
        // 当前进程:回收子进程
        while (1)
        {
            if (waitpid(-1, NULL, WNOHANG) == -1)
            {
                break;
            }
        }
    }
    return 0;
}

示例2:无读有写,可以写入

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
    // 让子进程A给子进程B发送消息
    // 1,创建无名管道
    int fd[2] = {0};
    pipe(fd);
    // 2,创建子进程
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        if (pid == 0)
        {
            break;
        }
    }
    // 3,分类
    if (i == 0)
    {
        // 子进程A:发送消息给子进程B
        // 因为子进程A是发送消息的,所有该进程中读的文件描述符无用,顾关闭
        // 0,读,1,写
        close(fd[0]);
        char *info = "你好,我是子进程A\n";
        write(fd[1], info, strlen(info));
        close(fd[1]);
    }
    else if (i == 1)
    {
    }
    else if (i == 2)
    {
        // 当前进程:回收子进程
        while (1)
        {
            if (waitpid(-1, NULL, WNOHANG) == -1)
            {
                break;
            }
        }
    }
    return 0;
}

示例3:有读无写,读端会阻塞

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
    // 让子进程A给子进程B发送消息
    // 1,创建无名管道
    int fd[2] = {0};
    pipe(fd);
    // 2,创建子进程
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        if (pid == 0)
        {
            break;
        }
    }
    // 3,分类
    if (i == 0)
    {
    }
    else if (i == 1)
    {
        // 子进程B:接收子进程A发送的消息
        // 因为子进程B是接收消息的,所有其进程中写的文件描述符无用,顾关闭
        close(fd[1]);
        char buf[200] = {0};
        // 注意:读会阻塞当前进程,直到管道中有数据可以读取
        read(fd[0], buf, 200);
        printf("子进程B:%s", buf);
        close(fd[0]);
    }
    else if (i == 2)
    {
        // 当前进程:回收子进程
        while (1)
        {
            if (waitpid(-1, NULL, WNOHANG) == -1)
            {
                break;
            }
        }
    }
    return 0;
}

示例4:缓存区大小测试与缓冲区内容已满继续写入会阻塞

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
    int fd[2] = {0};
    pipe(fd);
    int pid = fork();
    if (pid == 0)
    {
        // 子进程写
        close(fd[0]);
        int i = 0;
        while (1)
        {
            char buf[1024];
            write(fd[1], buf, 1024);
            i++;
            printf("已写入%dkb\n", i);
        }
    }
    else if (pid > 0)
    {
        wait(NULL);
    }
    return 0;
}

示例5:一个写入的信息只能被读取一次

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
    int fd[2];
    pipe(fd);
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        if (pid == 0)
        {
            break;
        }
    }
    if(i == 0)
    {
        //写1次
        close(fd[0]);
        char *buf = "写入的内容\n";
        write(fd[1],buf,strlen(buf));
        close(fd[1]);
    }
    else if(i == 1)
    {
        //读两次
        close(fd[1]);
        char buf[100] = {0};
        read(fd[0],buf,100);
        printf("第一次读取到的内容:%s\n",buf);
        read(fd[0],buf,100);
        printf("第二次读取到的内容:%s\n",buf);
        close(fd[0]);
    }
    else if(i == 2)
    {
        //回收子进程
        while(waitpid(-1,NULL,WNOHANG) != -1);
    }
    
    return 0;
}

示例6:当所有进程中读端关闭,写端将收到SIGPIPE的信号

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <sys/types.h>
void fun()
{
    printf("收到SIGPIPE信号\n");
}
int main(int argc, char const *argv[])
{
    int fd[2];
    pipe(fd);
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        if (pid == 0)
        {
            break;
        }
    }
    if (i == 0)
    {
        signal(SIGPIPE,fun);
        //写入
        close(fd[0]);
        while(1)
        {
            char *buf = "hello\n";
            sleep(1);
            write(fd[1],buf,strlen(buf));
        }
        close(fd[1]);
    }
    else if(i == 1)
    {
        //读一次
        close(fd[1]);
        for (int j = 0; j < 5; j++)
        {
            char buf[1024] = {0};
            read(fd[0],buf,1024);
            printf("读取到的内容:%s\n",buf);
        }
        
        close(fd[0]);
        printf("读端关闭\n");
        _exit(0);
    }
    else if(i == 2)
    {
        //回收
        close(fd[0]);
        while(waitpid(-1,NULL,WNOHANG) != -1);
    }
    return 0;
}

实现: ps -A | grep bash

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
  //要求:使用代码实现 ps -A | grep bash
  int fd[2] = {0};  // 0 读  1 写
  pipe(fd);
  
  int pid = vfork();
  if (pid == 0)
  {
      close(fd[0]);
      //ps -A
      /*
          因为ps -A最终的结果会输出的控制台
          控制台输出对应的文件描述符为1
          此时将我们管道的写端复制文件描述符为1
          此时表示输出的文件描述1就是我们管道的写端
          此时ps -A程序执行完毕后,将其输出的内容写入到了我们的管道中
       */
      dup2(fd[1],1);
      execlp("ps","./ps","-A",NULL);
      close(fd[1]);
  }
  else if(pid > 0)
  {
      //grep bash
      close(fd[1]);
      /*
          grep bash是从标准输入中读取数据
          我们将标准输入改为我们管道的读端
          此时grep bash就是我们管道的读端读取数据
          管道读端的数据就是管道写段写入的数据
          即ps -A输出的内容
       */
      dup2(fd[0],0);
      execlp("grep","./grep","bash",NULL);
      close(fd[0]);
      wait(NULL);
  } 
  return 0;
}

有名管道:

概述

又名:命名管道(FIFO)
特点:
	1、半双工,数据在同一时刻只能在一个方向上流动。
	2、写入 FIFO 中的数据遵循先入先出的规则。
	3、FIFO 所传送的数据是无格式的,这要求 FIFO 的读出方与写入方必须事先约定好数据的格式,如多少字节算一个消息等。
	4、FIFO 在文件系统中作为一个特殊的文件而存在,但 FIFO 中的内容却存放在内存中。
	5、管道在内存中对应一个缓冲区。不同的系统其大小不一定相同。
	6、从 FIFO 读数据是一次性操作,数据一旦被读,它就从 FIFO 中被抛弃,释放空间以便写更多的数据。
	7、当使用 FIFO 的进程退出后,FIFO 文件将继续保存在文件系统中以便以后使用。
	8、FIFO 有名字,不相关的进程可以通过打开命名管道进行通信。

mkfifo 函数

作用:创建有名管道

语法

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
	参数:
		pathname:文件名
		mode:文件操作模式,一般用0666(所有用户可读可写)
	返回值:
			成功:0
			失败:-1,一般失败是因为存在与pathname名相同的文件

读写特点

1、open打开管道 不指定 O_NONBLOCK (阻塞)

1、open 以只读方式打开 FIFO 时,要阻塞到某个进程为写而打开此 FIFO

2、open 以只写方式打开 FIFO 时,要阻塞到某个进程为读而打开此 FIFO。

3、open 以只读、只写方式打开 FIFO 时会阻塞,调用 read 函数从 FIFO 里读数据时 read 也会阻塞。

4、通信过程中若写进程先退出了,则调用 read 函数从 FIFO 里读数据时不阻塞;若写进程又重新运行,则调用

​ read 函数从 FIFO 里读数据时又恢复阻塞。

5、通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程也会(收到SIGPIPE 信号)退出。

6、调用 write 函数向 FIFO 里写数据,当缓冲区已满时 write 也会阻塞。

2、open打开管道 指定O_NONBLOCK (非阻塞)

1、先以只读方式打开:如果没有进程,已经为写而打开一个 FIFO, 只读 open 成功,并且 open 不阻塞。

2、先以只写方 式打开:如果没有进程,已经为读而打开一个 FIFO,只写 open 将出错返回-1。

3、read、write 读写命名管道中读数据时不阻塞。

4、通信过程中,读进程退出后, 写进程向命名管道内写数据时,写进程也会(收到SIGPIPE 信号)退出。

3、 注意:open函数以可读可写方式打开FIFO 文件时的特点:

1、open不阻塞。

2、调用read函数从FIFO里读数据时read会阻塞。

3、调用write函数向FIFO里写数据,当缓冲区已满时write也会阻塞

实现有名管道的聊天

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wait.h>
// 实现 张十一 与 张优秀 之间的通信
int main(int argc, char const *argv[])
{
    // 1.创建xxz给zy发信息的管道
    mkfifo("./xxz_to_zy", 0666);
    // 2.创建zy给xxz发信息的管道
    mkfifo("./zy_to_xxz", 0666);
    // 3.创建子进程 一个用来发信息 一个用来收信息
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        if (pid == 0)
        {
            break;
        }
    }
    //子进程1 用来发信息
    if (i == 0)
    {   //文件描述符  0标准输入   1标准输出  2标准错误  
        int fd = 0;
        //如果有XXZ这个宏,当前用户就是 张优秀     
        #ifdef XXZ          
            fd = open("./xxz_to_zy", O_RDWR); //此时是张优秀给张十一发消息  以可读、可写的方式打开
        #else
            fd = open("./zy_to_xxz", O_RDWR); //此时是张十一给张优秀发消息     
        #endif
        //开始发信息   
        while (1)
        {
            // 用来存放信息 大小为300字节
            char info[300] = {0};  
            // 从标准输入中获取信息   最多获取300个字节
            fgets(info, 300, stdin);
            //打印展示 
            printf("我:%s", info);
            //清除脏数据 也就是按的回车上去的\n
            info[strlen(info) - 1] = 0;        
            //写进文件 消息
            write(fd,info,strlen(info));
            //给定结束的条件  使用 比较字符串是否相等
            if(strcmp(info,"88") == 0 )
            {
                break;
            }
        }
        close(fd);   //关闭文件描述符
    }
    else if (i == 1)//子进程2 用来收信息
    {
        int fd = 0; 
        //接收信息  
        #ifdef XXZ
            fd = open("./zy_to_xxz",O_RDWR);   //读取 张十一发来的信息
        #else
            fd = open("./xxz_to_zy",O_RDWR);   //读取 张优秀发来的信息
        #endif
        //开始读取信息
        while(1)
        {
            // 用来存放信息 大小为300字节
            char info[300] = {0};
            read(fd,info,300);
            //再定义宏用来决定谁来说话
            #ifdef XXZ
                printf("张优秀说:%s\n",info);
            #else
                printf("张十一说:%s\n",info);
            #endif
            //给定结束的条件  使用 比较字符串是否相等    这里是因为传过来的数据本身就是剔除了\n的  所以这里直接比较字符串是否相等即可
            if(strcmp(info,"88") == 0 )
            {   
                break;
            }
        }
        close(fd);   //关闭文件描述符
    }
    else if (i == 2)// 当前是父进程 用来回收子进程
    {
        while (waitpid(-1, NULL, WNOHANG) != -1);
    }
    return 0;
}

在这里插入图片描述

无名管道与有名管道的区别?

  • 1 无名管道 只能在有血缘关系的进程之间通讯

有名管道 既可以在有血缘关系的进程间通讯也能在无血缘关系的进程间通信

  • 2 无名管道没有对应的文件 有名管道有对应的文件
  • 3 但是有名管道中对应的文件不会存储其管道中的数据 数据是存储在内存中

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

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

相关文章

小红书算法岗面试,竞争太激烈了

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

排版套料系统设计说明

先上效果图 项目地址 1.产品介绍 产品名称&#xff1a;StreamFit 智能排版套料系统 主要功能&#xff1a; 智能排版优化 功能描述&#xff1a;StreamFit 利用先进的算法技术&#xff0c;自动对各类材料&#xff08;如布料、金属板材、纸张等&#xff09;进行高效排版布局&am…

一次Mysql数据库活跃连接数高告警的排查方法

基础相关知识 在现代应用中&#xff0c;数据库的性能和稳定性直接影响到整个系统的运行情况。活跃连接数高的告警往往意味着数据库负载过重&#xff0c;可能会导致性能下降甚至服务不可用。 活跃连接数指的是当前与数据库建立连接并且处于活动状态的连接数量。 高活跃连接数…

阿里云百炼通义大模型接入流程,手把手教程

阿里云百炼通义大模型接入流程&#xff0c;即体验大模型、创建Agent应用和创建自训练大模型&#xff0c;阿里云百科aliyunbaike.com分享阿里云官网关于阿里云百炼通义大模型的接入流程&#xff1a; 阿里云百炼通义大模型接入流程 快速接入阿里云百炼通义大模型共分为三大步骤&a…

大模型客服的未来发展趋势

在当今数字化时代&#xff0c;大模型客服正以惊人的速度改变着客户服务的格局。随着技术的不断进步&#xff0c;大模型客服的未来发展趋势充满了无限可能。随着人工智能技术的快速发展&#xff0c;智能客服领域正迎来一场前所未有的变革。大模型客服作为其中的重要分支&#xf…

为什么营业执照显示经营异常

经营异常是怎么回事&#xff1f;是什么意思&#xff1f;1、年报未依照正常的时间公示或者某些要素没有公示;2、营业执照的地址与实际的地址不符&#xff0c;该地址联络不到人。经营异常不处理有什么后果&#xff1f;有什么影响&#xff1f;企业被列入工商异常一般会对公司的经营…

Maven的生命周期与依赖作用域介绍

说明&#xff1a;本文介绍Maven的生命周期&#xff0c;以及在pom.xml文件中每个依赖&#xff08;dependency标签内&#xff09;scope标签的内容。 Maven生命周期 在IDEA项目中&#xff0c;右侧边栏&#xff0c;点Maven&#xff0c;可以看到以下生命周期。 其中&#xff0c; c…

【AI知识点】偏差-方差权衡(Bias-Variance Tradeoff)

偏差-方差权衡&#xff08;Bias-Variance Tradeoff&#xff09; 是机器学习和统计学中的一个核心概念&#xff0c;描述了模型在训练数据和测试数据上的表现与模型复杂度之间的关系。它解释了为什么我们需要在模型复杂度和模型泛化能力之间做权衡&#xff0c;以避免模型出现欠拟…

数字化转型:企业竞争力提升的关键

在当今时代&#xff0c;数字化转型已成为企业发展的必然趋势。它不仅仅是技术的应用&#xff0c;更是一种战略思维的转变。 数字化转型的主要内容 1.业务流程数字化&#xff1a;通过引入信息技术&#xff0c;实现业务流程的自动化、智能化&#xff0c;提高业务流程的效率和准确…

科普篇 --- 什么是汽车中的API?

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

第四节——从深层剖析指针(让你不再害怕指针)

文章目录 1. 字符指针变量剑指offer例题 2. 数组指针变量2.1 数组指针变量是什么&#xff1f;2.2 数组指针变量怎么初始化 3. ⼆维数组传参的本质代码实现 4. 函数指针变量4.1 函数指针变量的创建4.3 两段有趣的代码4.3.1 typedef 关键字 5. 函数指针数组的定义 1. 字符指针变量…

Stable Diffusion绘画 | AI 图片智能扩充,超越PS扩图的AI扩图功能(附安装包)

来到「文生图」页面&#xff0c;输入固定的起手式提示词。 第1步&#xff0c;开启 ControlNet&#xff0c;将需要扩充的图片加载进来&#xff1a; 控制类型选择「Inpaint」&#xff0c;预处理器选择「inpaint_onlylama」&#xff0c;缩放模式选择「缩放后填充空白」&#xff1…

【C++差分数组】3224. 使差值相等的最少数组改动次数|1996

本文涉及知识点 C差分数组 LeetCode3224. 使差值相等的最少数组改动次数 给你一个长度为 n 的整数数组 nums &#xff0c;n 是 偶数 &#xff0c;同时给你一个整数 k 。 你可以对数组进行一些操作。每次操作中&#xff0c;你可以将数组中 任一 元素替换为 0 到 k 之间的 任一…

【目标检测】集装箱缺陷检测数据集1476张5类缺陷VOC+YOLO格式

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1476 标注数量(xml文件个数)&#xff1a;1476 标注数量(txt文件个数)&#xff1a;1476 标注…

什么是高斯积分,以及如何求它的值(error function)

文章目录 什么是高斯积分高斯积分与误差函数的关系求值证明过程技巧1 两个相互独立的积分的乘积转为双重积分技巧2 富比尼定理技巧3 坐标系转换总结 什么是高斯积分 高斯积分的公式如下&#xff1a; 高斯积分与误差函数的关系 参考wiki&#xff0c;误差函数的定义如下&…

Ajax和axios简单用法

Ajax Ajax&#xff08;Asynchronous JavaScript And XML&#xff0c;异步的JavaScript和XML&#xff09;。 作用是&#xff1a; 数据交换&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获取服务器响应的数据。异步交互&#xff1a;可以在不重新加载整个页面的情况…

【汇编语言】寄存器(CPU工作原理)(一)—— 寄存器的基础知识及存储

文章目录 前言1. 寄存器2. 通用寄存器3. 字在寄存器中的存储结语 前言 &#x1f4cc; 汇编语言是很多相关课程&#xff08;如数据结构、操作系统、微机原理&#xff09;的重要基础。但仅仅从课程的角度出发就太片面了&#xff0c;其实学习汇编语言可以深入理解计算机底层工作原…

1、如何查看电脑已经连接上的wifi的密码?

在电脑桌面右下角的如下位置&#xff1a;双击打开查看当前连接上的wifi的名字&#xff1a;ZTE-kfdGYX-5G 按一下键盘上的win R 键, 输入【cmd】 然后&#xff0c;按一下【回车】。 输入netsh wlan show profile ”wifi名称” keyclear : 输入完成后&#xff0c;按一下回车&…

初阶C语言-指针

1.指针是什么&#xff1f; 理解指针的两个要点&#xff1a; 1.指针是内存中一个最小单元的编号&#xff0c;也就是地址 2.口头语中说的指针&#xff0c;通常是指指针变量&#xff0c;是用来存放内存地址的变量 总结&#xff1a;指针就是地址&#xff0c;口语中说的指针通常是指…

详解单流Transformer架构中图像/文本/表格/视频/音频经过transformer提取模态特征并生成令牌特征以及CLS到底是什么作用?

系列论文研读目录 文章目录 系列论文研读目录论文中经常出现的如下图中所示结果&#xff0c;其中到底做了什么&#xff1f;1、一张图片 经过self attention 和Feed forward 生成的是什么&#xff1f;具体流程如下&#xff1a;结果&#xff1a; 举个具体计算的例子假设条件1. 自…