【看表情包学Linux】初识文件描述符 | 虚拟文件系统 (VFS) 初探 | 系统传递标记位 | O_TRUNC | O_APPEND

这篇具有很好参考价值的文章主要介绍了【看表情包学Linux】初识文件描述符 | 虚拟文件系统 (VFS) 初探 | 系统传递标记位 | O_TRUNC | O_APPEND。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符爆笑教程《看表情包学Linux》👈 猛戳订阅!​​​​​o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

💭 写在前面:通过上一章节的讲解,想必大家已对文件系统基本的接口有一个简单的了解,本章我们将继续深入讲解,继续学习系统传递标志位,介绍 O_WRONLY, O_TRUNC, O_APPEND 和 O_RDONLY。之后我们就正是打开文件描述符 fd 的大门了,之前我们所探讨讲解的系统文件操作,都是为了给文件描述符做铺垫的,可见这这一块知识点是相当的重要。话不多说,让我们正式开始本章的学习!

📜 本章目录:

Ⅰ. 系统传递标记位

0x00 引入:O_WRONLY 没有像 w 那样完全覆盖?

0x01 O_TRUNC 截断清空(对标 w)

0x02  O_APPEND 追加(对标 a)

0x03 O_REONLY 读取

Ⅱ. 文件描述符(fd)

0x00 引入:open 参数的返回值

0x01 文件描述符的底层理解

0x02 理解:Linux 下一切皆文件

0x03 初识 VFS(虚拟文件系统)

0x04 回头看问题:fd 的 0,1,2,3... 

 o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符  本篇博客全站热榜排名:未上榜


Ⅰ. 系统传递标记位

0x00 引入:O_WRONLY 没有像 w 那样完全覆盖?

 语言在  模式打开文件时,文件内容是会被清空的,但是 O_WRONLY 好像并非如此?

💬 代码演示:当前我们的 log.txt 内有 5 行数据,现在我们执行下面的代码:

int main(void)
{
    umask(0);
    // 当我们只有 O_WRONLY 和 O_CREAT 时
    int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);
    if (fd < 0) {
        perror("open"); 
        return 1;
    }
    printf("fd: %d\n", fd); 
    
    // 修改:向文件写入 2 行信息
    int cnt = 0;
    const char* str = "666\n";  // 修改:内容改成666(方便辨识)
    while (cnt < 2) {
       write(fd, str, strlen(str));
       cnt++;
    }

    close(fd);

    return 0;
}

🚩 运行结果如下:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

❓ 疑点:O_WRONLY 怎么没有像 w 那样完全覆盖???

我们以前在  语言中,w 会覆盖把全部数据覆盖,每次执行代码可都是会清空文件内容的。 

而我们的 O_WRONLY 似乎没有全部覆盖,曾经的数据被保留了下来,并没有清空!

其实,没有清空根本就不是读写的问题,而是取决于有没有加 O_TRUNC 选项!

因此,只有 O_WRONLY 和 O_CREAT 选项是不够的:

  • 如果想要达到 w 的效果还需要增添 O_TRUNC
  • 如果想到达到 a 的效果还需要 O_APPEND

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 下面我们就来介绍一下这两个选项!

0x01 O_TRUNC 截断清空(对标 w)

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 在我们打开文件时,如果带上 O_TRUNC 选项,那么它将会清空原始文件。

如果文件存在,并且打开是为了写入,O_TRUNC 会将该文件长度缩短 (truncated) 为 0。

也就是所谓的 截断清空 (Truncate Empty) ,我们默认情况下文件系统调用接口不会清空文件的,

但如果你想清空,就需要给 open() 接口 带上 O_TRUNC 选项:

💬 代码演示:open() 达到 fopen"w" 模式的效果

int main(void)
{
    umask(0);
    int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    if (fd < 0) {
        perror("open"); 
        return 1;
    }
    printf("fd: %d\n", fd); 
    
    // 向文件写入 2 行信息
    int cnt = 0;
    const char* str = "666\n";
    while (cnt < 2) {
       write(fd, str, strlen(str));
       cnt++;
    }

    close(fd);

    return 0;
}

🚩 运行结果如下:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

然而  语言的 fopen 函数,只需要浅浅地标上一个 "w" 就能搞定了:

fopen("log.txt", "w");

调一个 w 就以写的方式打开了,不存在会自动创建,并且会完全覆盖原始内容,是如此的简单!

