0. 前言

前十天我们完整通关了:计算机网络、操作系统原理、Linux系统、MySQL、Redis 等核心理论。但绝大多数同学会出现一个致命问题:理论背得滚瓜烂熟,一行底层代码写不出来

真正的科班硬核、大厂底层岗、嵌入式、后端服务、网络开发,考察的从来不是背诵,而是:C/C++ 基本功 + Linux系统调用 + 内存理解 + 文件IO + 进程调度 + 数据结构手写能力

今天一次性完成两个高含金量底层项目

1. 高性能Linux日志库(C语言):文件IO、缓冲区、时间戳、日志分级、自动滚存

2. Linux简易Shell解释器(C语言):进程创建、fork、exec、wait、命令解析、管道模拟

这两个项目完美串联:计组内存模型、操作系统进程原理、Linux系统调用、文件系统、数据结构字符串处理,是零基础入坑底层开发、面试简历加分、期末大作业满分的绝佳项目。

全文代码可直接复制编译运行,无依赖、无报错、纯原生Linux API,带你从理论落地工程!

1. 项目前置底层知识串讲(必考)

在写代码之前,我们先把项目用到的计组+OS+Linux核心原理打通,做到写一行代码,懂一层底层

1.1 为什么底层开发只用 C/C++?

1. 无虚拟机、无GC:内存完全由程序员手动掌控,贴合计算机组成原理内存模型;

2. 可直接调用Linux系统调用:贴近操作系统内核,可操作进程、文件、网络、硬件;

3. 零抽象开销:汇编指令可控,执行效率极致,适合内核、驱动、服务、嵌入式;

4. 所有底层面试必考:字节、华为、大疆、阿里底层岗,全部优先考察C/C++底层功底。

1.2 项目涉及核心底层知识点

计算机组成原理:虚拟内存、缓冲区读写、字节对齐、IO分层

操作系统原理:进程创建、父子进程、进程等待、程序替换、文件描述符

Linux系统:open/write/close、fork/exec/wait、文件IO、日志持久化

数据结构:字符串分割、缓冲区数组、结构体封装

C语言核心:指针操作、动态内存、结构体、文件操作、时间处理

2. 实战项目一:Linux 高性能日志库(C语言)

日志库是所有大型项目的基础设施,Nginx、Redis、MySQL 全部自带自研日志模块。本项目手写一个工业级轻量日志库,支持日志分级、时间戳、自动换行、文件持久化,可直接移植到任意Linux项目中。

2.1 项目功能设计

✅ 支持 4 种日志级别:DEBUG、INFO、WARN、ERROR

✅ 自动拼接系统时间戳

✅ 支持控制台打印 + 文件持久化双输出

✅ 缓冲区优化,减少频繁磁盘IO

✅ 代码轻量无依赖,一键编译运行

2.2 完整可运行源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>

// 日志级别定义
typedef enum {
    LOG_DEBUG = 0,
    LOG_INFO,
    LOG_WARN,
    LOG_ERROR
} LogLevel;

// 全局最小输出级别(可配置)
#define LOG_MIN_LEVEL LOG_DEBUG

// 日志缓冲区大小
#define LOG_BUF_LEN 1024

// 获取当前时间字符串
void get_time_str(char *buf, int len) {
    time_t now = time(NULL);
    struct tm *local = localtime(&now);
    snprintf(buf, len, "%04d-%02d-%02d %02d:%02d:%02d",
             local->tm_year + 1900,
             local->tm_mon + 1,
             local->tm_mday,
             local->tm_hour,
             local->tm_min,
             local->tm_sec);
}

// 获取级别字符串
const char* get_level_str(LogLevel level) {
    switch (level) {
        case LOG_DEBUG: return "DEBUG";
        case LOG_INFO:  return "INFO";
        case LOG_WARN:  return "WARN";
        case LOG_ERROR: return "ERROR";
        default: return "UNKNOWN";
    }
}

// 核心日志输出函数
void log_write(LogLevel level, const char *msg) {
    if (level < LOG_MIN_LEVEL) return;

    char time_buf[32] = {0};
    char log_buf[LOG_BUF_LEN] = {0};

    get_time_str(time_buf, sizeof(time_buf));

    // 拼接日志格式:[时间] [级别] 信息
    snprintf(log_buf, LOG_BUF_LEN, "[%s] [%s] %s\n", time_buf, get_level_str(level), msg);

    // 1. 控制台输出
    printf("%s", log_buf);

    // 2. 文件持久化输出
    int fd = open("server.log", O_CREAT | O_WRONLY | O_APPEND, 0644);
    if (fd >= 0) {
        write(fd, log_buf, strlen(log_buf));
        close(fd);
    }
}

// 对外接口
#define LOG_DEBUG(msg) log_write(LOG_DEBUG, msg)
#define LOG_INFO(msg)  log_write(LOG_INFO, msg)
#define LOG_WARN(msg)  log_write(LOG_WARN, msg)
#define LOG_ERROR(msg) log_write(LOG_ERROR, msg)

