《密码系统设计》第九周预习

20231313 张景云《密码系统设计》第九周预习


AI对内容的总结

Headfirst C

一、系统调用基础

1. 核心定义

系统调用是操作系统内核中的函数,是C程序与硬件、操作系统交互的桥梁。C标准库(如printf())底层依赖系统调用,例如printf()会通过系统调用将字符串输出到屏幕。

2. 关键特性

  • 外部依赖:系统调用代码不在用户程序中,而是存储于操作系统内核或动态库(因操作系统而异)。
  • 错误处理通用规则:多数系统调用失败时返回-1,并将errno(定义于errno.h)设为对应错误码;可通过strerror(errno)函数获取错误描述信息,常见错误码如ENOENT=2(无此文件或目录)、EPERM=1(不允许操作)。

二、核心系统调用详解

1. system():简单但有局限的调用

(1)功能与用法

接收字符串参数并当作系统命令执行,是代码中运行外部程序的“捷径”,适合快速原型开发。

  • 示例:system("dir D:")(Windows列出D盘目录)、system("gedit")(Linux打开文本编辑器)。
  • 应用场景:简化文件操作,如通过拼接命令字符串,快速实现“带时间戳的日志追加”功能(无需编写复杂C文件操作代码)。

(2)缺陷与风险

  • 安全漏洞:命令字符串拼接易遭“命令注入攻击”,例如输入' && ls / && echo ',会在执行日志追加时额外列出系统根目录内容,甚至可能被注入删除文件、启动病毒的命令。
  • 稳定性问题:注释含特殊字符(如撇号)会破坏命令语法;依赖PATH环境变量,可能因变量配置错误调用错误程序;无法灵活控制环境变量和命令参数。

2. exec()系列:更灵活的进程替换

(1)核心特性

  • 进程替换:运行新程序替换当前进程,新程序与原进程PID(进程标识符)相同,原进程代码在exec()成功后终止。
  • 头文件:需包含<unistd.h>
  • 错误判断:若exec()调用后程序仍继续执行,说明调用失败(因成功时原进程已被替换)。

(2)分类与用法

exec()系列按参数传递方式和功能差异,分为列表函数数组函数,函数名后缀字符对应不同功能:

后缀字符 功能描述
l(list) 以参数列表形式传递命令行参数,需以NULL结尾,且第一个参数(程序路径/名)与第二个参数(命令行首参)需相同
v(vector) 以字符串数组形式传递命令行参数,数组需以NULL结尾
p(path) 自动根据PATH环境变量查找程序,无需指定完整路径
e(environment) 可自定义环境变量数组,数组需以NULL结尾
  • 列表函数示例
    • execl("/home/flynn/clu", "/home/flynn/clu", "paranoids", "contract", NULL):指定完整路径,列表传参。
    • execlp("clu", "clu", "paranoids", "contract", NULL):通过PATH查找程序,列表传参。
    • execle("/home/flynn/clu", "/home/flynn/clu", "paranoids", "contract", NULL, env_vars):自定义环境变量,列表传参。
  • 数组函数示例
    • execv("/home/flynn/clu", my_args):指定完整路径,数组传参(my_args为含参数的字符串数组,以NULL结尾)。
    • execvp("clu", my_args):通过PATH查找程序,数组传参。

3. fork():进程克隆工具

(1)核心功能

克隆当前进程,生成父进程(原进程)和子进程(副本):

  • 子进程与父进程代码、变量值完全相同,仅PID不同。
  • 返回值规则:向父进程返回子进程PID(非零值),向子进程返回0;失败时返回-1
  • 头文件:需包含<unistd.h>,进程ID(PID)需用pid_t类型存储(适配不同操作系统的整数类型)。

(2)关键机制

  • 写时复制(Copy-on-Write):操作系统为提高效率,初始不复制父进程数据,仅当子进程修改数据时,才为其复制对应数据,避免不必要的资源消耗。
  • 与exec()配合使用:解决exec()替换进程后原程序终止的问题。流程为:
    1. 父进程调用fork()生成子进程;
    2. 子进程中调用exec()替换为目标程序;
    3. 父进程继续执行,实现“多进程并行”(如同时处理多个RSS源搜索)。

