【Linux】文件基础IO操作:C语言接口 | 系统调用接口 | 重定向

news2024/10/6 14:32:41

  • 重修C语言文件知识
  • Linux文件知识
    • 标记位传参
    • 文件的系统调用
    • 理解什么是文件
    • 文件fd的分配规则
    • 重定向
    • C语言文件层面的缓冲区知识

重修C语言文件知识

  1. 打开文件操作fopen函数:

在这里插入图片描述
我们看一段代码,以写(w)的形式来打开文件:

#include <stdio.h>

#define FILE_NAME "log.txt"
int main()
{
   FILE* fp = fopen(FILE_NAME,"w");
   if(NULL==fp)
   {
       perror("fopen");
       return 1;
   }
   fclose(fp);
   return 0;
}

一开始我们并没有创建文件,程序运行会自动创建一个log.txt的文件
在这里插入图片描述

  1. 打印输出到文件fprintf函数

在这里插入图片描述

#include <stdio.h>

#define FILE_NAME "log.txt"
int main()
{
   FILE* fp = fopen(FILE_NAME,"w");
   if(NULL==fp)
   {
       perror("fopen");
       return 1;
   }
   fprintf(fp,"%s\n","hello world!");
   fclose(fp);
   return 0;
}

运行程序,fprintf 会发送格式化输出到流 stream
在这里插入图片描述
w的方式对文件进行操作,文件的内容会被先清空,再进行操作
在这里插入图片描述

  1. 打开文件操作读(r)的方式,fgets函数从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内

在这里插入图片描述

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

#define FILE_NAME "log.txt"
int main()
{
   FILE* fp = fopen(FILE_NAME,"r");
   if(NULL==fp)
   {
       perror("fopen");
       return 1;
   }
   char buffer[64];
   while(fgets(buffer,sizeof(buffer)-1,fp) != NULL)
   {
       buffer[strlen(buffer)-1]=0;
       puts(buffer);
   }
   fclose(fp);
   return 0;
}

这个while循环可写可不写,这样写的作用也就是保证buffer最后一个字符是终止符号
下面输出的结果就是将log.txt中的数据输出出来
在这里插入图片描述

4.打开文件操作追加(a)的方式

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

#define FILE_NAME "log.txt"
int main()
{
   FILE* fp = fopen(FILE_NAME,"a");
   if(NULL==fp)
   {
       perror("fopen");
       return 1;
   }
   int count=5;
   while(count)
   {
       fprintf(fp,"%s:%d\n","hello world!!",count--);
   }
   fclose(fp);
   return 0;
}

在这里插入图片描述

打开文件相关方式:

  • “r” “只读”,只允许读取,不允许写入。文件必须存在,否则打开失败
  • “w” “写入”。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容
  • “a” “追加”。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)
  • “r+” “读写”。既可以读取也可以写入,也就是随意更新文件。文件必须存在,否则打开失败
  • “w+” “写入/更新”,相当于w和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容
  • “a+” “追加/更新”,相当于a和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)
  • “t” 文本文件。如果不写,默认为"t"。
  • “b” 二进制文件。

5.在linux下新建文件默认权限=0666,受到umask的影响,实际创建的出来的文件权限是: mask & ~umask
在这里插入图片描述
 C语言有文件的操作接口,那么C++、Java、python、php、GO等语言同样也有文件操作接口,但是它们的接口都不一样。
 而文件在哪?在磁盘,磁盘是硬件,而需要访问硬件都必须要操作系统OS来管理,使用OS给的文件级别的系统调用,操作系统只有一个,但是语言有很多个:库函数底层必须使用系统调用接口、库函数可以变化但是底层不变。


Linux文件知识

我们使用man 2来了解有关文件的系统调用知识,它与C语言有什么不同呢?

标记位传参

通过以下代码来解释什么是标记位传参:

#define ONE (1<<0)
#define TWO (1<<1)
#define THREE (1<<2)
#define FOUR (1<<3)

