Path: blob/main/documentation/content/zh-cn/books/arch-handbook/locking/_index.adoc
18099 views
---
title: 第 2 章 内核中的锁
prev: books/arch-handbook/boot
next: books/arch-handbook/kobj
showBookMenu: true
weight: 3
params:
path: "/books/arch-handbook/locking/"
---
[[locking]]
= 内核中的锁
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:sectnumlevels: 6
:sectnumoffset: 2
:partnums:
:source-highlighter: rouge
:experimental:
:images-path: books/arch-handbook/
ifdef::env-beastie[]
ifdef::backend-html5[]
:imagesdir: ../../../../images/{images-path}
endif::[]
ifndef::book[]
include::shared/authors.adoc[]
include::shared/mirrors.adoc[]
include::shared/releases.adoc[]
include::shared/attributes/attributes-{{% lang %}}.adoc[]
include::shared/{{% lang %}}/teams.adoc[]
include::shared/{{% lang %}}/mailing-lists.adoc[]
include::shared/{{% lang %}}/urls.adoc[]
toc::[]
endif::[]
ifdef::backend-pdf,backend-epub3[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]
endif::[]
ifndef::env-beastie[]
toc::[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]
__这一章由 FreeBSD SMP Next Generation Project 维护。 请将评论和建议发送给link:{freebsd-smp}_._
这篇文档提纲挈领的讲述了在FreeBSD内核中的锁,这些锁使得有效的多处理成为可能。 锁可以用几种方式获得。数据结构可以用mutex或man:lockmgr[9]保护。 对于为数不多的若干个变量,假如总是使用原子操作访问它们,这些变量就可以得到保护。
[TIP]
.译者注
====
仅读本章内容,还不足以找出"mutex" 和"共享互斥锁"的区别。似乎它们的功能有重叠之处, 前者比后者的功能选项更多。它们似乎都是man:lockmgr[9]的子集。
====
[[locking-mutexes]]
== Mutex
Mutex就是一种用来解决共享/排它矛盾的锁。 一个mutex在一个时刻只可以被一个实体拥有。如果另一个实体要获得已经被拥有的mutex, 就会进入等待,直到这个mutex被释放。在FreeBSD内核中,mutex被进程所拥有。
Mutex可以被递归的索要,但是mutex一般只被一个实体拥有较短的一段时间, 因此一个实体不能在持有mutex时睡眠。如果你需要在持有mutex时睡眠, 可使用一个 man:lockmgr[9] 的锁。
每个mutex有几个令人感兴趣的属性:
变量名::
在内核源代码中struct mtx变量的名字
逻辑名::
由函数``mtx_init``指派的mutex的名字。 这个名字显示在KTR跟踪消息和witness出错与警告信息里。 这个名字还用于区分标识在witness代码中的各个mutex
类型::
Mutex的类型,用标志MTX_表示。 每个标志的意义在man:mutex[9]有所描述。
MTX_DEF:::
一个睡眠mutex
MTX_SPIN:::
一个循环mutex
MTX_RECURSE:::
这个mutex允许递归
保护对象::
这个入口所要保护的数据结构列表或数据结构成员列表。 对于数据结构成员,将按照 ``结构名``.``成员名``的形式命名。
依赖函数::
仅当mutex被持有时才可以被调用的函数
.Mutex列表
[cols="1,1,1,1,1", frame="all", options="header"]
|===
| 变量名
| 逻辑名
| 类型
| 保护对象
| 依赖函数
|sched_lock
|"sched lock"(调度器锁)
|MTX_SPIN \| MTX_RECURSE
|`_gmonparam`, `cnt.v_swtch`, `cp_time`, `curpriority`, `mtx`.`mtx_blocked`, `mtx`.`mtx_contested`, `proc`.`p_procq`, `proc`.`p_slpq`, `proc`.`p_sflag`, `proc`.`p_stat`, `proc`.`p_estcpu`, `proc`.`p_cpticks proc`.`p_pctcpu`, `proc`.`p_wchan`, `proc`.`p_wmesg`, `proc`.`p_swtime`, `proc`.`p_slptime`, `proc`.`p_runtime`, `proc`.`p_uu`, `proc`.`p_su`, `proc`.`p_iu`, `proc`.`p_uticks`, `proc`.`p_sticks`, `proc`.`p_iticks`, `proc`.`p_oncpu`, `proc`.`p_lastcpu`, `proc`.`p_rqindex`, `proc`.`p_heldmtx`, `proc`.`p_blocked`, `proc`.`p_mtxname`, `proc`.`p_contested`, `proc`.`p_priority`, `proc`.`p_usrpri`, `proc`.`p_nativepri`, `proc`.`p_nice`, `proc`.`p_rtprio`, `pscnt`, `slpque`, `itqueuebits`, `itqueues`, `rtqueuebits`, `rtqueues`, `queuebits`, `queues`, `idqueuebits`, `idqueues`, `switchtime`, `switchticks`
|`setrunqueue`, `remrunqueue`, `mi_switch`, `chooseproc`, `schedclock`, `resetpriority`, `updatepri`, `maybe_resched`, `cpu_switch`, `cpu_throw`, `need_resched`, `resched_wanted`, `clear_resched`, `aston`, `astoff`, `astpending`, `calcru`, `proc_compare`
|vm86pcb_lock
|"vm86pcb lock"(虚拟8086模式进程控制块锁)
|MTX_DEF
|`vm86pcb`
|`vm86_bioscall`
|Giant
|"Giant"(巨锁)
|MTX_DEF \| MTX_RECURSE
|几乎可以是任何东西
|许多
|callout_lock
|"callout lock"(延时调用锁)
|MTX_SPIN \| MTX_RECURSE
|`callfree`, `callwheel`, `nextsoftcheck`, `proc`.`p_itcallout`, `proc`.`p_slpcallout`, `softticks`, `ticks`
|
|===
[[locking-sx]]
== 共享互斥锁
这些锁提供基本的读/写类型的功能,可以被一个正在睡眠的进程持有。 现在它们被统一到man:lockmgr[9]之中。
.共享互斥锁列表
[cols="1,1", options="header"]
|===
| 变量名
| 保护对象
|`allproc_lock`
|``allproc zombproc pidhashtbl proc``.``p_list proc``.``p_hash nextpid``
|`proctree_lock`
|``proc``.``p_children proc``.``p_sibling``
|===
[[locking-atomic]]
== 原子保护变量
原子保护变量并非由一个显在的锁保护的特殊变量,而是: 对这些变量的所有数据访问都要使用特殊的原子操作(man:atomic[9])。 尽管其它的基本同步机制(例如mutex)就是用原子保护变量实现的, 但是很少有变量直接使用这种处理方式。
* ``mtx``.``mtx_lock``