(3)平台差异

  • Windows不原生支持fork(),需通过Cygwin模拟(依赖Windows底层进程机制,效率低于Linux/Mac);
  • Windows替代方案:使用CreateProcess()函数(功能类似增强版system(),可参考微软MSDN文档)。

三、典型应用案例

1. 警卫巡逻日志程序(system()应用)

(1)功能

接收用户输入的巡逻注释,附加当前时间戳,追加到reports.log文件。

(2)核心代码(补全后)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>char* now() {time_t t;time(&t);return asctime(localtime(&t));
}int main() {char comment[80];char cmd[120];// 读取用户注释printf("Enter comment: ");fgets(comment, 80, stdin);// 拼接命令:echo "注释 时间" >> reports.logsprintf(cmd, "echo '%s %s' >> reports.log", comment, now());// 执行命令system(cmd);return 0;
}

(3)问题

存在命令注入风险,若用户输入含' && rm -rf / && echo ',可能删除系统文件。

2. 多RSS源新闻搜索程序(fork()+exec()应用)

(1)功能

循环遍历多个RSS源,通过fork()创建子进程,在子进程中调用execle()运行Python脚本rssgossip.py,并行搜索指定关键词新闻。

(2)核心代码(补全后)

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char *argv[]) {if (argc < 2) {fprintf(stderr, "Usage: %s <search_phrase>\n", argv[0]);return 1;}char *feeds[] = {"http://www.cnn.com/rss/celebs.xml","http://www.rollingstone.com/rock.xml","http://eonline.com/gossip.xml"};int times = 3;char *phrase = argv[1];int i;for (i = 0; i < times; i++) {char var[255];// 构造RSS_FEED环境变量sprintf(var, "RSS_FEED=%s", feeds[i]);char *vars[] = {var, NULL};// 创建子进程pid_t pid = fork();if (pid == -1) {fprintf(stderr, "Fork failed: %s\n", strerror(errno));return 1;}// 子进程:执行Python脚本if (pid == 0) {if (execle("/usr/bin/python", "/usr/bin/python", "./rssgossip.py", phrase, NULL, vars) == -1) {fprintf(stderr, "Can't run script: %s\n", strerror(errno));exit(1);}}}return 0;
}

(3)优势

  • 并行处理多个RSS源,效率高于串行执行;
  • 通过execle()指定程序路径和自定义环境变量,避免system()的安全风险和环境依赖问题。

四、关键要点与注意事项

1. 核心总结

系统调用 功能 优势 劣势/注意事项
system() 执行命令字符串 用法简单,适合快速开发 安全风险高(命令注入)、环境依赖强、无法灵活控制参数
exec()系列 替换当前进程 无命令解析风险、可自定义参数和环境变量 成功后原进程终止,需配合fork()实现多进程
fork() 克隆当前进程 实现多进程并行,配合exec()灵活控制外部程序 Windows不原生支持,需用pid_t存储PID

2. 开发建议

  • 优先选择exec()系列:若需调用外部程序,优先用exec()(如execlp()execle()),避免system()的安全漏洞;
  • 必须处理错误:系统调用均需检查返回值,结合errnostrerror()定位问题;
  • 跨平台适配:Windows环境下避免fork(),改用CreateProcess();Linux/Mac下合理使用fork()+exec()提升效率;
  • 规范数据类型:用pid_t存储进程ID,避免因平台整数类型差异导致兼容性问题。

对 AI 总结的反思

你的总结非常全面和系统,基本覆盖了《嗨翻C语言》第9章“进程与系统调用”的核心内容。以下是我对你的总结进行的反思与补充,旨在进一步完善细节、强调重点,并补充一些你可能遗漏的要点。


一、对现有总结的肯定

  • 结构清晰:从基础概念到具体系统调用,再到应用案例,逻辑层次分明。
  • 内容准确:对system()exec()fork()的功能、用法、优缺点描述准确。
  • 案例实用:两个典型程序(日志记录、RSS搜索)很好地体现了系统调用的实际应用场景。
  • 注意事项到位:强调了错误处理、平台差异、安全性等关键点。

二、反思与补充建议

1. 系统调用的本质与分类

  • 补充:系统调用是用户态程序进入内核态的接口,通常通过软中断(如int 0x80)或专用指令(如syscall)实现。
  • 强调system()exec()fork() 都是库函数,它们封装了底层的系统调用(如execveclone等)。

2. exec() 系列函数的参数细节

  • 补充说明
    • 第一个参数通常是程序路径(或通过PATH查找的名称)。
    • 第二个参数是argv[0],即程序名,通常与第一个参数相同。
    • 最后一个参数必须是NULL,表示参数列表结束。
    • 对于带e的版本(如execle),最后一个参数是环境变量数组,也以NULL结尾。

3. fork() 的返回值与父子进程逻辑

  • 补充
    • fork() 后,父子进程并发执行,执行顺序由调度器决定。
    • 子进程会继承父进程的文件描述符、信号处理方式、环境变量等
    • 父进程应使用wait()waitpid()回收子进程资源,避免僵尸进程。

4. Windows 平台的替代方案

  • 补充
    • Windows 下没有 fork(),也没有 exec() 系列。
    • 应使用 CreateProcess() 函数,它可以同时创建新进程并指定程序、参数、环境等。
    • 也可使用 _spawn() 系列函数(如 _spawnlp),它们是 POSIX 兼容的替代品。

5. 错误处理与 errno 的线程安全性

  • 补充
    • errno线程局部变量,每个线程有自己的 errno,因此在多线程程序中是安全的。
    • 应在系统调用失败后立即检查 errno,因为后续成功调用可能覆盖其值。

6. 安全性强化建议

  • 补充
    • 使用 exec() 时,应避免将用户输入直接作为参数,尤其是路径或命令名。
    • 对于 system(),如果必须使用,应对输入进行严格的转义和验证

三、补充代码示例:使用 wait() 回收子进程

你在 RSS 搜索程序中未处理子进程的回收,这可能导致僵尸进程。以下是补充版本:

#include <sys/wait.h>// 在 main 循环后添加等待子进程退出的代码
for (i = 0; i < times; i++) {int status;pid_t wpid = wait(&status);if (wpid == -1) {perror("wait error");break;}if (WIFEXITED(status)) {printf("Child %d exited with status %d\n", wpid, WEXITSTATUS(status));}
}

四、扩展知识点(可选了解)

主题 说明
wait() / waitpid() 回收子进程状态,避免僵尸进程
pipe() + fork() 实现父子进程间通信
dup2() 重定向子进程的标准输入/输出
signal() / sigaction() 处理进程间信号(如 SIGCHLD)
getpid() / getppid() 获取当前进程/父进程的 PID

总结

你的学习总结已经非常出色,具备很强的系统性和实用性。我提供的补充内容主要是为了:

  • 强化对系统调用本质的理解;
  • 补充跨平台和并发控制的细节;
  • 强调资源管理和安全性;
  • 提供进一步扩展学习的路径。

如果你正在准备面试或项目开发,建议重点掌握:

  • fork() + exec() 的经典组合;
  • 错误处理与平台兼容;
  • 进程间通信(如管道、信号)的扩展使用。

mermaid 代码与截图

  root((C语言进程与系统调用))系统调用基础核心定义操作系统内核函数C程序与硬件OS交互的桥梁C标准库底层依赖系统调用关键特性外部依赖代码不在用户程序中存储于内核或动态库错误处理规则失败返回-1设置errno变量strerror函数获取描述常见错误码ENOENT 无此文件EPERM 不允许操作核心系统调用详解system调用功能与用法执行命令字符串快速原型开发示例dir命令gedit编辑器缺陷与风险安全漏洞命令注入攻击稳定性问题特殊字符破坏依赖PATH变量exec系列核心特性进程替换PID保持不变需包含unistd.h错误判断机制分类与用法列表函数execlexeclpexecle数组函数execvexecvp后缀字符含义l 参数列表v 参数数组p PATH查找e 环境变量fork调用核心功能克隆当前进程父子进程PID不同返回值规则父进程返回子进程PID子进程返回0失败返回-1关键机制写时复制与exec配合使用平台差异Windows不支持Cygwin模拟CreateProcess替代典型应用案例警卫巡逻日志程序功能记录带时间戳日志核心代码system实现安全问题命令注入风险多RSS源新闻搜索功能并行搜索RSS源核心代码fork加exec实现优势并行处理安全性高关键要点与注意事项核心总结system 简单但危险exec 灵活可控fork 多进程基础开发建议优先选择exec系列必须处理错误跨平台适配规范数据类型扩展知识进程管理wait和waitpidgetpid和getppid进程间通信pipe加fork信号处理资源管理文件描述符继承僵尸进程避免

deepseek_mermaid_20251102_af9ec0

基于AI的学习

image

学习实践过程遇到的问题与解决方式(AI 驱动)


学习路径概览

阶段1:基础概念理解

问题1:进程替换概念抽象难懂

  • 症状:无法理解exec()成功后原进程"消失"的含义
  • AI解决方案
    用户:exec()成功后为什么后面的代码不执行?
    AI:用"演员换角色"比喻:- 原进程 = 演员A扮演角色X- exec() = 演员A瞬间换成角色Y的服装和台词- 角色X的剧本被完全丢弃
    
  • 验证方法:写测试程序,在exec()前后都打印信息,观察结果

问题2:fork()返回值混淆

  • 症状:不理解为什么一个函数返回两个值
  • AI助记口诀
    "父得子ID,子得零,失败都得负一"
    父进程 → 拿到孩子的身份证号(pid>0)
    子进程 → 拿到零(知道自己是孩子)  
    失败 → 拿到-1(创建失败)
    

阶段2:实践编码困难

问题3:exec()函数族选择困难

  • 症状:面对6个exec变体不知道用哪个
  • AI决策树
    需要传递环境变量? ↓ 是 → 用execle()或execve()↓ 否 → 参数已放在数组中?↓ 是 → 用execvp()(自动搜索PATH)↓ 否 → 用execlp()(列表传参+自动搜索)
    

问题4:僵尸进程问题

  • 症状:程序运行后进程表中留下僵尸进程
  • AI诊断与修复
    // 问题代码
    pid_t pid = fork();
    if (pid == 0) {execlp("ls", "ls", NULL);
    }
    // 缺少wait(),子进程变僵尸// AI建议修复
    pid_t pid = fork();
    if (pid == 0) {execlp("ls", "ls", NULL);exit(127); // exec失败处理
    } else {wait(NULL); // 回收子进程
    }
    

阶段3:高级概念理解

问题5:文件描述符继承机制

  • 症状:不理解重定向的实现原理
  • AI可视化解释
    原进程:fd表[0:stdin, 1:stdout, 2:stderr, 3:file.txt]↓ exec()替换
    新进程:fd表[0:stdin, 1:stdout, 2:stderr, 3:file.txt] ← 完全继承!
    这就是重定向 ls > file.txt 的基础
    

问题6:写时复制性能疑惑

  • 症状:"既然复制整个进程,为什么还说fork()高效?"
  • AI技术解析
    实际过程:
    1. fork()时:父子进程共享所有内存页(标记为只读)
    2. 当任一进程写入内存时:触发页错误 → 内核复制该页 → 修改权限为可写
    3. 结果:只复制真正被修改的页面,大幅减少内存拷贝
    

典型调试场景

场景1:exec()总是失败

用户现象

execl("ls", "ls", "-l", NULL); // 总是返回-1

AI诊断流程

  1. 检查errnoprintf("Error: %s\n", strerror(errno));
  2. 常见原因
    • 路径错误:用execlp("ls", ...)execl("/bin/ls", ...)
    • 权限问题:程序无执行权限
    • 参数格式:最后一个参数必须是NULL

解决方案

// 方法1:使用PATH搜索
execlp("ls", "ls", "-l", NULL);// 方法2:使用绝对路径  
execl("/bin/ls", "ls", "-l", NULL);

场景2:父子进程同步问题

用户现象:子进程输出与父进程输出混在一起

AI解决方案

// 添加进程同步
pid_t pid = fork();
if (pid == 0) {// 子进程立即执行execlp("ls", "ls", NULL);
} else {wait(NULL);  // 父进程等待子进程结束printf("子进程已完成\n");
}

学习效果验证方法

概念理解测试

AI生成测试题

  1. 如果fork()后不调用exec(),子进程会执行什么代码?
  2. system("ls")fork()+exec() 的主要区别是什么?
  3. 为什么exec()成功后的代码永远不会执行?

实践能力检验

AI建议的练习项目

// 项目1:实现简单shell
// 项目2:实现管道命令 ls | grep "test"
// 项目3:实现后台进程执行

学习策略总结

有效学习方法

  1. 概念 → 比喻 → 代码 三阶段理解
  2. 最小化示例:每个概念用一个最简单的程序验证
  3. 渐进复杂:从system()exec()再到fork()+exec()

AI辅助学习技巧

  1. 具体化提问:不说"我不懂fork()",而说"fork()返回值在父子进程中为什么不同"
  2. 请求示例:让AI提供可运行的代码片段
  3. 验证理解:向AI解释概念,请求纠正
  4. 实战调试:粘贴错误代码和输出,请求诊断

常见陷阱规避

  • 忘记exec()参数列表以NULL结束
  • 混淆exec()的路径参数和argv[0]
  • 忽略错误处理导致 silent failure
  • 忘记回收子进程产生僵尸进程

参考资料

AI工具

  • 豆包
  • Deepseek

图书

  • 《Windows C/C++加密解密实战》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/953587.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《密码系统设计》第九周预习

20231313 张景云《密码系统设计》第九周预习AI对内容的总结 Headfirst C 一、系统调用基础 1. 核心定义 系统调用是操作系统内核中的函数,是C程序与硬件、操作系统交互的桥梁。C标准库(如printf())底层依赖系统调用…

2025年程序员兼职常用的10个平台推荐 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

JavaScript笔记(1)

基本数据类型(值类型):Number、String、Boolean、Null、Undefined、Symbol、BigInt直接存储在栈内存中不可以动态地添加属性: let name = "bob" name.age = 22 // Cannot create property age on string…

回归 CSP-S2025游记

洛谷传送门去年打完 \(CSP-S\) 拿了 \(2=\) 没过线就退役回 \(whk\) 了,回归之后的第一站:\(CSP2025\)坐标 \(HA\)DAY 0 初赛前一周回归复习了一下 (其实复习的基本上都没考) DAY 0.5 CSP-S第一轮(2025.9.28) 起的…

使用netfilter_queue重定向IP数据包

使用netfilter_queue重定向IP数据包 一、开发环境 OS:Debian 12 gcc :15.1.0 安装libnetfilter-queue-dev开发工具包sudo apt-get install libnetfilter-queue-dev

线性表、串、数组、广义表

队列和栈 循环队列:队空 head=tail 队满 (tail+1)%size=head 空串:长度为0的串,不包含任何字符 空格串:一个或多个空格组成的串 串比较:以字符的ASCLL码的值,当其中一个串先结束,则另一个串长的为大。 让我们…

【赶紧收藏】7款Windows数据恢复神器!能解决99%的问题,手慢无!

随着全球智能手机和电脑用户数量的增长,对优质数据恢复软件的需求也日益增长。与此同时,随着数字用户数量的增加,数据丢失问题也愈发突出。 要恢复丢失的数据,你需要一款优秀的专业数据恢复软件,它能够从各种数据…

回归CSP-S2025游记

洛谷传送门去年打完 \(CSP-S\) 拿了 \(2=\) 没过线就退役回 \(whk\) 了,回归之后的第一站:\(CSP2025\)坐标 \(HA\)DAY 0 初赛前一周回归复习了一下 (其实复习的基本上都没考) DAY 0.5 CSP-S第一轮(2025.9.28) 起的…

分类测试

分类测试分类测试

有哪些好用的媒体播放器

HJX media player HJX media player是黄景行电脑软件制作的一款媒体播放器,支持多种格式的音频,例如.mp3 .mpg .wmp .mp4 .mpeg .bmp .png .jpeg .aac .ogg

THUSC 2024 游记

和 @GoodCoder666 一起,/bx 时间久远,好像记不得什么了 嗯好像没过d1t1,但是通过了d1t2,我记得是个好玩的题 day2的工程题好像很好拿分,但是当时还是太弱了读不懂信息熵,最后400- 拿了个3=跑路啦

2025年10月学习机品牌推荐:AI精准学榜对比榜单

开学不到一个月,家长群里“作业崩溃”截图再次刷屏:新课标词汇量陡增、数学建模题连家长都看不懂、物理实验视频要学生自己拍。教育部数据显示,2024 年中小学“双减”课后服务覆盖率已达 100%,但校内时间压缩,家庭…

2025年10月学习机品牌推荐:护眼大屏榜对比与品牌排名

开学不到一个月,不少家长发现孩子在家预习、复习效率低,作业错题反复出现,课外辅导班又贵又远。学习机因此成为“家庭第二课堂”的刚需:既要同步校内教材,又要能精准查漏补缺,还要护眼、易操作。教育部2025年7月…

JSOI 2024 游记

搬过来了( day -114514 无法停课( day 1 快进到开t1。写写写推推推 3h。奇怪的不完全的二分做法(?,假了假了。麻了麻了。要寄了怎么办。()于是扔,后两题随便写写暴力走人。 [0,100]+24+8=[32,132] upd:洛谷T1…

2025年10月学习机品牌评价榜:五款主流机型横向对比指南

孩子放学回家,作业堆积、错题反复、新课标改革后家长不会辅导,这是不少家庭每晚的真实场景。教育部“双减”之后,校内时间压缩,家庭学习场景被放大,家长对“同步、精准、护眼”的需求集中爆发。中怡康2025年三季度…

2025年11月专业太空舱民宿品牌推荐排行:优质厂家对比评价

随着旅游消费升级和个性化住宿需求增长,太空舱民宿作为新兴业态正迎来快速发展。根据文化和旅游部数据,2024年国内特色民宿市场规模同比增长23%,其中创新型住宿产品占比显著提升。选择太空舱民宿的投资者多为景区运…

2025年11月太空舱原材料推荐榜单:权威厂家综合评测与选择指南

随着太空舱在文旅住宿、移动办公等场景的快速普及,选择合适的原材料供应商成为项目成功的关键因素。无论是计划投资太空舱项目的企业主,还是负责采购的工程管理人员,都面临着如何从众多供应商中筛选出具备正规资质、…

2025年11月太空舱民宿推荐榜单:权威对比与选择指南

随着旅游消费升级与个性化住宿需求增长,太空舱民宿凭借其科技感与自然融合的特点逐渐成为文旅投资新热点。本文基于国家文旅部发布的住宿业创新指南、行业权威媒体市场调研数据及用户反馈,为计划投资太空舱民宿的从业…

2025年11月太空舱民宿品牌排行:优质工厂生产资质与服务全解析

随着旅游消费升级和个性化住宿需求增长,太空舱民宿作为一种新兴业态正快速崛起。根据文化和旅游部数据中心统计,2024年国内特色住宿预订量同比增长超过30%,其中具备科技感和自然体验的太空舱类民宿关注度显著提升。…

2025年11月太空舱原材料推荐评价:有实力供应商排行与采购建议

在太空旅游和高端住宿需求持续增长的背景下,太空舱原材料的选择成为产业链上下游企业关注的重点。许多从事文旅项目开发、移动房屋制造的企业主和采购负责人,往往面临原材料质量参差不齐、供应商服务不完善等实际问题…