【Linux】文件描述符 (上篇)

news2024/11/18 2:33:17

文章目录

  • 📖 前言
  • 1. 文件的预备知识
  • 2. 复习C语言的文件操作
  • 3. Linux系统级文件接口
    • 3.1 open、 close、 read、 write 接口:
    • 3.2 内核当中实现的映射关系:
    • 3.3 如何理解Linux下一切皆文件:

📖 前言

本章开始,我们将进入Linux文件相关的学习与操作,从复习回顾C语言的文件操作接口,再从操作系统角度出发,学习系统调用接口。再了解虚拟文件系统,内核管理文件的数据结构。最后通过学习的操作文件的系统接口来模拟实现C语言的文件操作接口,最后对之前实现的shell进程改进。目标已经确定,接下来就要搬好小板凳,准备开讲了…🙆🙆🙆🙆


1. 文件的预备知识

  • 文件 = 文件内容 + 文件属性
  • 文件属性也是数据,即便你创建一个空文件,也要占据磁盘空间。
  • 文件操作 = 文件内容的操作 + 文件属性的操作
  • 有可能,在操作文件的过程中,既改变内容,又改变属性。
  • 属性可能随着内容的变化可能在变化。
  • 所谓的 “打开” 文件,究竟在干什么?
  • 将文件的属性或内容加载到内存中!
  • —— 这是由冯·诺依曼体系决定的!CPU只能在内存中对文件进行读写操作。
  • 打开文件不是目的,访问文件才是目的。
    • 例如:将文件内容中小写字母改成大写字母,是先将文件内容读到内存里,再把buff里面所有的内容改成大写,再写回到文件中。
  • 程序被加载到内存中后磁盘中还有吗?
  • 是的程序被加载到内存中后,磁盘中仍然存在程序文件。
  • 程序文件是存储在磁盘上的二进制文件,它包含了程序的代码、数据和资源等信息。
  • 当程序被加载到内存中时,操作系统会将程序文件中的代码和数据复制到内存中,程序在内存中执行。
  • 但是,如果需要重新启动程序或者重新加载程序,操作系统仍然需要从磁盘中读取程序文件。
  • 因此,程序文件仍然存在于磁盘中,直到被删除或者替换为止。
  • 如果程序压根没运行,这个程序就在磁盛上单独的一份。
  • 进程对应着磁盘上的一个程序,程序被加载到内存里的时候,在内存里有一份,在磁盘里也有一份。
  • 是不是所有的文件,都会处于被打开的状态?
  • 绝对不是!没有被打开的文件,在哪里?
    • 只在磁盘上静静的存储着!
  • 打开的文件(内存文件)和磁盘文件
  • 下面讲的所有内容都是打开文件。
  • 软硬链接,inode的时候再讲磁盘文件。
  • 通常我们打开文件,访问文件,关闭文件,是谁在进行相关操作?
  • fopen,fclose, fread, fwrite …
  • 当我们的文件程序运行起来的时候,才会执行对应的代码。
  • 然后才是真正的对文件进行相关的操作。
  • 真正的是进程对文件进行操作!
  • 目前学习文件就变成了:进程和打并文件的关系
  • 进程在内存,打开文件也在内存,所以是内存级的关系。
  • 文件的本质是进程和打开文件之间的关系。
  • 小结:
  • 对文件的操作:
    • 只有将程序编成可执行程序之后,加载到内存里的时候。
    • 变成了一个进程并且被CPU调度,开始执行自己编写的代码,这个时候才开始进行文件操作。
    • 所以当文件程序运行起来的时候,才会执行对应的代码,然后才是对文件的操作。
    • 所以通常说对文件的操作这句话,应该准确的说是:程序对应的进程对文件的操作。
  • 把文件打开在做什么:
    • 打开一个文件最终的目标是通过CPU执行用户代码,来完成对应文件操作。
    • 所以如果要是对数据进行操作,尤其是通过CPU来对数据进行操作(通过代码的方式)的话,就必须要求数据也要在内存当中。
    • 这个数据指的是文件的属性或者内容,一定要加载到内存里,这是由体系结构决定的(冯.诺依曼)。
  • 访问一个文件就得先打开,打开就得在内存里。
  • 程序要打开文件,必须先把程序变成进程。
  • 所有文件操作的本质都是在研究进程和打开文件的关系。

