文章目录
密码系统设计
推荐VSCode中安装Markdown插件和markdown pdf 插件完成作业
第十周预习报告
AI 对学习内容的总结(1分)
要求
- 让AI(kimi,元宝等)阅读学习内容并进行总结,教材内容可以使用微信读书或者云班课电子教材
总结
《Head First C》第十章主要介绍了进程间通信(Interprocess Communication,IPC)的概念和方法。以下是本章的主要内容总结:
-
进程间通信的重要性:
- 创建进程只是一半的工作,能够控制进程并在进程间传输数据是另一半。
- 进程间通信允许进程协同工作,完成复杂的任务。
-
重定向(Redirection):
- 通过命令行使用
>
和<
操作符可以重定向标准输出和标准输入到文件。 - 标准输出(stdout)、标准输入(stdin)和标准错误(stderr)是进程的三个默认数据流。
- 数据流可以被重定向到文件或其他数据流。
- 通过命令行使用
-
文件描述符(File Descriptors):
- 每个数据流由文件描述符表示,这是一个数字。
- 进程通过描述符表(descriptor table)来管理文件描述符和它们关联的数据流。
- 文件描述符不一定指向实际的文件,也可以是键盘、屏幕或网络连接等。
-
进程如何重定向自己:
- 进程可以通过修改描述符表来重定向自己的数据流。
fileno()
函数可以返回文件指针对应的文件描述符。dup2()
函数可以复制数据流,使得多个文件描述符指向同一个数据流。
-
错误处理:
- 展示了如何将错误处理代码抽象成一个函数,避免重复代码。
- 使用
exit()
函数可以快速终止程序。
-
等待进程结束:
waitpid()
函数可以让父进程等待子进程结束。waitpid()
函数返回后,可以通过WEXITSTATUS()
宏获取子进程的退出状态。
-
管道(Pipes):
- 管道是连接进程输出和另一个进程输入的机制。
pipe()
函数创建一个管道,并在描述符表中添加两个新的文件描述符。- 子进程通常关闭管道的读端,并将标准输出重定向到管道的写端。
- 父进程关闭管道的写端,并将标准输入重定向到管道的读端。
-
信号(Signals):
- 信号是操作系统发送给进程的简短消息,用于通知进程发生了某些事件。
- 默认情况下,进程会运行一个信号处理函数(signal handler)来响应信号。
- 可以使用
sigaction()
函数设置自定义的信号处理函数。 - 信号可以用于中断程序、清理资源或处理定时任务。
-
使用
alarm()
和sleep()
:alarm()
函数设置一个定时器,到期时发送SIGALRM
信号。sleep()
函数使程序休眠指定的秒数。
-
信号的发送和接收:
kill
命令可以用来向进程发送信号。raise()
函数允许进程向自己发送信号。
本章通过实际的代码示例和案例,讲解了如何在C语言中实现进程间通信,包括数据流的重定向、管道的使用、信号的处理等,这些都是编写能够并发执行多个任务的复杂程序的基础。
对 AI 总结的反思与补充(2分)
要求
- AI总结的问题
- 自己的补充
反思与补充
总结基本覆盖了《Head First C》第十章的主要内容,但可以进一步补充和完善以下几点:
-
信号处理的复杂性:
- 信号处理可能涉及到竞态条件和不可预测的行为,特别是在多线程环境中。在实际应用中,需要谨慎处理信号和线程之间的交互。
-
信号屏蔽字(Signal Masking):
- 在
sigaction
结构体中,可以通过信号屏蔽字(sa_mask
)暂时忽略某些信号,这对于避免在处理一个信号时接收到另一个信号非常重要。
- 在
-
信号的默认行为和忽略:
- 除了自定义信号处理函数外,还可以将信号设置为默认行为(
SIG_DFL
)或完全忽略(SIG_IGN
)。这些选项在某些情况下非常有用,但也需要小心使用,因为它们可能会影响程序的健壮性和调试。
- 除了自定义信号处理函数外,还可以将信号设置为默认行为(
-
信号和程序终止:
- 信号不仅可以用来优雅地终止程序,还可以用于处理紧急情况,比如用户中断或致命错误。
-
alarm()
函数的限制:alarm()
函数只能设置一个单一的定时器,并且它与sleep()
函数共享同一个定时器。这意味着不能同时使用alarm()
和sleep()
。
-
raise()
函数的使用场景:raise()
函数可以用来在自定义信号处理函数中发送信号,实现信号的升级(signal escalation),例如,从较轻微的错误信号升级到更严重的信号。
-
信号的发送和接收顺序:
- 在不同的操作系统和平台上,信号的发送和接收顺序可能不一致。开发者不应该依赖于信号的发送和接收顺序。
-
信号处理的最佳实践:
- 信号处理函数应该尽可能简短和快速,因为它们可能会在程序的任何地方被调用。此外,信号处理函数中不应该调用不是异步信号安全的函数。
-
kill()
命令的更多用法:kill()
命令不仅可以发送信号,还可以用于调试和监控进程状态。
-
实际应用中的进程间通信:
- 除了本章介绍的基本IPC机制外,实际应用中还可能涉及到更复杂的IPC技术,如共享内存、消息队列、信号量等。
学习思维导图(2分)
要求
- Mermaid 代码与截图(参考Mermaid MindMap语法)或者提交思维导图链接(如果使用线上编辑器,推荐processon,xmind,…)
思维导图
下面是个简单mermaid的思维导图,你可以根据你自己的需求修改
mindmap
root((密码系统设计第一周))
教材
graph TD
A[第十章: 进程间通信] --> B[进程间通信的重要性]
A --> C[重定向]
A --> D[文件描述符]
A --> E[进程如何重定向自己]
A --> F[错误处理]
A --> G[等待进程结束]
A --> H[管道]
A --> I[信号]
A --> J[使用alarm()和sleep()]
A --> K[信号的发送和接收]
B --> B1[控制进程与发送数据]
C --> C1[命令行重定向]
C1 --> C1a[使用>操作符]
C1 --> C1b[标准输入输出错误]
C --> C2[文件描述符与数据流]
C2 --> C2a[文件描述符]
C2 --> C2b[描述符表]
E --> E1[fileno()和dup2()]
E1 --> E1a[查找文件描述符]
E1 --> E1b[复制数据流]
F --> F1[错误代码抽象]
F1 --> F1a[exit()函数]
G --> G1[waitpid()函数]
G1 --> G1a[等待子进程结束]
G1 --> G1b[获取退出状态]
H --> H1[pipe()函数]
H1 --> H1a[创建管道]
H1 --> H1b[进程间数据流]
H --> H2[父子进程通信]
H2 --> H2a[子进程关闭读端]
H2 --> H2b[父进程关闭写端]
I --> I1[信号处理]
I1 --> I1a[sigaction()函数]
I1 --> I1b[自定义信号处理]
I --> I2[信号的默认行为]
I2 --> I2a[SIG_DFL]
I2 --> I2b[SIG_IGN]
J --> J1[alarm()和sleep()函数]
J1 --> J1a[设置定时器]
J1 --> J1b[程序休眠]
K --> K1[kill命令]
K1 --> K1a[发送信号]
K1 --> K1b[调试和监控]
K --> K2[raise()函数]
K2 --> K2a[自我信号发送]
K2 --> K2b[信号升级]
课件
网络空间安全
密码与密码系统
法律法规与标准
密码应用与密评
实践
gitee(github)
openssl
gmssl
上面mermaid实际效果,vscode中可以预览:
基于 AI 的学习(2分)
要求
- 至少找到自己理解不是太好 2 个概念,让 AI 对自己进行苏格拉底提问
- 参考下面提示语或者使用 AI Agent
提示词:“我在学习XXX知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”
- 核心是要求AI工具:“请你以苏格拉底的方式对我进行提问”
- 然后AI工具就会给你提问,如果不知道问题的答案,可以反问AI:“你的理解(回答)是什么?”
- 如果你觉得差不多了,可以先问问AI工具:“针对我XXX知识点,我理解了吗?”
- AI工具会给出它的判断,如果你也觉得自己想清楚了,可以最后问AI工具:“我的回答结束了,请对我的回答进行评价总结”,让它帮你总结一下。
学习内容
me
我在学习进程间通信的知识,请你以苏格拉底的方式对我进行提问,一次一个问题
ai
当然可以,让我们开始吧。首先,我想知道:
你能否告诉我,当我们谈到“进程间通信”时,你认为这涉及到哪些基本概念?
me
进程的概念,和通信的概念
ai
很好,你已经提到了两个核心概念:进程和通信。那么,让我们进一步探讨。你能描述一下,在你看来,什么是进程,它与程序有何不同?
me
进程是动态的概念,是在进行的程序
ai
没错,进程确实是程序的动态执行实例。那么,我问你,进程是如何与外界交互的呢?它如何接收输入和发送输出?
me
这里不太清楚
ai
没问题,我们来探讨一下。进程与外界交互主要通过几种方式:
标准输入输出:每个进程都有标准输入(stdin)、标准输出(stdout)和标准错误(stderr)这三个流。这些流允许进程从控制台接收输入,并向控制台或其他目的地发送输出。
文件描述符:在Unix-like系统中,一切皆文件。进程可以通过文件描述符与文件、设备、网络套接字等进行交互。
管道和命名管道(FIFO):管道允许一个进程的输出直接成为另一个进程的输入,而命名管道则允许不相关的进程之间进行通信。
信号:信号是操作系统发送给进程的异步事件,用于通知进程发生了某些事情,如用户中断(Ctrl-C)或错误条件。
共享内存和消息队列:这些是更高级的进程间通信机制,允许进程共享数据或发送格式化的消息。
套接字:套接字允许进程在网络上进行通信,无论是在同一台机器上还是跨网络。
了解了这些基本的交互方式后,你能告诉我,为什么我们需要进程间通信吗?
me
不太清楚
ai
进程间通信(Inter-Process
Communication,简称IPC)是操作系统中不同进程之间传递数据和信号的一种机制。我们需要进程间通信的原因主要包括以下几点:
资源共享:不同的进程可能需要访问相同的资源,如文件、设备或内存区域。进程间通信允许它们协调对这些资源的访问。
任务协调:在多任务操作系统中,不同的进程可能需要协同工作以完成复杂的任务。进程间通信提供了一种机制,使得进程可以相互通知状态变化或请求操作。
模块化:进程间通信支持软件的模块化设计,不同的模块可以作为独立的进程运行,通过通信机制来交互,这样可以提高系统的灵活性和可维护性。
并发执行:在多处理器系统中,进程可以在不同的CPU上并行执行。进程间通信允许这些并发执行的进程共享信息和协调工作。
错误处理:当一个进程遇到错误或异常情况时,它可能需要通知其他进程,以便采取适当的恢复措施。
数据交换:不同的进程可能需要交换数据,例如,一个进程生成数据,另一个进程处理数据。
系统服务:操作系统提供的服务,如文件系统操作、网络通信等,通常需要通过进程间通信机制来实现。
隔离性:进程间通信还有助于保持进程的隔离性,每个进程都有自己的地址空间,通信机制可以在不破坏这种隔离性的情况下实现数据交换。
扩展性:随着系统规模的扩大,进程间通信机制可以帮助系统扩展,允许更多的进程加入到系统中,同时保持有效的通信。
分布式系统:在分布式系统中,进程间通信跨越网络,允许不同计算机上的进程相互通信,实现分布式计算和数据共享。
进程间通信是操作系统设计中的一个核心概念,对于构建可靠、高效和可扩展的系统至关重要。
学习实践过程遇到的问题与解决方式(AI 驱动,优先使用AI工具解决问题)(2分)
-
理解概念的困难:
- 问题:IPC涉及的概念如进程、线程、信号、套接字等可能比较抽象,难以理解。
- 解决办法:通过实际编写代码和运行示例程序来加深理解。使用图解和动画帮助可视化抽象概念。
-
编程错误:
- 问题:在编写IPC程序时,可能会遇到语法错误、逻辑错误或者运行时错误。
- 解决办法:仔细检查代码,使用调试工具,阅读错误信息和日志来定位问题。学习如何有效地使用调试器。
-
竞态条件和同步问题:
- 问题:当多个进程或线程同时访问共享资源时,可能会出现竞态条件。
- 解决办法:使用同步机制,如互斥锁(mutexes)、信号量(semaphores)或条件变量(condition variables)来控制访问。
-
死锁:
- 问题:在尝试同步多个资源时,可能会发生死锁。
- 解决办法:遵循死锁预防策略,如确保获取锁的顺序一致,或者使用超时机制。
-
性能问题:
- 问题:IPC可能会引入性能瓶颈,特别是在高负载情况下。
- 解决办法:优化代码,减少IPC调用的次数,使用更高效的通信机制,如共享内存。
-
安全性问题:
- 问题:IPC可能暴露安全漏洞,特别是当涉及到网络通信时。
- 解决办法:确保使用加密通信,验证数据的完整性,实施适当的访问控制。
-
跨平台兼容性问题:
- 问题:不同的操作系统可能有不同的IPC机制和API。
- 解决办法:使用跨平台的库和框架,或者为不同的平台编写特定的代码。
-
理解文档和API:
- 问题:IPC的文档和API可能复杂难懂。
- 解决办法:通过阅读示例代码和参与社区讨论来提高理解。实践是最好的老师。
-
调试分布式系统:
- 问题:在分布式系统中,调试IPC问题可能特别困难。
- 解决办法:使用专门的工具来监控和记录分布式系统中的通信,以及使用日志来追踪问题。
-
资源泄露:
- 问题:在处理文件描述符或内存时,可能会忘记释放资源。
- 解决办法:确保在代码中正确管理资源,使用RAII(资源获取即初始化)等技术自动管理资源的生命周期。
作业提交要求(1分)
- 提交Markdown 文件,文档命名“学号姓名《密码系统设计》.md”
- 提交Markdown 文件转为 PDF,文档命名“学号姓名《密码系统设计》第 X 周.pdf”
- 提交代码托管链接(可选):学号姓名 gitee(github) 链接
- 内容质量高有加分