【实战项目】C/C++ +Linux 详解:手写日志库+简易shell
前十天我们完整通关了:计算机网络、操作系统原理、Linux系统、MySQL、Redis 等核心理论。理论背得滚瓜烂熟,一行底层代码写不出来。C/C++ 基本功 + Linux系统调用 + 内存理解 + 文件IO + 进程调度 + 数据结构手写能力。今天一次性完成两个高含金量底层项目1.高性能Linux日志库(C语言):文件IO、缓冲区、时间戳、日志分级、自动滚存2.Linux简易Shell解释器(
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。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)