void show(int flag)
{
    if(flag & ONE)printf("one\n");
    if(flag & TWO)printf("two\n");
    if(flag & THREE)printf("three\n");
    if(flag & FOUR)printf("four\n");
}
int main()
{
    show(ONE);
    printf("---------\n");
    show(TWO);
    printf("---------\n");
    show(ONE | TWO);
    printf("---------\n");
    show(ONE | TWO | THREE);
    printf("---------\n");
    show(ONE | TWO | THREE | FOUR);
    return 0;
}

标记对应比特位,每一个宏对应的数值,只有一个比特位是1,彼此不会重叠,如果想要互相结合就或(|),函数里面通过与(&)来判断,这样就相当于可以传入多个参数
在这里插入图片描述

文件的系统调用

1.系统调用打开文件open
在这里插入图片描述在这里插入图片描述
pathname: 要打开或创建的目标文件
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数: 前三个常量,必须指定一个且只能指定一个

  • O_RDONLY: 只读打开

  • O_WRONLY: 只写打开

  • O_RDWR : 读写打开

  • O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限

  • O_APPEND: 追加写

使用系统调用来打开文件O_WRONLY

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FILE_NAME "log.txt"
int main()
{
    int fp = open(FILE_NAME,O_WRONLY);
    if(fp < 0)
    {
        perror("open");
        return 1;
    }
    close(fp);
    return 0;
}

在C语言中我们使用读的形式打开文件可以直接成功,但是在系统调用中我们使用只使用读的形式访问文件,是会失败的。
在这里插入图片描述
我们必须要更改代码为:

    int fp = open(FILE_NAME,O_WRONLY | O_CREAT);

更改后创建出来的文件是乱码:
在这里插入图片描述
凭什么认为Linux一创建文件就按照比如666、777去创建?我们在C语言中使用的是已经封装过的系统调用,他会自动生成权限,而系统调用没有这些东西,他需要自己去传参,所有我们最后还需要传入作为权限的参数:

    int fp = open(FILE_NAME,O_WRONLY | O_CREAT, 0666);

在这里插入图片描述
在这里插入图片描述

更改umask的值
在这里插入图片描述

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FILE_NAME "log.txt"
int main()
{
    umask(0);
    int fp = open(FILE_NAME,O_WRONLY | O_CREAT,0666);
    if(fp < 0)
    {
        perror("open");
        return 1;
    }
    close(fp);
    return 0;
}

我们在创建访问之前将umask的值更改为0,使用我们传入的权限值去初始化,最后这个log.txt的权限值就是666
在这里插入图片描述

我们再访问shell中umask的值发现它还是0002,这是为什么,我们不是刚刚已经修改了,而且创建出来的文件权限也是按照更改后的umask初始的?这是因为我们程序里面的umask是这个子进程在执行,而与shell这个父进程无关系,子进程只能改变自己的文件权限,所以我们更改的时候不会影响shell。
在这里插入图片描述

  1. 向文件写入write

在这里插入图片描述

ssize_t是有符号整型,在32位机器上等同与int,在64位机器上等同与long int.

open函数返回值:
我们以读的形式打开(或创建)文件,并打印出open函数的返回值

int main()
{
    umask(0);
    int fp = open(FILE_NAME,O_WRONLY | O_CREAT,0666);
    if(fp < 0)
    {
        perror("open");
        return 1;
    }
    printf("fp:%d\n",fp);
    close(fp);
    return 0;
}

为什么这个打印的值是3呢?且看目录中的理解什么是文件详细讲述
在这里插入图片描述

ssize_t write(int fd, const void *buf, size_t count);

 读写文件有两种读写方案:文本类、二进制类(而这些文件读取的分类是语言本身提供的)
而操作系统就很简单粗暴,直接以void*方式返回,在操作系统看来都是二进制,操作系统只会管你要写几个字节,而不会管你具体内容(不管你是图片还是字符串什么的,只认二进制)

 假如我们也想像C语言那样写入hello word!! 并加上数字。一个是字符串、一个是数字,那么我们如何使用系统调用来实现呢?
