【Linux】基础IO-下

目录

1、重定向

2、缓冲区

3、简单模拟实现C文件标准库


1、重定向

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define filename "log.txt"

int main()
{
    int fd = open(filename, O_CREAT|O_WRONLY|o_TRUNC,0666);
    if(fd < 0)
    {
        perror("open"); //当打开出错时,就会显示open: 错误描述信息
        return 1;
    }
    
    printf("fd:%d\n",fd);

    //返回值是你实际写入到这个文件中的个数
    int cnt = 5;
    const char *msg = "hello Linux";
    while(cnt)
    {
        write(fd, msg,strlen(msg));
        cnt--;
    }

    close(fd);

    return 0;
}

文件描述符的分配规则:从0下标开始寻找最小的没有被使用的数组位置,它的下标就是新文件的文件描述符。eg:flose(0),那么打开的新文件的fd就是0.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define filename "log.txt"

int main()
{
    
    close(1);//关闭显示器文件
    int fd = open(filename, O_CREAT|O_WRONLY|o_TRUNC,0666);
    if(fd < 0)
    {
        perror("open"); //当打开出错时,就会显示open: 错误描述信息
        return 1;
    }
    
    int cnt = 5;
    const char *msg = "hello Linux";
    while(cnt)
    {
        write(1, msg,strlen(msg)); //向显示器写入
        cnt--;
    }

    close(fd);

    return 0;
}

结果:./myproc

(没有任何显示)  但是cat  log.txt

显示:hello Linux

           hello Linux

           hello Linux

           hello Linux

           hello Linux

我们可以看到,需要向显示器打印的数据被打印到了文件里------这其实就是输出重定向

其实是因为:当flose(1)的时候,系统就会重新将1下标分配给log.txt,可是,在write的时候是向1写的,就会写入到 log.txt 文件(上图就是重定向的原理)   重定向其实是将数组的内容做修改。

数组的内容:就是文件的地址。  系统中有专门用作重定向的系统调用,本质就是将3号下标的log.txt file* 拷贝到1号下标,这样,就可以是log.txt分配的fd是1,这样写入的话就可以直接完成重定向。

#include <unistd.h>
int dup2(int oldfd, int newfd);// oldfd 是最后两个都变成的fd(即你要往哪个里面写)  newfd是需要将oldfd复制到的下标  其实是指针内容进行拷贝
//使用一下系统调用进行重定向。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define filename "log.txt"

