【第18期】核心思维:CPU是“保姆”还是“调度员”?

核心差异:裸机开发(Bare-metal)关注的是过程,而 RTOS 开发关注的是状态

1. 裸机模型:CPU 是个操碎心的“保姆”

回顾我们在上一期写的“时间片轮询”代码,虽然它已经非阻塞了,但 CPU 的生活依然很苦。

场景:你要煮饭(Task A)、烧水(Task B)和收快递(Task C)。

  • 裸机做法: CPU 就像一个焦虑的保姆,在厨房和门口之间来回疯狂折返跑。

    • 跑去厨房:“水开了吗?” -> 没开。

    • 跑去门口:“快递来了吗?” -> 没来。

    • 跑去电饭煲:“饭好了吗?” -> 没好。

    • ... (无限循环,每秒跑几百万次)

代码写照

while(1) {
    if (UART_Rx_Flag) { ... }  // 看了眼门口
    if (Timer_Flag)   { ... }  // 看了眼锅里
    // CPU 始终全速运行,哪怕没事干也在空转检测
}

本质:CPU 实际上是在空耗。虽然看起来利用率是 100%,但 99% 的指令都是无效的“检查”。这不仅费电,而且一旦某个任务处理慢了(比如煮饭时把手烫了),收快递的任务就彻底被耽误了。


2. RTOS 模型:CPU 是个高冷的“调度员”

RTOS(实时操作系统)引入了一个颠覆性的概念:任务状态 (Task State)。 特别是 “阻塞 (Blocked)” 状态,这是裸机里不存在的。

场景:同样的任务。

  • RTOS 做法: CPU 变身调度员,坐在办公室里喝茶。

    • 烧水任务说:“我要烧 5 分钟。”

    • 调度员 (CPU) 说:“好,你出去(进入阻塞态),5 分钟内别让我看见你。”

    • 收快递任务说:“我在等电话。”

    • 调度员说:“好,你去睡觉(进入阻塞态),电话响了再叫醒你。”

    • 这时候如果没有其他任务,CPU 就直接休眠(进入低功耗模式)。

只有当“5分钟到了”或者“电话响了(中断来了)”,对应的任务才会从“阻塞态”变为“就绪态 (Ready)”,调度员才会把 CPU 的使用权交给它。


3. 灵魂对比:延时的本质

这是理解 RTOS 最好的切入点。

裸机延时 (Delay / Time Check)

// 方式 A:死等 (最差)
HAL_Delay(500); // CPU 在这 500ms 里除了数数,啥也干不了

// 方式 B:轮询 (好一点)
if (GetTick() - last > 500) { ... } // CPU 还是得不断地回来检查这个 if 条件

RTOS 延时 (Yield / Block)

// FreeRTOS 为例
vTaskDelay(500);

这行代码背后的含义是:

  1. 当前任务告诉调度器:“我主动放弃 CPU,请把我从【就绪列表】里删掉,放入【延时列表】。”

  2. 调度器立刻去【就绪列表】里找优先级最高的下一个任务去运行。

  3. 甚至如果所有任务都阻塞了,系统会自动运行一个“空闲任务 (Idle Task)”,在这个任务里让 CPU 进入睡眠模式省电。

结论vTaskDelay 不是“延时”,而是**“让权”**。


4. 为什么说这是“思维跃迁”?

从裸机转 RTOS,最难改的不是 API,而是**“独占”的习惯**。

  • 裸机思维:我觉得这段代码很重要,我要一口气跑完,谁也别打断我。

  • RTOS 思维:这段代码我在等数据,数据没来我就主动挂起(Pending/Block),让 CPU 去处理别的事情。

这种转变带来了三个巨大的红利:

  1. 模块化解耦:写按键任务的人,完全不用关心显示屏任务需要多久。大家各写各的 while(1),互不干扰。

  2. 实时性保障:高优先级任务(如电机控制)可以随时抢占低优先级任务(如界面刷新),不再受限于 if 轮询的顺序。

  3. 功耗管理:这是裸机很难做到的。RTOS 天然知道什么时候“大家都没事干”,可以自动进入低功耗。