在这里插入图片描述

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FILE_NAME "log.txt"

int main()
{
    umask(0);
    int fp = open(FILE_NAME,O_WRONLY | O_CREAT,0666);
    if(fp < 0)
    {
        perror("open");
        return 1;
    }
    int count = 3;
    char arr[64];
    while(count)
    {
        sprintf(arr,"%s:%d\n","hello world!!",count--);
        write(fp,arr,strlen(arr));
    }
    close(fp);
    return 0;
}

我们使用sprintf将字符串写入数组中,然后使用write将数组写入文件
在这里插入图片描述
我们的write(fp,arr,strlen(arr));这个代码strlen不需要加1来存储\0,如果加了会出现乱码,因为以\0作为字符串的结束符是C语言规定的,和系统调用层面的文件操作没有关系

在C语言中,以写的方式打开文件会直接删除掉原数据,但是在系统调用的时候则是覆盖式的比如:
更改之前代码为:

sprintf(arr,"%s:%d\n","aaaaaa!!",count--);

在这里插入图片描述
我们在系统调用还需要传入一个O_TRUNC,才能实现出在C语言中w的效果:

    int fp = open(FILE_NAME,O_WRONLY | O_CREAT | O_TRUNC,0666);

在这里插入图片描述
在这里插入图片描述
追加就是将O_TRUNC跟换为O_APPEND

    int fp = open(FILE_NAME,O_WRONLY | O_CREAT | O_APPEND,0666);

在这里插入图片描述

  1. 读文件read函数

在这里插入图片描述

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FILE_NAME "log.txt"

int main()
{
    umask(0);
    int fp = open(FILE_NAME,O_RDONLY);
    if(fp < 0)
    {
        perror("open");
        return 1;
    }
    char buffer[1024];
    ssize_t num = read(fp,buffer,sizeof(buffer)-1);
    if(num>0)buffer[num]=0;
    printf("%s",buffer);
    close(fp);
    return 0;
}

sizeof(buffer)-1这段作用是为填写终止符留出空间
buffer[num]=0;这个语句的作用是添加结束符(0、\0、NULL),因为在C语言中的函数会自己写,而系统调用需要我们自己去写
在这里插入图片描述
在这里插入图片描述

理解什么是文件

文件操作的本质:进程 + 被打开文件 的关系

进程可以打开多个文件么?答案是肯定的,进程很多,同样系统一定会存在大量的被打开文件,那么这些被打开文件肯定也需要被操作系统OS管理起来,先描述再组织 -> OS为了管理对应的打开文件,必定会为文件创建对应的内核数据结构标识文件:struct file{}(包含了大部分属性)