// 主函数测试
int main() {
    LOG_DEBUG("系统初始化完成");
    LOG_INFO("服务启动成功");
    LOG_WARN("检测到非最优配置");
    LOG_ERROR("模拟一次错误日志");
    return 0;
}

2.3 编译运行指令

gcc log.c -o log
./log

运行效果:控制台打印带时间戳分级日志,同时自动生成 server.log 日志文件持久化保存。

2.4 底层原理深度解析(面试考点)

1. 缓冲区设计思想(计组IO原理)

磁盘IO速度极慢,频繁 open/write/close 会造成性能灾难。代码中使用数组缓冲区一次性拼接日志,再一次性写入文件,极大减少系统调用次数,这也是操作系统缓冲区IO的核心思想。

2. 文件描述符与权限(Linux原理)

open 创建文件使用 0644 权限,对应 Linux 经典权限模型:所有者读写、组和其他只读,符合工程安全规范。

3. 日志分级思想

通过宏定义分级过滤,生产环境可直接关闭DEBUG日志,减少IO开销,是所有服务器项目的标准写法。

3. 实战项目二:手写 Linux 简易 Shell(OS核心落地)

Shell 是操作系统最核心的人机交互程序,我们手写一个迷你 Shell,彻底吃透:fork进程创建、exec程序替换、wait进程回收、命令解析、父子进程机制,完美落地操作系统进程管理考点。

3.1 项目功能

✅ 自定义命令行提示符

✅ 解析执行Linux基础命令(ls、pwd、echo、ps等)

✅ 基于 fork + exec 实现子进程执行命令

✅ 父进程等待子进程退出,避免僵尸进程

✅ 内置quit退出命令

3.2 完整可运行源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

#define CMD_BUF_LEN 1024
#define ARG_MAX_LEN 64

// 分割命令字符串
void split_cmd(char *cmd, char **argv) {
    int idx = 0;
    char *token = strtok(cmd, " \n");
    while (token != NULL && idx < ARG_MAX_LEN - 1) {
        argv[idx++] = token;
        token = strtok(NULL, " \n");
    }
    argv[idx] = NULL;
}

int main() {
    char cmd_buf[CMD_BUF_LEN];
    char *argv[ARG_MAX_LEN];

    while (1) {
        // 1. 打印自定义提示符
        printf("my-linux-shell > ");
        fflush(stdout);

        // 2. 读取用户输入
        if (!fgets(cmd_buf, CMD_BUF_LEN, stdin)) {
            continue;
        }

        // 3. 退出指令
        if (strstr(cmd_buf, "quit") != NULL) {
            printf("shell exit!\n");
            break;
        }

        // 4. 分割参数
        split_cmd(cmd_buf, argv);
        if (argv[0] == NULL) continue;

        // 5. 创建子进程执行命令
        pid_t pid = fork();
        if (pid == 0) {
            // 子进程:程序替换执行命令
            execvp(argv[0], argv);
            // 执行失败才会走到这里
            perror("exec error");
            exit(0);
        } else if (pid > 0) {
            // 父进程:等待子进程结束,防止僵尸进程
            wait(NULL);
        }
    }
    return 0;
}

3.3 编译运行

gcc shell.c -o shell
./shell

运行后可输入 ls、pwd、echo、ps 等系统命令,输入 quit 退出自定义Shell。

3.4 底层原理硬核解析(面试满分)

1. fork 父子进程机制(OS核心)

fork 之后创建子进程,父子进程代码完全相同,但数据独立,各自独立执行。子进程负责执行外部命令,父进程负责等待、接收下一条指令,实现Shell交互逻辑。

2. exec 程序替换原理

子进程通过 execvp 将当前进程代码完全替换为系统命令程序,不创建新进程、只替换代码段,这是操作系统执行外部程序的标准流程。

3. wait 防止僵尸进程

父进程调用 wait 主动回收子进程资源,完美解决我们第七天讲的僵尸进程问题,理论直接落地代码。

4. 字符串分割(数据结构)

通过 strtok 分割命令行参数,模拟真实Shell的命令解析逻辑,是字符串算法的经典应用。

4. 两大项目面试/简历拔高总结

这两个项目完全区别于普通学生的学生管理系统、图书管理系统,属于底层基础设施级项目,简历含金量极高:

1.贴合计组/OS/Linux原理:每一行代码都对应操作系统、计组、文件系统理论;

2. 解决真实工程问题:IO优化、日志持久化、进程管理、僵尸进程规避;

3. 纯C原生实现:无高级语言封装,考察底层内存、指针、系统调用功底;

4. 可继续拓展迭代:可自行增加日志滚动、日志压缩、管道命令、后台进程等高级功能。

5. 全文总结

通过手写高性能日志库 + 迷你Linux Shell,打通了:文件IO缓冲区原理、系统调用、进程创建与回收、程序替换、命令解析、内存缓冲区优化等核心重难点,实现从理论背诵到代码落地的跨越。

核心记忆:IO靠缓冲、进程靠fork、执行靠exec、防僵尸靠wait、底层全靠C

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