它对应的底层 open 调用,调用接口所传入的选项就是 O_WRONLY, O_CREAT, O_TRUNC

由此可见, 的 fopen 是多么的好用!open 不仅要传这么多选项,而且属性也要设置:

open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
fopen("log.txt", "w");

0x02  O_APPEND 追加(对标 a)

上一章我们复习了 a 模式, 语言中我们以 a 模式打开文件做到追加的效果。

现在我们用 open,追加是不清空原始内容的,所以我们不能加 O_TRUNC,得加 O_APPEND

int fd = open("log.txt", O_WRONLY | O_CREATE | O_APPEND, 0666);

💬 代码演示:open() 达到 fopen"a" 模式的效果

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

int main(void)
{
    umask(0);
    int fd = open("log.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
    if (fd < 0) {
        perror("open"); 
        return 1;
    }
    printf("fd: %d\n", fd); 
    
    // 向文件写入 2 行信息
    int cnt = 0;
    const char* str = "666\n";
    while (cnt < 2) {
       write(fd, str, strlen(str));
       cnt++;
    }

    close(fd);

    return 0;
}

🚩 运行结果如下:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 我们再来对照  语言的 fopen,想做到这样的效果只需要一个 "a"

open("log.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
fopen("log.txt", "a");

实际上,系统级别的接口本来就是被文件接口封装的,fopen 是系统级文件接口的底层实现。

我们的 a, w, r... 在底层上实际上就是这些 "O_" 组合而成的,使用系统接口麻烦吗?

当然麻烦!要记这么多东西,当然还是 C 语言用的更爽了,一个字母标明文件模式就行了。

0x03 O_REONLY 读取

如果我们想读取一个文件,那么这个文件肯定是存在的,我们传 O_RDONLY 选项:

int main()
{
    umask(0);

    int fd = open("log.txt", O_RDONLY);
    if (fd < 0) {
        perror("open");
        return 1;
    }

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

    char buffer[128];
    ssize_t s = read(fd, buffer, sizeof(buffer) - 1);
    if (s > 0) {
        buffer[s] = '\0';  // 最后字符串序列设置为 '\0' 
        printf("%s", buffer);
    }


    close(fd);   
    
    return 0;
}

🚩 运行结果如下:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

Ⅱ. 文件描述符(fd)

0x00 引入:open 参数的返回值

int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);

我们使用 open 函数举的例子中,一直是用一个叫做 fd 的变量去接收的。

fopen 中我们习惯使用 fp pf 接收返回值,那是因为是 fopen 的返回值  FILE* 是文件指针,

file pointer 的缩写即是 fp,所以我们就习惯将这个接收 fopen 返回值的变量取名为 fp pf

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符那为什么接收 open 的返回值的变量要叫 fd 呢?

这个 fd 究竟是何方神圣?我们现在就揭开其神秘面纱,一睹芳容!它就是……

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

open 如果调用成功会返回一个新的 文件描述符 (file descriptor) ,如果失败会返回 -1 

  •  :失败 (success)
  •  :成功 (failed)

💬 代码演示:我们现在多打开几个文件,观察 fd 的返回值

int main(void)
{
    int fd_1 = open("log1.txt", O_WRONLY | O_CREAT, 0666);
    int fd_2 = open("log2.txt", O_WRONLY | O_CREAT, 0666);
    int fd_3 = open("log3.txt", O_WRONLY | O_CREAT, 0666);
    int fd_4 = open("log4.txt", O_WRONLY | O_CREAT, 0666);
    int fd_5 = open("log5.txt", O_WRONLY | O_CREAT, 0666);

    printf("fd_1: %d\n", fd_1); 
    printf("fd_2: %d\n", fd_2); 
    printf("fd_3: %d\n", fd_3); 
    printf("fd_4: %d\n", fd_4); 
    printf("fd_5: %d\n", fd_5); 
    
    close(fd_1);
    close(fd_2);
    close(fd_3);
    close(fd_4);
    close(fd_5);

    return 0;
}

🚩 运行结果如下:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

我们发现这 open 的 5 个文件的  (返回值) 分别是  ,那么问题了来了:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符  为什么从 3 开始,而不是从 0 开始?0, 1, 2 去哪了?

  • 0标准输入(键盘,stdin)
  • 1标准输出(显示器,stdout)
  • 2标准错误(显示器,stderr)

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 系统接口认的是外设,而  标准库函数认的是:

#include <stdio.h>

extern FILE* stdin;
extern FILE* stdout;
extern FILE* stderr;

系统调用接口!那么 stdin, stdout, stderr 和上面的 0,1,2 又有什么关系呢?

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 想解决这个问题,我们得先说说 :

我们知道,FILE* 是文件指针,那么  是什么呢?它是  库提供的结构体。

只要是结构体,它内部一定封装了多个成员!

虽然  用的是 FILE*,但是系统的底层文件接口只认 ,也就是说:

 标准库调用的系统接口,对文件操作而言,系统接口只认文件描述符。

" 文件操作的系统接口属于是六亲不认,只认 fd "

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 因此, 内部必定封装了文件操作符  !

下面我们来验证一下,先验证 0,1,2 就是标准

💬 代码验证:0 是标准输入 (stdin)

int main(void)
{
    // 验证 0,1,2 就是标准 I/O
    char buffer[1024];
    ssize_t s = read(0, buffer, sizeof(buffer) - 1);

    if (s > 0) {
        buffer[s] = '\0';

        printf("echo: %s", buffer);
    }
}

🚩 运行结果如下:

 o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

💬 代码验证:stdout 标准写入(1) 和 stderr 错误写入(2) :

int main(void)
{
    const char* s = "Hello, write something\n";
    write(1, s, strlen(s));  // 1:向标准输入写入
    write(2, s, strlen(s));  // 2:向标准错误写入
}

🚩 运行结果如下:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

(1 和 2 的区别我们放到后面再讲)

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 至此,我们证明了 ——

每次我们打开文件虽然打开的是 3,但是可以像 3,4,5,6…… 去写,默认系统就会帮我们打开:

0 (标准输入, stdin) ,1 (标准输出, stdout),2 (错误输出, stderr) 

下面我们要做的是,验证一下 0,1,2 和 stdin, stdout 和 stderr 的对应关系。

根据我们目前的分析, 本来就是一个结构体, 因为系统只认 ,

所以  语言本身调用的一定是系统结构,这就直接决定了不管怎么封装,底层必须有 !

💬 代码验证:下面我们就来证明  的存在,证明 stdin, stdout 和 stderr 的对应关系

int main(void)
{
    printf("stdin: %d\n", stdin->_fileno);
    printf("stdout: %d\n", stdout->_fileno);
    printf("stderr: %d\n", stderr->_fileno);
}

🚩 运行结果如下:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

" 这……就是透过现象看本质!"

函数接口的对应:fopen / fclose / fread / fwrite    open / close / read / write

数据类型的对应:(FILE*FILE) → 

🔺 结论:我们用的  语言接口一定封装了系统调用接口!

  这个 0, 1, 2, 3, 4, 5……,是不是有点像数组下标?

" 咳咳……不是有点像,它就是数组下标!"

刚才返回  的,用的都是系统接口,是操作系统提供的返回值。

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 既然操作系统能给你,那说明操作系统内部是有的。

文件描述符的值为什么是 1,2,3,4,5... ?为了理解这个问题,我们需要做大量的铺垫!

0x01 文件描述符的底层理解

💭 逻辑推导:进程:内存文件的关系 → 内存 → 被打开的文件实在内存里面的

一个进程可以打开多个文件,所以在内核中,进程与打开的文件之比为:

所以系统在运行中,有可能会存在大量的被打开的文件 → OS 要对这些被打开的文件进行管理!

OS 如何管理这些被打开的文件呢?还是我们老生常谈的那句话:

先描述,再组织!

所以对我们来说,一个文件被打开不要片面的认为只是对文件内容动动手脚!

它还要 在内核中创建被打开文件的内核数据结构 —— 先描述

struct file {
    // 包含了你想看到的文件的所有大部分 内容 + 属性
    
    struct file* next;
    struct file* prev;
};

* 注:上面的代码是便于理解的,可不是内核真正的代码,真的可远比这复杂得多!

如果你在内核中打开了多个的文件,那么系统会在内核中为文件创建一个 struct file 结构。

可以通过 next prev 将其前后关联起来(内核的链表结构有它自己的设计,这里我们不关注)

既然你打开了一个文件,就会创建一个 struct file,那么你打开多个文件,

系统中必然会存在大量的 struct file,并且该结构我们用链表的形式链接起来:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 如此一来,对被打开的文件的管理,就转化成为了对链表的增删改查!

"这一幕怎么有些似曾相识?我们之前讲进程好像就是这么讲的!task_struct!"

进程与打开的文件之比为 ,进程能打开这么多文件,那么:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符进程如何和打开的文件建立映射关系?打开的文件哪一个属于我的进程呢?

在内核中,task_struct 在自己的数据结构中包含了一个 struct files_struct *files (结构体指针):

struct files_struct *files;

而我们刚才提到的 "数组" 就在这个 file_struct 里面,该数组是在该结构体内部的一个数组。

struct file* fd_array[];

该数组类型为 struct file* 是一个 指针数组,里面存放的都是指向 struct file 的指针!

" 指向 struct file 的指针!是不是恍然大悟?这不就是文件的 stuct file 结构么?没错!"

数组元素映射到各个被打开的文件,直接指向对应的文件结构,若没有指向就设为 NULL

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 此时,我们就建立起了 "进程" 和 "文件" 之间映射关系的桥梁。

🔍 看图理解:在内核中实现的映射关系

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

 如此一来,进程想访问某一个文件,只需要知道该文件在这张映射表中的数组下标。

上面这些就是在内核中去实现的映射关系了!这个下标 0,1,2,3,4 就是对应的文件描述符  !

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符我们调用的 open / read / write / close 接口都需要 :

" 可以理解为买彩票,由于关系复杂就不给大家讲故事了,自行理解"

 选号:当我们 open 打开一个新的文件时,先创建 struct file,然后在当前的文件描述表中分配一个没有被使用的下标,把 stuct file 结构体的地址填入 struct file* 中,然后通过 open 将对应的  返回给用户,比如 3,此时我们的  变量接收的 open 的返回值就是 3 了。

 兑奖:后续用户再调用 read, write 这样的接口一定传入了对应的 ,找到了特定进程的 files,在根据对应的  索引到指针数组,通过 sturct file* 中存储的 struct file 结构体地址,找到文件对象,之后就可以对相关的操作了。

🔺 总结:其本质是因为它是一个数组下标,系统中使用指针数组的方式,建立进程和文件之间的关系。将  返回给上层用户,上层用户就可以调用后续接口 (read, write...) 来索引对应的指针数组,找到对应文件,这就是  为什么是 0,1,2... 的原因了!

0x02 理解:Linux 下一切皆文件

我们上面说的 0,1,2 → stdin, stdout, stderr → 键盘, 显示器, 显示器,这些都是硬件啊?

也用你上面讲的 struct file 来标识对应的文件吗?在解答这个问题之前,我们需要讲清楚:

" Linux 下一切皆文件 "

一切皆文件这个话题在之前的章节我们已经提过了,但是当时由于知识点尚未展开,没法讲解。

现在我们到了去讲解这个概念的时侯了,希望大家可以尝试去理解 "Linux 下一切皆文件" 。

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 在这之前我们先说个题外话,其实  语言也是可以模拟面向对象的!

💬 代码演示:在  中用 struct 模拟面向对象

struct file {
    // 对象的是属性
    // 函数指针
    void *(readp)(struct file* filep, int fd ...);
    void *(writep)(struct file* filep, int fd...);
};

void read(struct file* filep, int fd...) {
    // 逻辑代码
}

void write(struct file* filep, int fd...) {
    // 代码
}

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符C++ 本身就是从 C 语言衍生出来的,并不是 "万丈高楼平地起" 的。

是大量工程实战后不断积累的产物,所以 C++ 的面向对象实际上在 C 中也能实现。

我们举个例子:我们在计算机中,有各种硬件:键盘、显示器、磁盘、网卡、其他硬件...

对我们现阶段而言,这些设备我们统一称之为 "外设",下面我们来看图。

🔍 看图理解:注意,下图的 "上层" 是刚才演示的 "映射关系图" 

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

深灰色层:对应的设备和对应的读写方法一定是不一样的。

黑色层:看见的都是 struct file 文件(包含文件属性, 文件方法),OS 内的内存文件系统。

红色箭头:再往上就是进程,如果想指向磁盘,通过  找到对应的 struct file,根据对应的 file 结构调用读写方法,就可以对磁盘进行操作了。如果想指向对应的显示器,通过 fd 找到 struct file……最后调用读写,就可以对显示器操作了…… 以此类推。

虽然指针指向的是差异化的代码,但是在 深灰色层,我们看到的都是 struct file 文件对象!

在这一层我们 以统一的视角看待所有的设备,往上我们就看作 "一切皆文件" !

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符也就是说:如果想打开一个文件,打开之后把读写方法属性交给 OS,

在内核里给该硬件创建 stuct file,初始化时把对应的函数指针指向具体的设备,

在内核中存在的永远都是 struct file,然后将 struct file 互相之间用链表关联起来。

站在用户的角度看,一个进程看待所有的文件都是以统一的视角看待的,

所以当我们访问一个 file 的时候,这个 file 具体指向底层的哪个文件或设备,

这完全取决于其底层对应的读写方法指向的是什么方法!

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 这操作是不是感觉很熟悉!?

多态?C++ 中运行时多态用的虚表和虚函数指针,那不就是函数指针么?

"上层使用同一对象,指针指向不同的对象,最终就可以调用不同的方法"

这令人拍手叫绝的操作,你可以理解为:多态的前身

📚 补充:上面画的图,在往上走,就回到了内核的映射关系了:

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符 这里的 struct file 指向的硬件设备是谁,就取决于底层的硬件是怎么设计的了。

通过操作系统层做了一层软件封装,达到了这样的效果。

底层叫硬件,而 具体的硬件读写方法是驱动干的,具体的硬件读写是驱动程序要做的,

OS 只管跟外设要求其提供读写方法,最终 OS 在内核中给它们抽象成 struct file

把它们都看作文件,然后通过函数指针指向具体的文件对应的设备,就完成了 "一切皆文件" !

0x03 初识 VFS(虚拟文件系统)

上面说的这种设置一套 struct file 来表示文件的内存文件系统的操作,

我们称之为  (virtual file system) ,即 虚拟文件系统 。 

虚拟文件系统(VFS)是 Linux 内核中非常有用的一个方面,因为它为文件系统提供了一个通用的接口抽象。VFS 在 SCI 和内核所支持的文件系统之间提供了一个交换层。

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

0x04 回头看问题:fd 的 0,1,2,3... 

至此,我们梳理完了。现在我们再回过头看 fd 的 1,2,3,4... 就能有一个清楚的认识了。

现在我们再我们最开始的问题,想必大家已经做到 "知其然知其所以然" 了!

为什么从 3 开始,而不是从 0 开始?0, 1, 2 去哪了?

💡 stdin,stdout,stderr 和 0,1,2 是对应关系,因为 open 时默认就打开了,这也是为什么我们默认打开一个新的文件,fd 是从 3 开始的而不是 0 开始的真正原因!

"突然茅塞顿开,上一章打印出 fd 是 3 的疑惑终于解决了!"

  0, 1, 2, 3, 4……,是不是有点像数组下标?

💡 不是有点像,它其实上就是数组下标!fd 0,1,2,3,4...  在内核中属于进程和文件的对应关系,是用数组来完成映射的,这些数字就是数组的下标。read, write, close 这些接口都必须用 0,1,2,3,4 来找到底层对应的 struct file 结构,进而访问到底层对应的读写方法 (包括相关的属性,缓冲区等) 。

o_trunc,看表情包学Linux,服务器,linux,运维,文件描述符

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2023.3.24
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.文章来源地址https://www.toymoban.com/news/detail-782348.html

到了这里,关于【看表情包学Linux】初识文件描述符 | 虚拟文件系统 (VFS) 初探 | 系统传递标记位 | O_TRUNC | O_APPEND的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【看表情包学Linux】IPC 进程间通信 | PIPE 管道 | 匿名管道 | 管道通信的原理 | 系统调用: pipe 接口

       🤣  爆笑 教程  👉 《看表情包学Linux》 🔥 CSDN 累计订阅量破千的火爆 C/C++ 教程的 2023 重制版,C 语言入门到实践的精品级趣味教程。 了解更多: 👉  \\\"不太正经\\\" 的专栏介绍  ← 试读第一章 订阅链接: 🔗 《C语言趣味教程》 ← 猛戳订阅! 目录 Ⅰ. 进程间通信(I

    2024年02月14日
    浏览(39)
  • 【看表情包学Linux】软硬链接

      ​​​​​​​ 🤣  爆笑 Linux  教程:  👉 《看表情包学Linux》 🐴     本篇博客全站热榜排名: 9 💭 写在前面: 上面我们学到的所有东西,全部都是在内存中的。是不是所有的文件都被打开了呢?不是所有的文件,都被打开的,我们之前研究的是进程打开的文件,

    2024年02月02日
    浏览(38)
  • 【看表情包学Linux】软硬链接 | 动静态库

       🤣  爆笑 教程  👉 《看表情包学Linux》👈   猛戳订阅     🔥 💭 写在前面: 上一章我们讲解了 inode,为文件系统收了尾,这几章我们充分地讲解完了文件系统的知识点,现在我们开始开始学习软硬链接了。如果没有文件系统的铺垫,想直接理解软硬链接难免有些困

    2024年02月16日
    浏览(43)
  • 【看表情包学Linux】进程优先级 | 查看系统进程 | 优先级修改 | 进程的切换 | 竞争性与独立性 | 并行并发的概念 | 环境变量

       🤣  爆笑 教程  👉 《看表情包学Linux》👈   猛戳订阅     🔥 ​ 💭 写在前面: 我们先讲解进程的优先级,探讨为什么会存在优先级,以及如何查看系统进程、进程优先级的修改。然后讲解进程的切换,首次介绍进程的竞争性、独立性,以及并行和并发的概念,在通

    2024年01月19日
    浏览(43)
  • 【看表情包学Linux】缓冲区的概念 | Git 三板斧 | 实现简易进度条

       爆笑教程,只送有缘人  👉 《看表情包学Linux》 💭 写在前面: 本章我们先对缓冲区的概念进行一个详细的探究,之后会带着大家一步步去编写一个简陋的 \\\"进度条\\\" 小程序,过程还是挺有意思的,虽然实现的过程表现得非常沙雕,但它是本 Linux 专栏中第一个小程序。

    2024年02月02日
    浏览(50)
  • 【看表情包学Linux】软硬链接 | 软连接数 | 创建软硬链接 | 动静态库 | 生成静态库 | 生成动态库

       🤣  爆笑 教程  👉 《看表情包学Linux》👈   猛戳订阅     🔥 💭 写在前面: 上一章我们讲解了 inode,为文件系统收了尾,这几章我们充分地讲解完了文件系统的知识点,现在我们开始开始学习软硬链接了。如果没有文件系统的铺垫,想直接理解软硬链接难免有些困

    2024年02月14日
    浏览(48)
  • 【看表情包学Linux】插叙:实现简易的 Shell | 通过内建命令实现路径切换 | 再次理解环境变量

       🤣  爆笑 教程  👉 《看表情包学Linux》👈   猛戳订阅     🔥 💭 写在前面: 本章是个 \\\"插叙\\\",前几章我们学了程序替换,现在我们可以尝试动手做一个 \\\"会创建,会终止,会等待,会程序替换\\\" 的简易 shell 了。通过本章的内容,可以进一步巩固进程替换,学习内建

    2024年02月22日
    浏览(59)
  • 【看表情包学Linux】磁盘基础知识 | CHS 寻址 | 逻辑扇区 LBA | 索引节点 inode | 伪删除 inode bitmap 1→0

      ​​​​​​​ 🤣  爆笑 Linux  教程:  👉 《看表情包学Linux》 🐴     本篇博客全站热榜排名: 9 💭 写在前面: 上面我们学到的所有东西,全部都是在内存中的。是不是所有的文件都被打开了呢?不是所有的文件,都被打开的,我们之前研究的是进程打开的文件,

    2024年02月16日
    浏览(47)
  • 看表情包学C语言 ——局部优先原则

        🔗 【C语言趣味教程】专栏介绍👈 猛戳了解!!! 0x00 引入:什么是作用域? 变量和常量在程序中都是有作用范围的,这个范围我们称之为变量的  作用域 (scope) 。 作用域也称为 \\\"定义域\\\",是程序中 定义的变量所存在的区域,出了该区域变量就不能被访问。 变量的作

    2024年02月14日
    浏览(35)
  • 一.初识Linux 1-3操作系统概述&Linux初识&虚拟机介绍

    目录 一.初识Linux 1.操作系统概述 计算机组成 硬件: 软件: 操作系统: 操作系统工作流程 操作系统作用 常见的操作系统 PC端: 移动端:(掌上操作系统) 一.初识Linux 2.Linux初识 linux系统的诞生 Linux内核 Linux发行版 一.初识Linux 3.虚拟机介绍 虚拟机 ​ 计算机:硬件和软件组

    2024年01月22日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包