本章关键点

  1. 裸机 (Polled):CPU 主动去轮询每个任务,“你好了吗?”。效率低,响应慢。

  2. RTOS (Event-Driven):任务发生事件(时间到、数据来)后主动唤醒 CPU。效率高,实时性强。

  3. 核心动作:裸机是“死等”,RTOS 是“挂起 (Block)”。

<think>好的,用户需要一份针对TXT文档小说的数据预处理保姆级教程,适合初学者复制粘贴的自动运行代码。首先,我需要回顾之前的回答,确保这次的内容更详细,步骤更清晰。 用户之前已经得到了一个预处理脚本,但可能在使用过程中遇到了问题,或者需要更详细的指导。作为保姆级教程,必须每个步骤都详细说明,包括环境配置、代码使用、参数设置等。 首先,用户是初学者,可能对Python环境不熟悉,所以需要指导如何安装必要的库,比如chardet、jieba、tqdm。要明确写出安装命令,避免他们遇到依赖问题。 然后,代码部分需要逐行解释,但用户要求复制粘贴,所以可能需要分开讲解和提供完整代码。例如,在教程中分步骤解释每个函数的作用,然后给出完整的代码块供复制。 接下来,停用词表的部分,用户可能需要一个示例停用词表的内容,或者提供获取方式,比如常用的中文停用词表链接,或者直接给出一个简单的示例文件内容,让他们自己创建。 使用示例部分要具体,比如输入路径和输出路径的示例,最好用实际例子,比如在Windows和Linux下的路径写法,避免用户因为路径格式错误而运行失败。 此外,用户可能不知道如何处理整个文件夹,需要说明如何指定输入路径为文件夹,并确保所有txt文件都被处理。同时,常见问题部分需要预见到编码问题、章节分割不准确、分词效果差等情况,给出解决方案。 扩展建议部分,可以根据用户需求,提供添加自定义清洗规则、保留原始结构、日志记录等方法,让用户可以根据需要调整代码。 最后,相关问题部分需要关联之前的问题,比如处理不同章节格式、优化内存占用等,帮助用户进一步解决问题。 需要检查之前的回答,确保不重复,并且补充更多细节,比如更详细的环境配置步骤,代码注释,示例运行结果等。同时,确保所有命令行指令正确,代码无误,避免用户复制后运行出错。 可能还需要注意中文字符的处理,比如文件编码保存为UTF-8,防止乱码。另外,章节分割的正则表达式可能需要更灵活,比如处理“卷”或“回”等不同章节标题,但用户之前的问题提到过,这里可以建议修改正则表达式来适应。 总之,整个教程需要从零开始,详细到每个步骤,确保初学者能顺利跟随,并且代码可以直接运行,处理他们的小说TXT文件。</think>以下是为您定制的**保姆级TXT小说预处理教程**,包含可直接复制的完整代码、详细配置说明和常见问题解决方案: --- ### **环境准备(3分钟)** 1. 安装Python 3.8+ ([官网下载](https://www.python.org/downloads/)) 2. 打开CMD/Terminal执行: ```bash pip install chardet jieba tqdm ``` --- ### **完整代码(复制即用)** ```python # -*- coding: utf-8 -*- import os import re import chardet import jieba from tqdm import tqdm def detect_encoding(file_path): """ 自动检测文件编码 """ with open(file_path, 'rb') as f: return chardet.detect(f.read())['encoding'] def clean_text(content): """ 文本清洗 """ # 替换全角空格/特殊空格 content = content.replace('\u3000', ' ').replace('\xa0', ' ') # 保留中文、基本标点、字母数字(可自定义修改) content = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9\s,。?;:!、“”‘’—…()《》]', '', content) # 合并多余空行和空格 content = re.sub(r'\n{3,}', '\n\n', content) return re.sub(r' +', ' ', content) def process_file(input_path, output_dir, stopwords=None): """ 处理单个文件 """ try: # 自动检测编码 encoding = detect_encoding(input_path) with open(input_path, 'r', encoding=encoding, errors='replace') as f: content = f.read() # 执行清洗 cleaned = clean_text(content) # 分词处理(可选) if stopwords: words = [word for word in jieba.lcut(cleaned) if word not in stopwords] cleaned = ' '.join(words) # 保存结果 output_path = os.path.join(output_dir, os.path.basename(input_path)[:-4] + "_clean.txt") with open(output_path, 'w', encoding='utf-8') as f: f.write(cleaned) return True except Exception as e: print(f"处理失败: {os.path.basename(input_path)} | 错误: {str(e)}") return False if __name__ == "__main__": # ========== 配置区(按需修改)========== INPUT_PATH = "./raw_novels" # 原始小说存放路径 OUTPUT_DIR = "./cleaned_novels" # 清洗后输出路径 STOPWORDS_PATH = "./stopwords.txt" # 停用词表路径(没有可填None) # ===================================== # 加载停用词表 stopwords = None if STOPWORDS_PATH and os.path.exists(STOPWORDS_PATH): with open(STOPWORDS_PATH, 'r', encoding='utf-8') as f: stopwords = set(f.read().splitlines()) # 创建输出目录 os.makedirs(OUTPUT_DIR, exist_ok=True) # 获取待处理文件列表 file_list = [] if os.path.isfile(INPUT_PATH): file_list = [INPUT_PATH] else: for root, _, files in os.walk(INPUT_PATH): file_list.extend([os.path.join(root, f) for f in files if f.endswith('.txt')]) # 进度条显示处理过程 success_count = 0 with tqdm(total=len(file_list), desc="处理进度") as pbar: for file_path in file_list: if process_file(file_path, OUTPUT_DIR, stopwords): success_count += 1 pbar.update(1) print(f"\n处理完成!成功处理 {success_count}/{len(file_list)} 个文件") print(f"输出目录: {os.path.abspath(OUTPUT_DIR)}") ``` --- ### **使用说明(图解步骤)** #### 步骤1:准备文件结构 ``` 项目文件夹/ ├── raw_novels/ # 存放原始小说txt(支持子文件夹) │ ├── 小说1.txt │ └── 小说2.txt ├── stopwords.txt # 中文停用词表(可选) └── novel_cleaner.py # 本代码文件 ``` #### 步骤2:配置停用词表(示例内容) ```text 的 了 是 在 和 ... ``` (可从[中文停用词库](https://github.com/goto456/stopwords)下载完整版) #### 步骤3:运行脚本 ```bash python novel_cleaner.py ``` --- ### **功能扩展指南**(按需修改`clean_text`函数) ```python def clean_text(content): # 添加自定义规则(示例) content = content.replace("※※※", "[分隔符]") # 替换特定符号 content = re.sub(r'\d{4}-\d{2}-\d{2}', '', content) # 删除日 content = re.sub(r'作者的话.*?\n', '\n', content) # 删除作者注释 return content ``` --- ### **常见问题解决** 1. **编码错误**: - 现象:`UnicodeDecodeError` - 方案:在代码第16行`errors='replace'`会自动替换无法解码的字符 2. **章节分割不准确**: 修改正则表达式(第45行附近): ```python re.split(r'(第[一二三四五六七八九十百千万零〇\d]+[章节卷集回])', content) ``` 3. **分词效果不佳**: 在`jieba.lcut`前添加: ```python jieba.load_userdict("自定义词典.txt") # 添加专有名词词典 ``` --- ### **扩展建议** 1. 添加`自定义清洗规则`:在`clean_text`函数中插入正则表达式 2. 保留原始目录结构:在保存时使用`os.path.relpath` 3. 添加日志记录:使用`logging`模块记录处理过程 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值