-
Notifications
You must be signed in to change notification settings - Fork 453
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
--- | ||
|
||
title: rust体会 | ||
date: 2024-11-11 | ||
categories: | ||
- rust language | ||
tags: | ||
- author:ekkure | ||
- repo:https://github.com/ekkure/blog | ||
--- | ||
### Rust编程技巧与示例:宏、算法与类型转换 | ||
|
||
在Rust编程中,有许多细节和技巧可以帮助开发者更好地组织代码、优化算法性能,以及确保类型安全。本篇博客汇总了一些Rust编程的核心要点和实用代码示例,涵盖了宏的使用、排序算法、树和图的操作等内容。 | ||
|
||
--- | ||
|
||
### 1. 宏与#[macro_export]、#[macro_use] | ||
|
||
Rust中的宏非常强大,用于生成重复代码和提升代码的灵活性。使用`#[macro_export]`可以导出宏,使其在其他模块或包中可用;而`#[macro_use]`则在现代Rust中被推荐通过`use`语句显式引入。 | ||
|
||
示例宏定义: | ||
```rust | ||
#[rustfmt::skip] | ||
macro_rules! my_macro { | ||
() => { println!("Check out my macro!"); }; | ||
($val:expr) => { println!("Look at this other macro: {}", $val); }; | ||
} | ||
``` | ||
|
||
这里的`#[rustfmt::skip]`用于避免自动格式化,保持代码样式的灵活性和可读性。 | ||
|
||
--- | ||
|
||
### 2. Rust中的类型与特性 | ||
|
||
在实现数据结构或算法时,我们通常需要对泛型类型T施加一些特性约束,例如: | ||
- `Ord`:使得元素可以比较大小,适用于排序、合并等操作。 | ||
- `Clone`:便于复制元素值,即使是复杂类型,也可以无所有权转移地复制。 | ||
- `Display`:实现字符串友好的格式化输出,便于打印和日志记录。 | ||
|
||
这些特性可以通过`where`语句在泛型实现中指定: | ||
```rust | ||
impl<T> LinkedList<T> | ||
where T: Ord + Clone + Display | ||
``` | ||
|
||
--- | ||
|
||
### 3. 内存操作与指针 | ||
|
||
Rust通过`unsafe`块支持手动管理内存和指针操作,用于高性能或底层操作。 | ||
例如,获取节点的指针并解引用: | ||
```rust | ||
let node_ptr = Some(unsafe { NonNull::new_unchecked(Box::into_raw(node)) }); | ||
res.add((*node_ptr.as_ptr()).val.clone()); | ||
cur_a = (*node_ptr.as_ptr()).next; // 注意这里直接获取的是ta的next指针 | ||
``` | ||
|
||
指针的安全解包和操作要格外小心,可以使用`Option`配合`unsafe`避免空指针风险。 | ||
|
||
--- | ||
|
||
### 4. 算法设计示例 | ||
|
||
#### 4.1 链表与树的操作 | ||
|
||
##### 插入与查找 | ||
在链表或树结构中,我们经常用到`Option`类型来表示节点的存在与否。例如,在插入和查找二叉树中,可以选择使用`if let`语句来处理`Some`和`None`的情况: | ||
```rust | ||
fn insert(&mut self, value: T) { | ||
if let Some(ref mut node) = self.root { | ||
node.insert(value); | ||
} else { | ||
self.root = Some(Box::new(TreeNode::new(value))); | ||
} | ||
} | ||
``` | ||
这种写法在处理可变引用时尤其简洁。 | ||
|
||
#### 4.2 排序算法与Ord与PartialOrd | ||
|
||
选择排序等算法需要比较泛型元素的大小,通常需要`PartialOrd`特性来支持部分排序(如非全序关系的情况),而对于要求全序的场景可以使用`Ord`。 | ||
|
||
#### 4.3 深度优先与广度优先搜索 | ||
|
||
在图算法中,深度优先搜索(DFS)和广度优先搜索(BFS)是两种基础的遍历方式: | ||
- DFS示例: | ||
```rust | ||
fn dfs_util(&self, v: usize, visited: &mut HashSet<usize>, visit_order: &mut Vec<usize>) { | ||
visited.insert(v); | ||
visit_order.push(v); | ||
for &nei in self.adj[v].iter() { | ||
if !visited.contains(&nei) { | ||
self.dfs_util(nei, visited, visit_order); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
- BFS示例: | ||
```rust | ||
fn bfs_with_return(&self, start: usize) -> Vec<usize> { | ||
let mut visit_order = vec![]; | ||
let mut visited = vec![false; self.adj.len()]; | ||
let mut queue = VecDeque::new(); | ||
queue.push_back(start); | ||
visited[start] = true; | ||
|
||
while let Some(node) = queue.pop_front() { | ||
visit_order.push(node); | ||
for &neighbor in &self.adj[node] { | ||
if !visited[neighbor] { | ||
visited[neighbor] = true; | ||
queue.push_back(neighbor); | ||
} | ||
} | ||
} | ||
visit_order | ||
} | ||
``` | ||
|
||
#### 4.4 平衡堆的插入与调整 | ||
|
||
Rust标准库中`Vec`的`swap_remove`方法可以高效地删除指定位置的元素,适用于实现优先队列等堆结构: | ||
```rust | ||
let result = self.items.swap_remove(1); // 移除并返回指定位置的元素 | ||
``` | ||
|
||
在删除元素后,可以通过调整堆结构(如最小/最大堆)来保持堆的性质。 | ||
|
||
--- | ||
|
||
### 5. 实现栈与队列 | ||
|
||
使用双队列实现栈的操作逻辑: | ||
```rust | ||
pub struct myStack<T> { | ||
q1: Queue<T>, | ||
q2: Queue<T> | ||
} | ||
|
||
impl<T> myStack<T> { | ||
pub fn push(&mut self, elem: T) { | ||
self.q2.enqueue(elem); | ||
while !self.q1.is_empty() { | ||
self.q2.enqueue(self.q1.dequeue().unwrap()); | ||
} | ||
std::mem::swap(&mut self.q1, &mut self.q2); | ||
} | ||
} | ||
``` | ||
|
||
这种方法利用队列的FIFO特性来模拟栈的LIFO特性。 | ||
|
||
--- | ||
|
||
### 6. 函数与内存管理 | ||
|
||
Rust中的`Box`和`unsafe`结合用于手动管理堆内存。`Box::from_raw`可以从裸指针重新创建`Box`,这在需要手动内存管理的场景中非常有用。 | ||
```rust | ||
unsafe fn raw_pointer_to_box(ptr: *mut Foo) -> Box<Foo> { | ||
let mut ret: Box<Foo> = unsafe { Box::from_raw(ptr) }; | ||
ret.b = Some(String::from("hello")); | ||
ret | ||
} | ||
``` | ||
|
||
这种方法常用于FFI(外部函数接口)中将指针恢复为拥有所有权的Rust类型。 | ||
|
||
--- | ||
|
||
### 总结 | ||
|
||
Rust语言通过丰富的内存管理工具和类型系统,确保了在安全性和性能上的平衡。无论是自定义数据结构还是排序、图遍历等基础算法,Rust的特性可以为代码提供极大的灵活性和安全保障。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
--- | ||
|
||
title: 调度与死锁 | ||
date: 2024-11-11 | ||
categories: | ||
- os | ||
tags: | ||
- author:ekkure | ||
- repo:https://github.com/ekkure/blog | ||
|
||
--- | ||
## 调度 | ||
|
||
#### **三级调度:** | ||
|
||
作业调度、高级调度(频次最低):主要解决:接纳多少个任务+接纳那哪些任务这两个工作 | ||
|
||
进程调度、低级调度(频次最高): 必须有、**核心**,**确定哪个进程可以占有CPU并执行** | ||
|
||
中级调度:将那些暂时不能运行的进程从内存挂起到外存,(阻塞状态下进程实体(程序 + 数据 + PCB)还在内存中,而挂起状态会把进程实体挂到外存,但是PCB会存在系统内核空间中,会记录进程在外存的状态以及位置),一般在**内存紧张**时使用 | ||
|
||
|
||
|
||
高级调度,用于批处理系统中,将任务从外存调度到内存中去。(在分时/实时系统中,任务是直接在内存,因此没有高级调度) | ||
|
||
分时系统:**只有进程调度** | ||
|
||
批处理系统:**进程调度 + 作业调度** | ||
|
||
|
||
|
||
#### 调度算法相关 | ||
|
||
准则:周转时间(常用于**批处理系统**)、平均周转时间、带权周转时间 | ||
|
||
响应时间(交互性作业、分时系统)、截止时间的保证(实时系统)、优先权准则 | ||
|
||
周转时间 = 完成时间 - 到达时间 | ||
|
||
带权周转时间 = 周转时间 / 服务时间 | ||
|
||
|
||
**调度算法** | ||
|
||
- FCFS(first come first serve), SJ(P)F等等 | ||
对于抢占式调度,注意**服务时间的更新,然后再比较,看谁抢** | ||
|
||
- 高优先权 优先调度算法 | ||
|
||
静态优先权:简单,但存在饥饿现象 | ||
|
||
动态优先权:eg Rp = (等待时间 + 服务时间)/ 服务时间 作为优先权 1 + tw / ts; | ||
|
||
- 时间片轮转 ......? | ||
|
||
多级反馈队列 S1 < S2 < S3 优先权 S1 > S2 > S3 | ||
|
||
|
||
|
||
- 实时调度 | ||
|
||
非抢占:轮转 || 优先权 | ||
|
||
抢占:基于中断时钟,好处是减少了上下文保存切换的次数 | ||
|
||
立即抢占 | ||
|
||
实时调度算法:EDF、LLF,还有例题 | ||
|
||
- 其他一些?? | ||
|
||
MPS:CPU共享内存, 共享缓存(单个儿独立的,容易出现绑定,忙闲不均) | ||
|
||
SMP中进程分配方式:静态分配和动态分配 | ||
|
||
调度方式: 自调度和成组调度(两种方式就对应了用户级线程和系统级线程), 专用处理机分配? | ||
|
||
|
||
## 死锁 | ||
|
||
**一些定义**: | ||
|
||
- 可剥夺资源:如主存,CPU,可以在使用时被强占的资源 | ||
- 不可剥夺资源:不可被打断抢占的资源,如驱动器,打印机 | ||
- 永久资源(外存),临时资源(进程运行过程中临时产生的数据资源等等) | ||
|
||
**竞争非剥夺资源,或者竞争临时资源可导致死锁** | ||
|
||
### 死锁的必要条件 | ||
|
||
- 互斥条件:进程互斥的使用临界资源 | ||
- 不剥夺条件(不可抢占) | ||
- 请求-保持条件:进程在申请新的资源的同时,保持对某些资源的占有 | ||
- 环路等待:循环等待链 | ||
|
||
|
||
|
||
|
||
|
||
### 解决死锁的方法 | ||
|
||
从严格依次降低,为 | ||
|
||
预防 -> 避免 -> 检测与解除 | ||
|
||
#### 预防 | ||
|
||
上面4个条件是死锁的必要条件 , Deadlock -> 4 其逆否命题为 !4 -> !Deadlock,所以我们从4个条件入手 | ||
|
||
1. 互斥,并没有好的办法 | ||
2. 不抢占:不抢占变成"抢占",如果进程申请不到全部资源时,主动释放 | ||
3. 请求保持条件:使用AND机制,但是有点浪费资源 | ||
4. 环路等待:破除环路,资源排序,参考哲学家进餐 | ||
|
||
#### 避免死锁 | ||
|
||
**这是比较中庸的做法,既不损耗很多的效率,也比较的严格** | ||
|
||
##### 银行家算法 | ||
|
||
一种是,资源分配表,为 | ||
|
||
| Process | Allocation | Need | Available | | ||
| ------- | ---------- | ---- | --------- | | ||
| | | | | | ||
|
||
另一种是,计算表 | ||
|
||
| Work | Need | Allocation | work + Allocation | Finish | | ||
| ---- | ---- | ---------- | ----------------- | ------ | | ||
| | | | | | | ||
|
||
**对资源进行分配时,分成两步** | ||
|
||
1. 判断分配请求 R是否满足 R < Available && R < Need | ||
2. 如果满足1,使用表1表示分配后的资源表T1,再次计算是否存在安全序列,如果不安全,退回至T0,否则保存T1,下次分配将从T1开始。 | ||
|
||
#### 检测和解除 | ||
|
||
使用方法:**资源分配图** | ||
|
||
**几个结论** | ||
|
||
- 不可完全简化 => 存在死锁 | ||
- 分配图中无环 => 不会存在死锁 | ||
- 分配图中有环 => 不一定死锁 | ||
|
||
简化方法,对一个资源分配图,首先考虑持有边,如果持有者线程能够完成(获得所有需要的资源),将持有边消去后,将资源返回,如果不能完成,边消去后,仍保持资源占有,直到完成。 | ||
|
||
然后考虑请求边,如果请求的资源有空闲的,可以把边消去,若请求线程能够完成,则可将该资源返回,否则保持占有 | ||
|
||
重复上述过程,直至卡住,或者全部成孤立。 | ||
|
||
**解除** | ||
|
||
通过撤销进程或者挂起进程来释放一些资源,进而推动僵持状态。 | ||
|
||
而具体的对哪些进程,以什么样的顺序进行操作,可以参考`Dijkstra`之类的算法,找到一种损耗最小、利益最大的方法。 |