2. 复习C语言的文件操作

  • 什么是当前路径
  • 在之前我们讲进程概念的时候我们讲过,【对当前路径的理解复习-传送门】。
  • 每个进程都有个工作路径,调用chdir可以更改工作路径。
  • 更改当前路径用chdir就可以更改,哪个进程调用这个函数就更改哪个进程的当前路径。
    • 一个进程在运行之前是会把自己所在的路径保存在自己的PCB当中。
    • 所以该进程当前在哪个路径,它自己是知道的。
    • 所以当前路径最准确的说法是 进程的当前所处的工作路径。

在源代码路径下是不对的,更准确的说法是在当前进程所对应的路径下。只不过默认的一个进程的工作路径是在,当前自己所处的路径,不过路径是可以改的。所以cd、pwd查看的时候,这个进程路径变化或者不变,,说白了就是在更改自己进程的当前路径。

在这里插入图片描述

在C语言中,fopen 函数用于打开文件,并返回一个指向文件的指针。下面是常见的几个选项:

1. "r":以只读方式打开文件。文件必须已经存在才能成功打开。
2. "w":以写入方式打开文件。如果文件不存在,则创建新文件;如果文件已存在,则清空文件内容。
3. "a":以追加方式打开文件。如果文件不存在,则创建新文件;如果文件已存在,则在文件末尾追加内容。
4. "rb":以二进制只读方式打开文件。类似于 "r",但以二进制模式读取文件。
5. "wb":以二进制写入方式打开文件。类似于 "w",但以二进制模式写入文件。
6. "ab":以二进制追加方式打开文件。类似于 "a",但以二进制模式追加内容。

这些选项可以根据需要选择,用于读取、写入或追加文件的内容。此外,还可以使用其他选项和模式来进行更高级的文件操作,例如对文件进行读写结合(“r+”、“w+”、“a+”)或者以二进制方式进行读写操作(“rb+”、“wb+”、“ab+”)。请注意,打开文件后应该使用 fclose 函数关闭文件指针,以释放相关资源。

通过fopen打开文件,r选项,再通过fgets按行读取文件:

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

int main()
{
    //1. 默认这个文件会在哪里形成呢?
    //2. r, w, r+, w+, a, a+
    //(r+ 和 w+ 都叫做既读又写,只不过w+多了一个功能,就是文件不存在会自动创建)
    //3. 关注一下文件清空的问题
    
    FILE* fp = fopen("log.txt", "r"); 
    if(fp == NULL)
    {
        perror("fopen");
        return 1;
    }

    char buffer[64] = { 0 };
    while(fgets(buffer, sizeof(buffer), fp) != NULL)
    {
        printf("echo : %s\n", buffer);
    }

    fclose(fp);

    return 0;
}
  • a:追加写入,不断的往文件中新增内容 -> 追加重定向

在这里插入图片描述
代码演示:

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

int main()
{    
    FILE* fp = fopen("log.txt", "a"); //写入
    if(fp == NULL)
    {
        perror("fopen");
        return 1;
    }

    const char* msg = "Hello World";
    int cnt = 1;
    while(cnt <= 5)
    {
        fprintf(fp, "%s: %d\n", msg, cnt++);
    }
    fclose(fp);

    return 0;
}

在这里插入图片描述

  • 当我们以w方式打开文件,准备写入的时候,其实文件已经先被清空了
    在这里插入图片描述

以w打开的时候文件就被清空了,如果不存在就创建。

  • 回归理论:
  • 当我们向文件写入的时候,最终是不是向磁盘写入?是的!
  • 磁盘是硬件吗?就是硬件!
  • 只有谁有资格向硬件写入呢?操作系统!
  • 能绕开操作系统吗?不能!
    • 因为操作系统是软硬件资源的管理者。
    • 所有的上层访问文件的操作,都必须贯穿操作系统。
    • 只有操作系统可以间接的向硬件当中写入,必须得经过操作系统,并且不能绕过操作系统。
    • 因为操作系统本身就是硬件的管理者。
  • 操作系统是如何被上层使用的?
    • 必须使用操作系统提供的相关系统调用!

