type
status
slug
date
summary
tags
category
password
icon
Ch1查漏补缺
extern的用法在rustlings里面用到过,当时是调用的外部RUST,主要用于调用FFI(Foreign Function Interface)
这里可以对比一下我们在C函数里面需要使用链接脚本里面定义的符号是怎么做:
extern int __code_start, __bss_start;
就是这样声明,而这玩意没有值(或者是说它对于它指向的int值没有所有权,只能取地址操作)
其实这里取int也行,取其它的也可以,只是对应指针大小的数据类型即可。
so,这里rust调用c的方法也是如此,对比一下用c实现清空bss段:
记录有意思的细节:
#[link_name = ".."]和#[link(name = "")]的意思是一样的吗?
不完全一样。在Rust中,
#[link_name = ".."]
和#[link(name = "")]
都是链接属性(link attributes),用于指定外部库的名称,但它们的使用场景和含义有所不同。#[link_name = ".."]
用于改变Rust在链接时搜索的符号名。这通常用于链接到C库时,当C库的函数名与Rust的函数名不一致时。例如:
在这个例子中,Rust会在链接时搜索名为
my_c_function
的符号,而不是my_rust_function
。而
#[link(name = "")]
用于指定要链接的外部库的名称。例如:
在这个例子中,Rust会链接到名为
c
的库,然后在该库中搜索printf
函数。所以,虽然这两个属性都与链接外部库有关,但它们的具体用途是不同的。
什么是Log?
我们这里是使用第三方库Log
这里因为log::set_logger这个方法参数签名:logger: &'static dyn Log
想了解dyn这个东西:
dyn
摘录:
为了处理 DST,Rust 提供了
Sized
trait 来决定一个类型的大小是否在编译时可知。这个 trait 自动为编译器在编译时就知道大小的类型实现。另外,Rust 隐式的为每一个泛型函数增加了 Sized
bound。也就是说,对于如下泛型函数定义:
实际上被当作如下处理:
泛型函数默认只能用于在编译时已知大小的类型。然而可以使用如下特殊语法来放宽这个限制:
?Sized
上的 trait bound 意味着 “T
可能是也可能不是 Sized
” 同时这个注解会覆盖泛型类型必须在编译时拥有固定大小的默认规则。这种意义的 ?Trait
语法只能用于 Sized
,而不能用于任何其他 trait。另外注意我们将
t
参数的类型从 T
变为了 &T
:因为其类型可能不是 Sized
的,所以需要将其置于某种指针之后。在这个例子中选择了引用。关于Mutex
作为展示如何使用互斥器的例子,让我们从在单线程上下文使用互斥器开始,如示例 16-12 所示:
文件名:src/main.rs
示例 16-12: 出于简单的考虑,在一个单线程上下文中探索
Mutex<T>
的 API像很多类型一样,我们使用关联函数
new
来创建一个 Mutex<T>
。使用 lock
方法获取锁,以访问互斥器中的数据。这个调用会阻塞当前线程,直到我们拥有锁为止。如果另一个线程拥有锁,并且那个线程 panic 了,则
lock
调用会失败。在这种情况下,没人能够再获取锁,所以这里选择 unwrap
并在遇到这种情况时使线程 panic。一旦获取了锁,就可以将返回值(在这里是
num
)视为一个其内部数据的可变引用了。类型系统确保了我们在使用 m
中的值之前获取锁。m
的类型是 Mutex<i32>
而不是 i32
,所以 必须 获取锁才能使用这个 i32
值。我们是不会忘记这么做的,因为反之类型系统不允许访问内部的 i32
值。正如你所怀疑的,
Mutex<T>
是一个智能指针。更准确的说,lock
调用 返回 一个叫做 MutexGuard
的智能指针。这个智能指针实现了 Deref
来指向其内部数据;其也提供了一个 Drop
实现当 MutexGuard
离开作用域时自动释放锁,这正发生于示例 16-12 内部作用域的结尾。为此,我们不会忘记释放锁并阻塞互斥器为其它线程所用的风险,因为锁的释放是自动发生的。获取了锁之后,可以打印出互斥器的值,并发现能够将其内部的
i32
改为 6。感觉有段优美的代码可以积累起来:
信号量的实现是用的mutex和condvar:(主要是上面的map闭包使用返回值collect然后给到threads的用法很简洁,可读性也不差,感受到了rust的魅力)
关于expect和unwrap
还有另一个类似于
unwrap
的方法它还允许我们选择 panic!
的错误信息:expect
。使用 expect
而不是 unwrap
并提供一个好的错误信息可以表明你的意图并更易于追踪 panic 的根源。expect
的语法看起来像这样:文件名:src/main.rs
expect
与 unwrap
的使用方式一样:返回文件句柄或调用 panic!
宏。expect
在调用 panic!
时使用的错误信息将是我们传递给 expect
的参数,而不像 unwrap
那样使用默认的 panic!
信息。它看起来像这样:Rust的属性
句法
InnerAttribute :
#
!
[
Attr ]
OuterAttribute :
#
[
Attr ]
Attr :
SimplePath AttrInput?
AttrInput :
|
=
LiteralExpression不带后缀*内部属性(Inner attributes)*以
#!
开头的方式编写,应用于它在其中声明的程序项。*外部属性(Outer attributes)*以不后跟感叹号的(!
)的 #
开头的方式编写,应用于属性后面的内容。属性的一些例子:
-> !和()无返回值的区别
在 Rust 中,
-> !
表示一个函数永远不会返回。这被称为 "发散函数"(diverging function)。这种类型的函数通常会进入无限循环,或者 panic,或者调用其他发散函数。在你的代码中,
panic
函数就是一个发散函数。它进入了一个无限循环,所以它永远不会返回。如果一个函数没有明确的返回类型(即没有
->
后面的部分),那么它的返回类型默认为 ()
,这是一个叫做 "unit" 的特殊类型,类似于其他语言中的 void
。这种类型的函数在完成其工作后会返回,返回值是一个空元组 ()
。所以,
-> !
和没有返回值(默认为 -> ()
)在语义上是有区别的:前者表示函数永远不会返回,后者表示函数会返回,但没有有意义的返回值。Cell和RefCell
Rust 提供了
Cell
和 RefCell
用于内部可变性,简而言之,可以在拥有不可变引用的同时修改目标数据,对于正常的代码实现来说,这个是不可能做到的(要么一个可变借用,要么多个不可变借用)。全局变量
- 作者:liamY
- 链接:https://liamy.clovy.top/article/OS_Tutorial/rust_improve
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。