我们通过下面代码来理解文件:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FILE_NAME(number) "log.txt"#number//把参数转化为字符串,然后合起来
int main()
{
    int fd0 = open(FILE_NAME(1), O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd1 = open(FILE_NAME(2), O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd2 = open(FILE_NAME(3), O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd3 = open(FILE_NAME(4), O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd4 = open(FILE_NAME(5), O_WRONLY | O_CREAT | O_APPEND, 0666);
    
    printf("fd: %d\n", fd0);
    printf("fd: %d\n", fd1);
    printf("fd: %d\n", fd2);
    printf("fd: %d\n", fd3);
    printf("fd: %d\n", fd4);
    
    close(fd0);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    return 0;
}

通过下面的输出结果我们发现:为什么open返回值从3开始?012又去了哪里?连续的小整数,一般情况我们只在数组下标才有所对应
在这里插入图片描述
三个标准输入输出流:

  • stdin—键盘
  • stdout—显示器
  • stderr—显示器

FILE* fp = fopen();这个FILE是结构体,它里面有一个字段是文件描述符

在这里插入图片描述

我们增加下面代码:

	printf("stdin->fd: %d\n", stdin->_fileno);
    printf("stdout->fd: %d\n", stdout->_fileno);
    printf("stderr->fd: %d\n", stderr->_fileno);

从输出结果我们可以看出,012在哪是什么了:三个标准输入输出提前占用了012
在这里插入图片描述

为什么这些输出的数字是为数组下标?且看下图
在这里插入图片描述
通过上面的学习,我们知道了文件描述符就是一个小整数:

  • Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2.
  • 0,1,2对应的物理设备一般是:键盘,显示器,显示器

上图可知:文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件

文件描述符的本质,就是数组的下标!

文件fd的分配规则

我们首先做一个结果分析:

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

#define FILE_NAME "log.txt"
int main()
{
    //close(0);
    umask(0);
    int fd = open(FILE_NAME,O_WRONLY | O_CREAT,0666);
    if(fd < 0)
    {
        perror("open");
        return 1;
    }
    printf("fd:%d\n",fd);
    close(fd);
    return 0;
}

打印的结果是3,这是我们上面解释过的
在这里插入图片描述

我们在main函数刚开始的地方先close(0);看看输出结果:
在这里插入图片描述

我们在main函数刚开始的地方先close(2);看看输出结果:
在这里插入图片描述

我们在main函数刚开始的地方先close(0);close(2);看看输出结果:
在这里插入图片描述

正常情况我们会自动打开三个标准输入输出,我们加载一个文件就会从3开始:
在这里插入图片描述
但是,如果我们关闭掉一个会怎么样呢?
在这里插入图片描述

如果我们关闭close(1);会出现什么情况呢?
在这里插入图片描述
我们发现,显示器上并没有打印的结果,这是为什么呢?且看下面解释:
在这里插入图片描述

    printf("fd:%d\n",fd);
    fprintf(stdout,"fd:%d\n",fd);

这两个printf的结果都是一样:
在这里插入图片描述
在这里插入图片描述

上面结果可以说明printf本质上就是打印输出到stdout中,现在我们将stdout先关闭了,然后创建的新struct_file占据了原本的stdout的位置,所以我们可以认为现在的printf输出应该输出到新创建的文件log.txt中,但是我们cat log.txt发现里面并没有数据,难道我们的结论是错误的?不是的,这里是因为缓冲区的缘故。

我们在最后刷新一下fflush(stdout);,我们这里刷新的是stdout,且最后输出的结果就是fd:1,证明确实是分配的1号位
在这里插入图片描述

本来输出打印应该打印到stdout显示器上,但是我们现在关闭close(1);却将打印的结果打印到了新创建的文件中,这种特性叫做重定向

重定向

如果我们也想实现跟刚才一样的显示效果,将原本打印到显示器上的数据,输出到新建文件中去:
在这里插入图片描述
在这里插入图片描述
我们需要将1号位中的数据替换为新建文件fd,那么最终留下来的肯定是fddup2调用是将newfd中的内容替换为oldfd,留下来的是oldfd,所以我们使用dup2调用需要:dup2(fd,1);

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FILE_NAME "log.txt"
int main()
{
    umask(0);
    int fd = open(FILE_NAME,O_WRONLY | O_CREAT,0666);
    if(fd < 0)
    {
        perror("open");
        return 1;
    }
    dup2(fd,1);
    printf("fd:%d\n",fd);
    fprintf(stdout,"fd:%d\n",fd);
    fflush(stdout);
    close(fd);
    return 0;
}

这样我们就完成了一个重定向功能
在这里插入图片描述

追加重定向O_APPEND + dup2(fd,1);

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define FILE_NAME "log.txt"
int main()
{
    umask(0);
    int fd = open(FILE_NAME,O_WRONLY | O_CREAT | O_APPEND,0666);
    if(fd < 0)
    {
        perror("open");
        return 1;
    } 
    dup2(fd,1);
    printf("fd:%d\n",fd);
    fprintf(stdout,"fd:%d\n",fd);
    const char* msg = "hello world";
    write(1, msg, strlen(msg));
    fflush(stdout);
    close(fd);
    return 0;
}

持续运行./Test,将输出内容追加到log.txt
在这里插入图片描述

输入重定向dup2(fd,0);

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define FILE_NAME "log.txt"
int main()
{
    umask(0);
    int fd = open(FILE_NAME,O_RDONLY);
    if(fd < 0)
    {
        perror("open");
        return 1;
    }
    dup2(fd,0);
    char arr[64];
    while(1)
    {
        printf("输入> ");
        if(fgets(arr, sizeof(arr), stdin) == NULL)break;
        printf("%s",arr);
    }
    close(fd);
    return 0;
}

通过dup2(fd,0);log.txt里面的数据用做标准输入,while循环的作用是将标准输入中的数据拿出来存放入数组中,然后将其打印出来
在这里插入图片描述

如果我们在父进程中创建子进程,然后这个子进程做重定向操作会影响父进程吗?
在这里插入图片描述
程序替换,同样不会影响曾经进程打开过的重定向文件,重定向的各种操作属于内核数据结果,而程序替换则是磁盘与内存的代码数据替换,二者不会影响到。

常见的重定向有:> >> <
 我们分别使用一下:

  1. <输出重定向
    在这里插入图片描述
  2. >输入重定向
    在这里插入图片描述
  3. >>追加重定向
    在这里插入图片描述

C语言文件层面的缓冲区知识

我们先运行下面代码:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
    // C语言接口
    printf("hello printf\n");
    fprintf(stdout, "hello fprintf\n");
    fputs("hello fputs\n", stdout);

    // 系统调用
    const char *msg = "hello write\n";
    write(1, msg, strlen(msg));

    return 0;
}

在这里插入图片描述
我们将输出的结果重定向到log.txt文件中,可以发现打印的结果是一样的
在这里插入图片描述
但是如果我们将代码更改一下,在结尾创建子进程:

int main()
{
    // C语言接口
    printf("hello printf\n");
    fprintf(stdout, "hello fprintf\n");
    fputs("hello fputs\n", stdout);

    // 系统调用
    const char *msg = "hello write\n";
    write(1, msg, strlen(msg));

    fork();
    //do nothing -> return quit
    return 0;
}

在这里插入图片描述
还是一样的操作,但是在我们创建子进程后的,将输出重定向到log.txt,我们发现C语言接口打印了两遍,而系统调用只打印了一次
在这里插入图片描述

缓冲区刷线策略问题:
 缓冲区一定会结合具体的设备,定制自己的刷新策略

  • 立即刷新 – 无缓冲
  • 行刷新 – 行缓冲 – 显示器
  • 缓冲区满 – 全缓冲 – 磁盘文件
  • 用户强制刷新,比如fflush
  • 进程退出 – 一般都要进行缓冲区刷新

上面的出现的现象,一定与缓冲区有关,且缓冲区一定不在内核中,因为如果在内核中,write也会打印两次。我们之前谈论过的缓存区,都是指的用户级语言层面给我们提供的缓冲区,我们之前的输出输出操作都要传入 -> stdout stdin stderr 它们都是FILE*类型的,而FILE是一个结构体,这个结构体里面封装了fd还有一个缓冲区,所以我们刷新缓冲区都是fflush(文件指针)fclose(文件指针)

解释上面现象:
代码结束之前,进行创建子进程
1.如果我们没有进行重定向>,看到了4条消息,stdout 默认使用的是行刷新,在进程fork之前,三条C函数已经将数据进行打印输出到显示器上(外设),我们的FILE内部,进程内部不存在对应的数据了
2.如果我们进行了重定向>,写入文件不再是显示器,而是普通文件,采用的刷新策略是全缓冲,之前的3条c显示函数,虽然带了\n,但是不足以让stdout缓冲区写满,数据并没有被刷新!!!
执行fork的时候,stdout属于父进程,创建子进程时,紧接着就是进程退出,谁先退出,一定要进行缓冲区刷新(就是修改),修改就会发生写时拷贝,数据最终会显示两份
3. write为什么没有呢?上面的过程都和wirte无关,wirte没有FILE,而用的是fd,就没有C提供的缓冲区


如有错误或者不清楚的地方欢迎私信或者评论指出🚀🚀

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

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

相关文章

Web服务器群集:部署Tomcat

目录 一、理论 1.Tomcat 2.JDK 3.Tomcat安装 4.Tomcat优化 5.Tomcat虚拟主机设置 二、实验 1.JDK安装 2.Tomcat安装 3.Tomcat优化 4.Tomcat 虚拟主机配置 三、总结 一、理论 1.Tomcat &#xff08;1&#xff09;概念 Tomcat服务器是一个免费的开放源代码的Web应用…

emscripten的安装

参考&#xff1a;1.1 安装Emscripten-C/C面向WebAssembly编程 下载emsdk&#xff08;emscripten&#xff09;&#xff0c;git地址&#xff1a;git clone GitHub - emscripten-core/emsdk: Emscripten SDK打开emsdk中emsdk.bat所在的目录&#xff0c;进入cmd&#xff0c;输入 e…

Node.js健康检查和过载保护

[图片来源&#xff1a;unsplash.com[1]] 设想一下&#xff0c;你有30个Node服务器与 "Nginx "服务器平衡。服务器的负载被平均分配&#xff0c;所以如果你有9000个用户&#xff0c;每个服务器有300个客户。把负载平均分配给每台服务器并不意味着你可以避免过载&#…

linux下MySQL忘记密码解决方法

背景&#xff1a;自己搭建了很多测试环境&#xff0c;有的时候&#xff0c;某一台机器上面的MySQL密码可能就忘了&#xff0c;这种情况怎么办&#xff1f;记录一下解决方法&#xff0c;便于以后迅速解决这一类问题 第一步&#xff1a;查看MySQL的进程是否存活 ps -ef|grep my…

CMU15-445 2022 Fall 通关记录 —— Project 2:B+ Tree(上篇)

Project 2&#xff1a;B Tree Project #2 - BTree | CMU 15-445/645 :: Intro to Database Systems (Fall 2022) NOTE&#xff1a; 记录完成该Pro中&#xff0c;一些可能会遇到的问题&#xff1a; 本实验中&#xff0c;有很多API是需要自己去实现的&#xff0c;因此&#xf…

NLP入门:word2vec self-attention transformer diffusion的技术演变

这一段时间大模型的相关进展如火如荼&#xff0c;吸引了很多人的目光&#xff1b;本文从nlp领域入门的角度来总结相关的技术路线演变路线。 1、introduction 自然语言处理&#xff08;Natural Language Processing&#xff09;&#xff0c;简称NLP。这个领域是通过统计学、数…

自学黑客(网络安全),一般人我劝你还是算了吧(自学网络安全学习路线--第十七章 网络安全技术下)【建议收藏】

文章目录 一、自学网络安全学习的误区和陷阱二、学习网络安全的一些前期准备三、自学网络安全学习路线一、扫描工具赏析1、扫描工具概述2、如何获取扫描工具3、常用扫描工具4、SATAN的分级5、SATAN的特点6、SNMP7、Nessus8、X-scan9、常用扫描工具比较10、其它扫描工具 二、扫描…

【azure】office 365邮箱auth2认证之spa的刷新令牌过期后如何处理

参考&#xff1a;https://learn.microsoft.com/zh-cn/azure/active-directory/develop/refresh-tokens 官方对令牌和刷新令牌生命周期的描述 已失效的刷新令牌如何获取新的令牌和刷新令牌 /*** office 365使用失效的刷新令牌和应用程序的相关信息来获取新的访问令牌和刷新令牌…

PyTorch安装配置(windows)

一、Anaconda安装与配置 Anaconda提供了conda机制用于管理Python数据分析时常用的工具库/包 官网下载最新的&#xff08;翻墙&#xff09;&#xff1a;https://repo.anaconda.com/archive/ 清华大学Anaconda镜像站&#xff1a;https://mirrors4.tuna.tsinghua.edu.cn/help/an…

从研发赋能型PMO到产研管理型PMO的组织变革思考︱广联达产研管理部副总经理丰之恺

广联达科技股份有限公司产研管理部副总经理丰之恺先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;从研发赋能型PMO到产研管理型PMO的组织变革思考。大会将于8月12-13日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#x…

4G无线通信技术的单片机远程升级研究(学习)

介绍了一种基于4G无线通信技术的单片机远程在线升级系统及方法&#xff0c;由上位机、4G无线模块、嵌入式设备终端3部分组成。 结合EC20 R2.1 4G模块&#xff0c;介绍了4G无线网络的组建方法&#xff0c;借助4G网络实现远程无线升级。 通过验证测试&#xff0c;系统能够实现嵌入…

css内阴影

CSS内阴影及特定方向内阴影 基本参数&#xff1a; /* x 偏移量 | y 偏移量 | 阴影颜色 */ box-shadow: 60px -16px teal;/* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影颜色 */ box-shadow: 10px 5px 5px black;/* x 偏移量 | y 偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影…

Python GUI编程利器:初始Tkinker(1)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 神兽归笼 最近天气炎热起来了&#xff0c;大家一定要注意防暑降温啊&#xff01; 马上要放暑假了&#xff0c;你有什么计划没…

AI届老牌顶流!AI孙燕姿?AI配音?带你玩转语音合成!

热度与争议并存&#xff01;AI孙燕姿成新晋顶流&#xff1f;随着AI孙燕姿的爆火&#xff0c;AI老牌顶流「语音合成」再度被炒热飞桨AI Studio也汇聚着众多“语音合成”深度玩家本期就来带大家快速上手 AI克隆歌手 该应用项目使用AI孙燕姿同源模型So-VITS-SVC 4.0&#xff0c;其…

Pyside6-QtCharts+psutil实战-绘制一个CPU监测工具

今天是实战篇章&#xff0c;我们结合可以快速提升我们开发效率的工具一起开实战一波实时读取系统CPU使用情况的折线图。 使用的开发工具Qt Designer来开发UI界面。 十分便捷。使用起来也算比较的简单了&#xff0c;虽然也存在不少的BUG。 ❝ 对所需要的控件进行拖拽式&#xff…

如何看待低级爬虫与高级爬虫?

爬虫之所以分为高级和低级&#xff0c;主要是基于其功能、复杂性和灵活性的差异。根据我总结大概有下面几点原因&#xff1a; 功能和复杂性&#xff1a;高级爬虫通常提供更多功能和扩展性&#xff0c;包括处理复杂页面结构、模拟用户操作、解析和清洗数据等。它们解决了开发者…

死神来了 | 印度火车,能靠点谱吗?

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 阿福 运营 / SandLiu 卷圈 监制 / 姝琦 封面 / 姝琦Midjourney 产品统筹 / bobo 场地支持 / 声湃轩天津录音间 6月初&#xff0c;印度三列火车先后相撞&#xff0c;造成288人死亡、1175人受伤&#xff0c;被称为印度本世…

基于Echarts2.X的地图数据可视化指南

目录 前言 一、关于Echarts版本 1、为什么用Echarts2.2.7 2、文件目录说明 二、地图数据可视化 1、新建map.html 2、Echarts图表初始化 3、参数设置 三、源码展示分析 1、初始化阶段 2、timelineOption.js模拟数据 总结 前言 在前面的博文&#xff08;数据会说话-从我国…

ebpf执行报错no BTF found for kernel

一、现象描述 采用cilium epbf框架开发的ebpf程序无法在系统上正常运行。 curtiscurtis-desktop:~$ cd work/ curtiscurtis-desktop:~/work$ ls kmodule vfs_write_moitor curtiscurtis-desktop:~/work$ curtiscurtis-desktop:~/work$ sudo ./vfs_write_moitor -filename/mn…

第九十天学习记录:C++核心:函数提高

函数默认参数 在C中&#xff0c;函数的形参列表中的形参是可以有默认值的。 语法&#xff1a;返回值类型 函数名 &#xff08;参数默认值&#xff09;&#xff5b;&#xff5d; 问&#xff1a;C语言可以在函数的形参赋默认值吗&#xff1f; 答&#xff1a; 在C语言中&#xf…