所有的语言都对系统接口做了封装,封装了系统接口。

  • 为什么要封装?
  1. 原生系统接口,使用成本比较高!
  2. 语言不具备跨平台性!
  • 封装是如何解决跨平台问题的呢?
  • C语言的解决办法:穷举所有的底层接口 + 条件编译!
  • 其他语言用的可能就是多态解决。
  • 不同的语言用不同的方式对系统调用进行封装。
  • 所以就导致了不同语言对文件操作的接口都不同。

所有的跨平台的语言,必须通过自己的方案,对所有的系统接口做相关封装,设计好自己对应语言当中的IO接口。

如果直接使用OS接口:
在这里插入图片描述
具有上下级的关系:

任何一个语言,只要在同一个平台下跑,底层接口是不变的(Linux, Window…)。

我们为什么要学习系统级接口的原因:

  • 文件接口更接近于操作系统,这样理解语言层面的接口会很简单。
  • 在一个平台当中,这些接口是不变的。
  • 只要将不变的接口学了, 在学习其他语言的时候会更容易理解。

3. Linux系统级文件接口

3.1 open、 close、 read、 write 接口:

open、 close、 read、 write四个系统调用接口。

open函数的介绍:

在这里插入图片描述
两个同名函数,这是同名函数,难道是函数重载吗?我们来看看GPT的回答:

在这里插入图片描述
第二个参数标记位,通过宏来实现的:

  • O_RONLY,O_WRONLY,O_RDWR,O_APPEND,O_CREAT…
  • 系统传递标记位,是用位图结构来进行传递的!【位图复习-传送门】
  • 每一个宏标记,一般只需要有一个比特位是1,并且和其他宏对应的值,不能重叠。

演示一下:

#include <stdio.h>

#define PRINT_A 0x1 //0000 0001
#define PRINT_B 0x2 //0000 0010
#define PRINT_C 0x4 //0000 0100
#define PRINT_D 0x8 //0000 1000
#define PRINT_DFL 0x0

//等同于系统级open
void Show(int flags)
{
    if(flags & PRINT_A) printf("hello A\n");
    if(flags & PRINT_B) printf("hello B\n");
    if(flags & PRINT_C) printf("hello C\n");
    if(flags & PRINT_D) printf("hello D\n");

    if(flags == PRINT_DFL) printf("hello Default\n");
}

int main()
{
    printf("PRINT_DFL:\n");
    Show(PRINT_DFL);

    printf("PRINT_A\n");
    Show(PRINT_A);

    printf("PRINT_B\n");
    Show(PRINT_B);

    printf("PRINT_A 和 PRINT_B\n");
    Show(PRINT_A | PRINT_B);

    printf("PRINT_C 和 PRINT_D\n");
    Show(PRINT_C | PRINT_D);

    printf("PRINT all:\n");
    Show(PRINT_A | PRINT_B | PRINT_C | PRINT_D);

    return 0;
}

上述代码,模拟了用宏做标记为的实现。

返回值:

在这里插入图片描述

  • 返回的是个整数,文件描述符
  • -1是发生错误,出错之后error会设置

在这里插入图片描述

  • O_TRUNCopen函数中的一个标志位,表示截断(truncate)文件。
  • C语言在w方式打开文件的时候,会清空的!
  • 同样的道理, O_APPEND是C语言中a方式打开文件,追加!

在这里插入图片描述

O_TRUNC标志的含义是,如果指定的文件已经存在,那么在打开该文件的同时会将其内容清空(即截断文件)。如果指定的文件不存在,则会创建一个新的空文件。

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

int main()
{
    //有点像就近原则
    umask(0);

    //fopen("log.txt", "w"); //底层的调用的是open, O_WRONLY | O_CREAT | O_TRUN和这些选项,还要设置属性
    int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    if(fd < 0)
    {
        perror("open");

        return 1;
    }

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

    int cnt = 0;
    //const char* str = "Hello World\n";
    const char* str = "aaa";
    while(cnt < 2)
    {
        //不能带\0,这是C语言的用法, 文件不认识\0
        write(fd, str, strlen(str));
        cnt++;
    }

    return 0;
}

创建一个文件的话,这个文件要受到Linux权限的约束的。

  • 所以要打开一个之前并不存在的文件的话,不能用两个参数的open,我们要用三个参数的open。
  • 最后的mode代表所创建文件的权限。

不然权限是乱的,如图所示:

在这里插入图片描述
加了权限参数之后,发现是664,为什么不直接是0666呢?