int main()
{
    int fd = open(filename, O_CREAT|O_WRONLY|o_TRUNC,0666);
    //int fd = open(filename, O_CREAT|O_WRONLY|O_APPEND,0666);//追加重定向
    if(fd < 0)
    {
        perror("open"); //当打开出错时,就会显示open: 错误描述信息
        return 1;
    }
    int cnt = 5;
    //重定向
    dup2(fd,1); //直接使用系统调用来进行重定向
    close(fd);  //可以关也可以不关,这样就不会造成文件描述符浪费
    const char *msg = "hello Linux";
    while(cnt)
    {
        write(1, msg,strlen(msg)); //向显示器写入
        cnt--;
    }

    close(fd);

    return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define filename "log.txt"

int main()
{
    int fd = open(filename,O_RDONLY);//输入重定向
    if(fd < 0)
    {
        perror("open");
        return 1;
    }

    //重定向  //dup2(int oldfd, int newfd); //可以理解为用fd替换0
    dup2(fd, 0);

    char inbuffer[1024];
    ssize_t s = read(0, inbuffer, sizeof(inbuffer)-1);
    //s保存的是实际读取的字节数
    if(s > 0)
    {
        inbuffer[s] = '\0';//将第s个字节设置为\0  字符串结束
        printf("echo# %s\n", inbuffer);
    }
    
    close(fd);

    return 0;
}
//解释:本来是从键盘文件读的,但是写了输入重定向,就是直接从文件中读

运行的结果就直接将文件内容读出来了。//直接从文件里面读,就叫输入重定向

重定向的本质:其实就是对文件描述符表的内容的地址做修改

int fd = open(filename, O_CREAT|O_WRONLY|o_TRUNC,0666);

dup(fd,1);

printf("hello printf!\n");

fprintf(stdout,"hello fprintf\n");

//上面这两个函数是库函数,底层肯定有stdout

//int fprintf(FILE *stream, const char *format, ...);

命令行上:
echo "hello Linux" > log.txt

echo "heoll Linux" >> log.txt //追加重定向

cat < log.txt 

进程历史打开的文件与进行的各种重定向关系 都和未来进行程序替换无关! 程序替换并不影响文件访问!这也相当于形成了文件管理和进程管理的解耦!

stout && sterr 的区别

stdin->fd: 0     标准输入
stdout->fd: 1   标准输出   向显示器输出
stderr->fd:  2    标准错误   向显示器输出

都是向显示器输出,那两个有上面区别?????

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main()
{
    fprintf(stdout, "hello normal message\n");
    fprintf(stdout, "hello normal message\n");
    fprintf(stdout, "hello normal message\n");
    fprintf(stdout, "hello normal message\n");
    
    fprintf(stderr, "hell error message\n");
    fprintf(stderr, "hell error message\n");
    fprintf(stderr, "hell error message\n");
    fprintf(stderr, "hell error message\n");

    return 0;
}

上面的代码:

直接运行:

但是,当我们进行重定向时: 我们会发现 error message 没有被重定向 只有normal message被重定向了 因为normal信息打印的时候用的是stdout  这是标准输出  而 stderr是标准错误 我们只是使用了 > 进行了输出重定向(这是1),也就是让1不要指向显示器,指向我创建的文件(本质是:指针数组存的地址被改变了)

 error message 没有被重定向 只有normal message被重定向了  ' > '  是输出重定向   就是让1不要指向显示器 而是   直接指向你创建的文件   也就是说,让本来应打印到标准输出的信息 打印到了文件里

./mytest  1> normal.log  2> err.log  这样写就可以将normal信息和error信息都重定向到文件中。1其实可以不写,因为 > 本来就是输出重定向,但是要想重定向err信息(即标准错误输出)就必须加2

也可以将两个一起重定向  ./mytest >all.log 2>&1    1已经做了前面的   &1的意思就是将1里面的内容写到2里面    即 1先指向新创的文件  然后让2 里面的地址 也变成和1一样的(即同一个文件的地址)  因此两个就指向了同一个文件.

这就是为什么有时候用printf有时候用perror

  • 使用printf时,你主要是输出程序运行中的各种信息。
  • 使用perror时,你是在处理错误,并希望获取系统提供的错误描述。

2、缓冲区

#include<stdio.h>
#include<string.h>
#include<unistd.h>

int main()
{
    const char *fstr = "hello fwrite\n";
    const char *str = "hello write\n";

    //C语言提供的
    printf("hello printf\n");      //stdout->1
    fprintf(stdout, "hello fprintf\n");      //stdout->1
    fwrite(fstr,strlen(fstr), 1, stdout);      //stdout->1

    //操作系统提供的系统调用接口
    write(1, str, strlen(str));   //1
    fork();
    return 0;
}

补充:size_t fwrite(const void *ptr,  size_t size,   size_t nmemb,  FILE *stream);

fwrite的返回值其实是nmemb的个数.  4字节 10个4字节  返回的是写入到基本单位的个数.

运行上面的代码,正常打印四句.但是./myfile > log.txt  即重定向之后:

通过实验现象 我们可以发现 C接口被打印了两次.  但是系统调用接口的打印只有一次,也就是说,系统调用不会受其他东西的影响.  那么出现这样的现象是为什么呢??

我们再看一个代码.

#include<stdio.h>
#include<string.h>
#include<unistd.h>

  代码1 //
int main()
{
    const char *fstr = "hello fwrite\n";
    const char *str = "hello write\n";

   
    printf("hello printf\n");      //stdout->1
    fprintf(stdout, "hello fprintf\n");      //stdout->1
    fwrite(fstr,strlen(fstr), 1, stdout);      //stdout->1
    flose(1);
    return 0;
}

// 代码2 
int main()
{
    const char *fstr = "hello fwrite";
    const char *str = "hello write";

   
    printf("hello printf");      //stdout->1
    fprintf(stdout, "hello fprintf");      //stdout->1
    fwrite(fstr,strlen(fstr), 1, stdout);      //stdout->1
    flose(1);
    return 0;
}
/ 代码3 
int main()
{
    const char *str = "hello write";

    write(1, str, strlen(fstr), 1, stdout);
    flose(1);
    return 0;
}

代码1 和 代码2 的区别就是1 有\n 而代码2 没有,那为什么有\n,就算close(1)  也可以打印出三条打印信息呢???     为什么3 可以打印出hello write  ??

printf/fprintf/fwrite/ fputs......---->C的库函数

他们的底层一定调用write(系统调用)

其实,调用printf  fprintf fwrite 这些函数是,其实已经将这些字符串 写进缓冲区  里了,只不过这个缓冲区一定不在OS内.  因为,如果在系统级别的缓冲区,当close的时候,因为close也是系统级别的,一定会将缓冲区的内容刷新出来,但是我们并没有看到这样的现象,因此,可以说明这个缓冲区不是系统级别的缓冲区!!!!!       他们不是通过write将数据写到内核缓冲区的.

就像write是系统调用接口,它是直接写到系统缓冲区里面close的时候将数据刷出来.  C语言其实会给我们提供一个缓冲区,这个缓冲区是用户级别的, 调用库函数就是将数据写入到用户级别的缓冲区里面,当到合适的时候,比如说:碰到了强制刷新 、close fclose文件描述符 、 或者字符串里面有\n   这样C库才会自动调用write将数据写到系统的缓冲区中,然后刷新出来.


但是,要刷的时候如果1号文件描述符被关闭了 就刷不出来了

显示器的文件的刷新方式是行刷新,所以在printf执行完的时候,如果遇到\n 将数据立即进行刷新  eg:将上面的字符串都带上\n  然后close(1)   即使这样还是能打印出来 (因为在close(1) 之前,数据就已经被写到了操作系统里) 但是去掉  \n  就只有write系统调用才能打印出来.

总结一下:当close(1)之后,用户级别的缓冲区的数据就不会刷新到内核级别的缓冲区中了。刷新的本质就是将数据通过1 + write 写入到内核中.而且,目前我们认为,只要将数据刷新到内核,数据就可以到硬件了。操作系统会自动帮我们把数据写到磁盘/显示器。

缓冲区的刷新策略(用户级别的缓冲区):a、无缓冲:直接刷新   b、行缓冲:不刷新,直到碰到\n(显示器的)   c、全缓冲:缓冲区满了才刷新  (文件写入)  根据缓冲区的刷新策略来决定什么时候调write()系统调用将数据写到缓冲区里。

补充问题:

1、进程退出的时候数据也会被刷新

2、为什么要有这个缓冲区(用户级别的)

a、解决效率问题---用户的效率问题

b、配合格式化

3、这个缓冲区在哪?
我们之前说过FILE里面肯定封装了fd,其实里面还有对应打开文件的缓冲区字段和维护信息

fprintf(stdout,"hello world\n");

stdout是FILE*类型的,这个结构体里面{int fd = 1; 缓冲区}  hello world就是先放到这个缓冲区里面的,等到合适的时候,调用write刷新到系统缓冲区。

这个FILE对象属于用户级别呢?还是操作系统级别?

语言都属于用户层

这个缓冲区,是不是属于用户级的缓冲区呢?

答案是:是的!FILE *fopen(const char *path, const char *mode)  fopen的返回值为什么是FILE*
fopen是C标准库给我们提供的接口, 调用open在内核层建立内核级别的文件对象,并且拿到文件描述符;在语言层 malloc(FILE) 所以返回的就是FILE*   这个FILE里面就帮我们封装了文件描述符和缓冲区  也就是说,这个空间在C标准库里面已经帮我们做好了。

那么,我们再回头看一下之前的问题

#include<stdio.h>
#include<string.h>
#include<unistd.h>

int main()
{
    const char *fstr = "hello fwrite\n";
    const char *str = "hello write\n";

    //C语言提供的
    printf("hello printf\n");      //stdout->1
    fprintf(stdout, "hello fprintf\n");      //stdout->1
    fwrite(fstr,strlen(fstr), 1, stdout);      //stdout->1

    //操作系统提供的系统调用接口
    write(1, str, strlen(str));   //1
    fork();
    return 0;
}

重定向之后,由向显示器写入变成向文件写入。那么缓冲区的刷新策略也就由  行刷新变成全刷新。只有当缓冲区被写满的时候才进行刷新。 write是系统调用,所以hello write先被打印 而且他不会受其他东西的影响,所以只打印一次。fork()创建了子进程, 因为进程退出会刷新缓冲区,那么子进程也要对缓冲区的数据进行刷新,这也就相当于之前所说的对数据的写入,子进程就要将缓冲区需要刷新的数据给自己拷贝一份。 因此 子进程和父进程结束的时候都会刷出数据。

没有发生重定向时,是行刷新,在没有fork之前,这些数据就已经被刷到系统缓冲区,在调用fork之后,用户缓冲区是没有数据的。因此就只打印四句。

3、简单模拟实现C文件标准库

main.c

#include "Mystdio.h"

int main()
{
    _FILE *fp = _fopen("test.txt", "w");
    if(fp == NULL) return 1;

    const char *msg = "hello world";
    
    _fwrite(fp, msg, strlen(msg));
   // _fclose(fp);
    
    _fclose(fp);

    return 0;
}

Mystdio.h

#ifndef __MYSTDIO_H__
#define __MYSTDIO_H__

#include <string.h>

#define SIZE 1024
//刷新方式
#define FLUSH_NOW 1 
#define FLUSH_LINE 2 
#define FLUSH_ALL 4

//创建FILE结构体
typedef struct IO_FILE{
    
    int fileno;
    int flag;
    //char inbuffer[SIZE];//输入缓冲区
    //int in_pos;
    char outbuffer[SIZE]; //输出缓冲区  //用一下这个
    int out_pos;//代表输出缓冲区被使用了多少
    //在系统看来这个buffer没有类型,由上层的printf、scanf自己去解释

}_FILE

_FILE *_fopen(const char*filename, const char *flag);//打开文件的名字  打开文件的模式
int _fwrite(_FILE *fp, const char *s, int len);
void _fclose(_FILE *fp);

#endif

Mystdio.c

#include "Mystdio.h"
#inckude <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>

#define FILE_MODE 0666  //权限

_FILE *_fopen(const char*filename, const char *flag) //文件名称  打开模式
{
    //flag -> "w" "a" "r" 演示三种     
    
    assert(filename);
    assert(flag);

    int f = 0;
    int fd = -1;
    if(strcmp(flag, "w") == 0) {
        f = (O_CREAT|O_WRONLY|O_TRUNC);
        fd = open(filename, f, FILE_MODE);
    }
    else if(strcmp(flag, "a") == 0) {
        f = (O_CREAT|O_WRONLY|O_APPEND);
        fd = open(filename, f, FILE_MODE);
    }
    else if(strcmp(flag, "r") == 0) {
        f =  O_RDONLY;
        fd = open(filename, f);
    }
    else 
        errno = 2; return NULL;

    if(fd == -1)   return NULL;//文件打开失败
    //文件打开成功
    //创建文件对象让别人用

    _FILE *fp = (FILE*)malloc(sizeof(_FILE));
    if(fp == nuLL)  return NULL;  //文件创建失败

    fp->fileno = fd;
    fp->flag = FLUSH_LINE;
    fp->out_pos = 0;
    
    return fp;
}

int _fwrite(_FILE *fp, const char *s, int len)
{
    memcpy(&fp->outbuffer[fp->out_pos], s, len);  //将s复制到输出缓冲区里面
    fp->out_pos  += len;  //更新缓冲区    

    if(fp->flag & FLUSH_NOW) //立即刷新
    {
        write(fp->fileno, fp->outbuffer, len);//文件描述符  数据在哪里 要写入的字符的个数
        fp->out_pos = 0;//缓冲区刷新完之后清空pos
    }
    else if(fp->flag & FLUSH_LINE) 
    {
        if(fp->outbuffer[fp->out_pos - 1] == '\n') {
            write(fp->fileno, fp->outbuffer, len);
            fp->out_pos = 0;
        }
    }
    else if(fp->flag & FLUSH_ALL)
    {
        if(fp->out_pos ==SIAE){
            write(fp->fileno, fp->outbuffer, fp->out_pos);
            fp->out_pos = 0;
        }
    }

    return len;
}

_fflush(_FILE *fp)
{
    if(fp->out_pos > 0){
    write(fp->fileno, fp->outbuffer, fp->out_pos);
    fp->out_pos = 0;
    }
}

void _fclose(_FILE *fp)
{
    if(fp == NULL) return;
    //在关闭文件之前,需要强制对缓冲区中的数据进行刷新
    _fflush(fp);
    close(fp->fileno);
    free(fp);
}

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

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

相关文章

Java(三十) --- 基于比较的七大比较的排序算法(巨详细)

文章目录 前言1. 排序的概念和引用2.直接插入排序3.希尔排序(缩小增量排序)4. 直接选择排序5. 堆排序6. 冒泡排序7.快速排序7.1.Hoare法7.2.挖坑法7.3.快速排序的优化7.4.非递归方法 8.归并排序8.1.递归方法8.2.非递归方法8.3 海量数据的排序问题 9. 七大比较排序的复杂度以及稳…

构建安全基石:网络安全等级保护定级指南

在数字化时代&#xff0c;网络安全已成为企业与个人不可忽视的重要课题。网络安全等级保护定级指南&#xff0c;作为国家指导网络安全保护的重要文件&#xff0c;为各类机构提供了精准的安全防护蓝图。本文旨在深度解析网络安全等级保护定级指南的精髓&#xff0c;助力建构全面…

Docker-在Centos中部署Shell脚本获取镜像并构建容器

环境准备 1.Centos 7系统 参考&#xff1a;Centos安装 2.demo镜像推送到阿里云 参考demo镜像推送到阿里云 Centos操作 1.修改demo中相关配置springboot-docker-demo\bin\docker-deploy.sh ## 仓库地址 REGISTRY_SERVER公有网络域名 ## 用户名 USERNAME阿里云账号 ## 密码 P…

背包问题全解

文章目录 01背包一、01背包模板二、采药三、装箱问题四、宠物小精灵之收服五、数字组合 完全背包六、完全背包模板七、买书八、货币系统&#xff08;简单版&#xff09;九、货币系统&#xff08;进阶版&#xff09; 01背包 一、01背包模板 还有个疑惑&#xff0c;为什么最大价…

【高阶数据结构】红黑树的插入(超多精美图解+完整代码)

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《高阶数据结构》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多《高阶数据结构》点击专栏链接查看&a…

51单片机应用开发(进阶)---外部中断(按键+数码管显示0-F)

实现目标 1、巩固数码管、外部中断知识 2、具体实现&#xff1a;按键K4&#xff08;INT1&#xff09;每按一次&#xff0c;数码管从0依次递增显示至F&#xff0c;再按则循环显示。 一、共阳数码管 1.1 共阳数码管结构 1.2 共阳数码管码表 共阳不带小数点0-F段码为&#xff…

MacOS上Homebrew 安装、配置、更改国内镜像源及使用教程

Homebrew笔记 1. 介绍 官网&#xff1a;https://brew.sh/ 对于习惯了使用命令来完成一切的程序员来说&#xff0c;安装软件这种小事&#xff0c;自然是能够用命令解决&#xff0c;就不用图形界面选择。但是在 Linux 中&#xff0c;我们有 yum、apt、dnf、pkg等命令来完成软件的…

LeetCode 热题 100之链表1

1.相交链表 思路分析&#xff08;直接上双指针&#xff09;&#xff1a; 初始化两个指针&#xff0c;分别指向两个链表的头节点 headA 和 headB遍历两个链表&#xff0c;当指针到达链表的末尾时&#xff0c;将指针移动到另一个链表的头部 如果链表相交&#xff0c;两个指针会在…

【含开题报告+文档+PPT+源码】基于SSM的旅游与自然保护平台开发与实现

开题报告 围场县拥有丰富的自然景观和野生动植物资源&#xff0c;同时面临着旅游业发展和自然保护之间的平衡问题&#xff0c;通过强调自然保护&#xff0c;这个平台可以教育游客如何尊重和保护当地的生态环境。同时&#xff0c;平台还可以提供关于生态保护的信息&#xff0c;…

立仪光谱共焦在玻璃上奥秘与应用

在现代工业和科学研究中&#xff0c;玻璃因其透明、坚硬和易加工的特性被广泛应用于各个领域。然而&#xff0c;玻璃的厚度测量一直是困扰业界的一大难题。传统的千分尺或电容式传感器虽然在一定程度上能满足生产需求&#xff0c;但在精度、效率以及适用范围上存在明显的局限。…

中航资本:市盈率静和动分别是什么意思?市盈率静和动看哪个准?

市盈率静和动别离是什么意思&#xff1f; 市盈率静就是指静态市盈率&#xff0c;是以最新一期的年报为核算根据&#xff0c;其数据核算公式为&#xff1a;总市值最新一期的年报的净利润&#xff0c;年报的净利润可所以作用快报或作用预告发布的数据。 市盈率动就是动态市盈率…

动态规划 - 背包问题 - 完全背包

完全背包物品数量无限制&#xff0c;可以使用多次的实现方式&#xff1a;背包正序遍历 0-1背包&#xff1a;先物品后背包&#xff0c;物品正序、背包倒序&#xff08;保证每个物品只用一次&#xff09; 完全背包&#xff1a;先后顺序都可以&#xff0c;物品正序、背包正序 如果…

基于卷积神经网络的苹果病害识别与防治系统,resnet50,mobilenet模型【pytorch框架+python源码】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 苹果病害识别与防治系统&#xff0c;卷积神经网络&#xff0c;resnet50&#xff0c;mobilenet【pytorch框架&#xff0c;python源码】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于卷积…

appium+mumu模拟器 嚼碎菜鸟教程

1、android sdk 下载安装 下载地址&#xff1a;https://www.androiddevtools.cn/index.html# 选择版本&#xff1a;android sdk【sdk tools:installer_r24.4.1-windows.exe】 参考步骤&#xff1a;https://blog.csdn.net/2401_83004375/article/details/139300339 2、jdk 安装…

day11:磁盘管理

一&#xff0c;磁盘概述 磁盘概述 磁盘是一种持久性存储设备&#xff0c;用于存储操作系统、应用程序和数据。磁盘通常分为**机械硬盘&#xff08;HDD&#xff09;和固态硬盘&#xff08;SSD&#xff09;**两种&#xff0c;HDD 基于旋转的磁性盘片&#xff0c;而 SSD 基于闪存…

【WRF数据处理】基于GIS4WRF插件将geotiff数据转为tiff(geogrid,WPS所需数据)

【WRF数据处理】基于GIS4WRF插件将geotiff数据转为tiff&#xff08;geogrid&#xff0c;WPS所需数据&#xff09; 数据准备&#xff1a;以叶面积指数LAI为例QGis实操&#xff1a;基于GIS4WRF插件将geotiff数据转为tiff警告&#xff1a;GIS4WRF: Input layer had an unexpected …

ES8JC-ASEMI超快恢复二极管ES8JC

编辑&#xff1a;ll ES8JC-ASEMI超快恢复二极管ES8JC 型号&#xff1a;ES8JC 品牌&#xff1a;ASEMI 封装&#xff1a;SMC 安装方式&#xff1a;贴片 批号&#xff1a;最新 恢复时间&#xff1a;35ns 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;8A 最大循…

ECCV 2024论文分享┆Agent Attention: Softmax注意力和线性注意力的高效融合

简介 本推文主要介绍了由清华大学黄高老师团队发表在ECCV 2024上的一篇论文《Agent Attention: On the Integration of Softmax and Linear Attention》&#xff0c;文中提出了一种新型的代理注意力&#xff08;Agent Attention&#xff09;。近年来&#xff0c;Transformer在…

Github 2024-10-29Python开源项目日报 Top10

根据Github Trendings的统计,今日(2024-10-29统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10TypeScript项目1gpt4free存储库:强大语言模型的集合 创建周期:300 天开发语言:Python协议类型:GNU General Public License v3…

【Java】逻辑控制 —— 三大结构 和 猜数字游戏

目录 1. 顺序结构 2. 分支结构【与C略有不同】 2.1 if语句 2.2 switch语句 注意事项【与C不同】 3. 循环结构【与C略有不同】 3.1 while循环 * break和continue 3.2 for循环 3.3 do while循环 * 输入的判断&#xff08;hasNext&#xff09; 4. 猜数字游戏 1. 顺序结…