在这里插入图片描述
这个和umask有关,我们要在一开始将umask设置成0。

在这里插入图片描述

不然不同的地方使用这段代码,umask可能都不同,需要我们认为控制,若不这样,很可能造成不同地方跑同样的代码,创造出来的文件权限不同。

为什么我们write往文件里写的时候,写的长度为什么不带上最后的‘\0’呢?

  • 我们先来看一下write接口:

在这里插入图片描述因为这是刻意为之,因为文件是不认是C语言的‘\0’。

在Linux中,有几个默认打开的文件是常见的:

  • 标准输入(stdin):文件描述符为0,通常与用户交互,通过键盘输入数据。
  • 标准输出(stdout):文件描述符为1,通常将程序输出的内容显示在终端上。
  • 标准错误(stderr):文件描述符为2,用于输出程序的错误消息或诊断信息。

在这里插入图片描述

我们可以通过read接口,读取键盘输入的内容:

int main()
{
    char buffer[1024];
    ssize_t s = read(0, buffer, sizeof(buffer) - 1);
    if(s > 0)
    {
        buffer[s] = '\0';
        printf("echo: %s", buffer);

    }
    return 0;
}

在这里插入图片描述
验证0,1,2就是标准IO:

//验证0,1,2就是标准IO
int main()
{
    const char* str = "Hello World!\n";

    write(1, str, strlen(str));
    write(2, str, strlen(str));
    return 0;
}

在这里插入图片描述
验证0, 1, 2 和stdin, stdout, stderr的对应关系:

//0,1,2和stdin, stdout, stderr的对应关系
int main()
{
    printf("stdin: %d\n",stdin->_fileno);
    printf("stdout: %d\n",stdout->_fileno);
    printf("stderr: %d\n",stderr->_fileno);

    return 0;
}

在这里插入图片描述
close接口,关闭文件:

在这里插入图片描述
close是真的将文件销毁了吗?

  • 调用 close 函数后,文件仍然存在,并且可以通过重新打开或使用其他文件操作函数来再次访问。
  • close 操作只是将文件与当前程序的连接断开,而不是销毁文件本身。
  • 类似于智能指针中的做法。

3.2 内核当中实现的映射关系:

为什么fd是从3开始的?

  • 因为0,1,2 已经被默认打开了。

在这里插入图片描述
我们看到stdin,stdout,stderr三个都是FILE的指针,在我们之前学习C语言知道,FILE是个结构体,是描述文件的一个结构体。

  • FILE* 是文件指针,里面封装了多个成员。
  • 通过上面演示的现象说明,FILE结构体内必定封装了fd

0,1, 2, 3, 4, 5…其实是数组下标!凡是用fd返回的,用的都是系统接口,操作系统提供的返回值!
open/ read/write/close - 要么是得到fd要么用到fd。

  • 内核数据结构详解~
  • 一个进程可不可以打开多个文件?当然可以!
  • 所以在内核中,进程:打开的文件 = 1 : n
    • 所以系统在运行中,有可能会存在大量的被打开的文件!
  • OS要不要对这些被打开的文件进行管理呢?
    • 操作系统如何管理这些被打开的文件呢?
    • 一定是先描述,再组织!!

一个文件被打开,在内核中,要创建该被打开的文件的内核数据结构 — 先描述!

  • 进程如何和打开文件建立映射关系呢?

在这里插入图片描述

  • 内核当中实现的映射关系:

在这里插入图片描述
由图小结:

  • 其一:
    • 所以打开文件时是先创建一个struct file
    • 并且在当前文件描述符表里面分配一个没有被使用的下标,。
    • 将地址填入表中,并将数组对应的下标返回给用户。
  • 其二:
    • 当用户再次调用read, write等,一定传入了fd。
    • 只需要找到特定进程,找到fd,根据特定的文件描述符再索引到数组。
    • 最后找到文件对象,就可以对它进行相关操作了。
  • 内核当中:对被打开的文件的管理,转化成为了对链表的增删改查!
  • 所以一个进程将来想访问某一个文件,只需要知道该文件在这个映射表当中的数组下标。
  • 进程和文件之间的关系和语言没有关系!!

0,1, 2 -> stdin, stdout, stderr -> 键盘,显示器,显示器(这些都是硬件!)也用上面将的struct file来标识对应的文件吗??是的!!

3.3 如何理解Linux下一切皆文件:

如何知道这些struct file对应的操作方法是不一样的?

  • Linux是C语言写的,虽然不支持结构体中封装函数,但是可以用函数指针。
  • 通过函数指针的方式,让函数指针指向特定的方法。
  • 打开struct file的时候识别底层文件的类型拿到底层文件的读写方法,用自己的函数指针指向就可以了。
  • 上层来使用看的时候就认为是一切皆文件。
  • virtual file system 虚拟文件系统:

在这里插入图片描述
OS内的内存文件系统以统一的视角看待所有的设备!!

  • 如果要打开文件,就在内核给硬件创建struct file
  • 然后初始化的时候,将函数指针指向具体的设备。
  • 但是在内核中存在的永远都是struct file,然后将struct file关联起来。
  • 所以一个进程看所有的文件都以统一的方式来看待。
  • 当我们访问一个file的时候,具体指向底层哪个对应的设备完全取决于对应的读写方法指向的哪个方法。
  • 对应的设备,对应的读写方法一定是不一样的!

上层使用同一个对象,指针指向不同的对象,最终就能调用不同的方法,可以理解为多态的前身。

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

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

相关文章

python绘制带有误差棒的条形图

文章目录 bar和barh加入误差棒定制误差棒颜色 bar和barh 在matplotlib中&#xff0c;通过bar和barh来绘制条形图&#xff0c;分别表示纵向和横向的条形图。二者的输入数据均主要为高度x和标签height&#xff0c;示例如下 import matplotlib.pyplot as plt import numpy as np…

MySQL CDC技术方案梳理

本篇主要探讨MySQL数据同步的各类常见技术方案及优劣势对比分析&#xff0c;从而更加深层次的理解方案&#xff0c;进而在后续的实际业务中&#xff0c;更好的选择方案。 1 CDC概念 CDC即Change Data Capture&#xff0c;变更数据捕获&#xff0c;即当数据发生变更时&#xff…

Ubuntu: scp命令使用及Permission denied错误解决方案

scp命令介绍 scp 命令用于 Linux 之间复制文件和目录。scp 是 secure copy 的缩写, scp 是 Ubuntu 系统下基于 ssh 登陆进行安全的远程文件拷贝命令。 scp local_file remote_usernameremote_ip:remote_folder scp /Users/X.pem root192.168.1.247:/usr/local/ssl Permission…

java项目之高校校园点餐系统(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的闲一品交易平台。技术交流和部署相关看文末&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框架&#…

傻瓜式一键生成主子表

文章目录 傻瓜式一键生成主子表 简介创建主子表示例 根据已有主表创建子表示例 创建空属性主子表示例 总结 傻瓜式一键生成主子表 直接将xml导入到Studio里即可。下载文件连接&#xff1a; CSDN链接阿里云盘 简介 很多同学在创建主子表时&#xff0c;都会可能遇到如下一些问…

日本留学托福要求多少分才及格呢?

日本有悠久的历史和文化&#xff0c;吸引了越来越多的留学生前往探索和学习。那么&#xff0c;日本留学托福要求多少分才及格呢&#xff1f; 日本留学托福成绩要求 综合类&#xff1a;通常要求申请者取得托福总分在80以上&#xff0c;各项分数要求分别为口语20以上&#xff0c…

LinuxI2C应用编程——I2C-Tools的使用

文章目录 I2C 硬件框架I2C 软件框架I2C协议&#xff08;传输数据的格式&#xff09;写操作读操作I2C 信号 SMBus 协议概述硬件和软件上的区别SMBus 协议分析符号的含义SMBus Quick CommandSMBus Receive ByteSMBus Send ByteSMBus Read ByteSMBus Read WordSMBus Write ByteSMB…

11_Linux阻塞与非阻塞

目录 阻塞和非阻塞IO简介 等待队列 等待队列头 等待队列项 轮询 Linux驱动下的poll操作函数 阻塞式访问IO实验 阻塞式访问IO驱动程序编写 运行测试 非阻塞式IO实验 运行测试 阻塞和非阻塞IO简介 阻塞和非阻塞IO是Linux驱动开发里面很常见的两种设备访问模式,在编写…

充分利用测试自动化的 10 个最佳实践

目录 前言&#xff1a; 实践1&#xff1a;手动和自动测试结合 实践2&#xff1a;特别注意回归测试 实践3&#xff1a;包括端到端测试 实践4&#xff1a;为自动化测试提供集体所有权 实践5&#xff1a;详细计划与测试相关的所有流程 实践6&#xff1a;选择适合您需求的自…

Python随机生成2堆三维点云点,有固定的重复率并可视化

Python随机生成2堆三维点云点&#xff0c;有固定的重复率并可视化 1. 效果图2. 源码 这篇博客源于博友的提问&#xff0c;刚好电脑在旁边没啥事&#xff0c;那就开整吧。 np.random 生成随机点&#xff08;提供了俩种方法&#xff0c;1. xyz限制都是0~MAX值&#xff0c;2. xyz分…

IDEA中使用.env文件配置信息

一、说明 我们以配置阿里云的 Access Key 的信息为例&#xff08;配置别的信息当然也可以&#xff0c;我只是举个例子&#xff01;&#xff01;&#xff01;&#xff09;&#xff0c;假设我们的代码中需要用到它。Access Key有两个属性&#xff0c;分别为【ALIBABA_CLOUD_ACCE…

【剧前爆米花--前端三剑客】html的一些常用标签及其实例

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaEE初阶》 文章分布&#xff1a;这是一篇关于html前端的文章&#xff0c;在这篇文章中我会简单介绍一些常用的html标签&#xff0c;并给出他们的应用实例&#xff0c;希望对你有所帮助&#xff01; 目录 html常见标签 标题标…

python_day3_tuple

元组tuple &#xff1a;无法修改&#xff08;只读的列表&#xff09; t1 () t2 tuple() t3 (1, java, True, ()) print(f"t1的数据类型是&#xff1a;{type(t1)}") print(f"t2的数据类型是&#xff1a;{type(t2)}") print(f"t3的数据类型是&#…

ChatLaw:北大团队智能法律助手,国产大模型成功应用普惠法律服务

“ 技术发展的本质是普惠&#xff0c;用技术降低普通人获取法律知识的成本&#xff0c;向社会输出普惠的公平正义。—— 北京大学 ChatLaw 项目组” 刚刚清华团队升级了国产大模型&#xff1a;ChatGLM2-6B&#xff0c;ChatGLM2-6B 初体验。 转眼这两天北大团队推出的智能法律助…

DAY36:贪心算法(三)最大子数组和+买卖股票最佳时机

文章目录 53.最大子数组和枚举思路暴力解法贪心思路完整版时间复杂度 122.买卖股票的最佳时机Ⅱ&#xff08;解法比较巧妙&#xff09;思路完整版总结 53.最大子数组和 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元…

Java开发基础系列(一):Java设计概述

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; Java开发基础系列(一):Java设计概述 ⏱️ 创作时间&#xff1a; 2023年…

【漏洞复现】nginxWebUI 存在前台远程命令执行漏洞

文章目录 前言声明一、nginxWebUI 简介二、漏洞描述三、影响版本四、漏洞复现五、修复建议 前言 nginxWebUI 存在前台远程命令执行漏洞&#xff0c;攻击者通过该漏洞获取服务器控制权限进而进一步获取敏感数据信息。 声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由…

# 文盘Rust -- FFI 浅尝

作者&#xff1a; jiashiwen 原文来源&#xff1a; https://tidb.net/blog/cfa03c39 notice"Rust is a trademark of the Mozilla Foundation in the US and other countries." rust FFI 是rust与其他语言互调的桥梁&#xff0c;通过FFI rust 可以有效继承 C 语言…

道德与社会问题简报 #4: 文生图模型中的偏见

简而言之: 我们需要更好的方法来评估文生图模型中的偏见 介绍 文本到图像 (TTI) 生成 现在非常流行&#xff0c;成千上万的 TTI 模型被上传到 Hugging Face Hub。每种模态都可能受到不同来源的偏见影响&#xff0c;这就引出了一个问题: 我们如何发现这些模型中的偏见&#xff1…

Android启动流程优化 上篇

Android启动流程优化 上篇 本文链接&#xff1a;Android启动流程优化 上篇_猎羽的博客-CSDN博客 启动流程 各个阶段图 1、各个阶段的概括总结 分为5个大阶段或者10个小阶段 【字节跳动团队】内部论坛分享也是这么处理的 补充一些只是细节点: application#onCreate()运行…