当前位置: 首页 > news >正文

网站做关键词链接有用吗做个网站的费用

网站做关键词链接有用吗,做个网站的费用,wordpress升级说版本低,桂林两江四湖附近酒店10min速通FSCK、原子操作与VFS 文件系统检查器1.检查inode表1) 遍历所有inode2) 修复多次引用数据块 2.检查目录结构3.检查目录的连接1) 检查根目录确保存在2) 遍历所有目录的inode,有问题的连接到/lostfound 4.检查引用次数5.检查位图一致性 日志1.主要的数据结构1) 原子操作描… 10min速通FSCK、原子操作与VFS 文件系统检查器1.检查inode表1) 遍历所有inode2) 修复多次引用数据块 2.检查目录结构3.检查目录的连接1) 检查根目录确保存在2) 遍历所有目录的inode,有问题的连接到/lostfound 4.检查引用次数5.检查位图一致性 日志1.主要的数据结构1) 原子操作描述符2) 事务结构3) 日志结构 2.原子操作的生成1) 获取原子操作描述符2) 将元数据缓冲区纳入管理3) 获取原数据缓冲区的更新4) 将更新操作加入当前原子操作描述符中 3.事务提交4.崩溃的恢复 虚拟文件系统简介 写了三天理解了FSCK的底层原理原子操作和VFS所以就把笔记发了出来。 在不少的情况下由于计算机软硬件或人为原因断电、崩溃crash如果此时系统正在更新硬盘数据则可能出现数据一致性问题——崩溃一致性问题crash-consistency problem 图1 数据块 索引点 位图关系 #mermaid-svg-elJXUriTZKMJxocf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-elJXUriTZKMJxocf .error-icon{fill:#552222;}#mermaid-svg-elJXUriTZKMJxocf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-elJXUriTZKMJxocf .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-elJXUriTZKMJxocf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-elJXUriTZKMJxocf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-elJXUriTZKMJxocf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-elJXUriTZKMJxocf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-elJXUriTZKMJxocf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-elJXUriTZKMJxocf .marker.cross{stroke:#333333;}#mermaid-svg-elJXUriTZKMJxocf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-elJXUriTZKMJxocf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-elJXUriTZKMJxocf .cluster-label text{fill:#333;}#mermaid-svg-elJXUriTZKMJxocf .cluster-label span{color:#333;}#mermaid-svg-elJXUriTZKMJxocf .label text,#mermaid-svg-elJXUriTZKMJxocf span{fill:#333;color:#333;}#mermaid-svg-elJXUriTZKMJxocf .node rect,#mermaid-svg-elJXUriTZKMJxocf .node circle,#mermaid-svg-elJXUriTZKMJxocf .node ellipse,#mermaid-svg-elJXUriTZKMJxocf .node polygon,#mermaid-svg-elJXUriTZKMJxocf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-elJXUriTZKMJxocf .node .label{text-align:center;}#mermaid-svg-elJXUriTZKMJxocf .node.clickable{cursor:pointer;}#mermaid-svg-elJXUriTZKMJxocf .arrowheadPath{fill:#333333;}#mermaid-svg-elJXUriTZKMJxocf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-elJXUriTZKMJxocf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-elJXUriTZKMJxocf .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-elJXUriTZKMJxocf .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-elJXUriTZKMJxocf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-elJXUriTZKMJxocf .cluster text{fill:#333;}#mermaid-svg-elJXUriTZKMJxocf .cluster span{color:#333;}#mermaid-svg-elJXUriTZKMJxocf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-elJXUriTZKMJxocf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 节点更新 元数据状态不一致 位图尚未更新 然而磁盘在同一时间只能进行一次I/O操作硬件层面无法实现所以文件系统需要在软件层面原子性的从一个状态更新到一个新的状态。 本节将介绍两种解决方案文件系统检查器和日志。 文件系统检查器 F i l e S y s t e m C h e c k e r F S C K File System CheckerFSCK FileSystemCheckerFSCK 文件系统检查器File System CheckerFSCK是解决崩溃一致性问题的一种简单方案。 主要用于解决由于各种原因导致的文件系统不一致性问题例如系统崩溃、断电、文件系统损坏等。 在处理崩溃一致性问题时FSCK提供了一种简单而有效的方法来检查和修复文件系统。当文件系统遭受损坏或出现不一致性时FSCK可以扫描整个文件系统并检测到潜在的错误。一旦检测到错误FSCK会尝试自动修复它们以便文件系统恢复到一致状态。 使用FSCK可以确保文件系统的完整性从而避免数据丢失或文件损坏。它通常在操作系统启动时自动运行或者可以手动启动以检查特定的文件系统。 在openEuler中这个工具被称为 e2fsck(以下简称FSCK) 可以用来检测Ext2/3/4文件系统。 e 2 f s c k e2fsck e2fsck 1.检查inode表 1) 遍历所有inode 这是检查inode表的第一步。inode是文件系统中的一个重要数据结构用于存储文件或目录的元数据。遍历所有inode是为了检查它们的状态和完整性。 检查inode类型字段i_mode是否合法检查inode记录的文件大小i_size_lo 与 i_size_high检查数据块是否被另一个inode重复引用 2) 修复多次引用数据块 如果一个数据块被多个inode引用这可能会导致数据不一致或损坏。修复这种情况可以确保数据的一致性和完整性。 再次扫描所有inode指向的数据块遍历文件系统树结构对文件系统进行修复 2.检查目录结构 目录是文件系统中组织文件和子目录的方式。检查目录结构可以发现并修复任何目录相关的问题例如丢失或重复的目录项。 rec_len 的值至少为8B并且不能大于该目录所在数据块中剩余空间大小name_len 值小于rec_len-8inode编号指定正在使用目录第一项为.(当前目录)目录第二项为..父目录收集每个目录的inode编号 3.检查目录的连接 这涉及到检查目录项之间的连接关系确保它们正确地链接在一起没有断裂或循环引用。 1) 检查根目录确保存在 2) 遍历所有目录的inode,有问题的连接到/lostfound 4.检查引用次数 在文件系统中某些数据结构或数据块可能被多个地方引用。检查引用次数可以确保这些数据结构或数据块被正确地使用和释放避免内存泄漏或其他问题。 多数inode为未分配引用次数为0 已分配引用次数为1 文件目录多链接引用次数大于1 5.检查位图一致性 位图是文件系统中用于跟踪空闲空间的数据结构。检查位图一致性可以确保文件系统能够正确地分配和回收空间。 非常耗时特别是在检索文件系统中的所有索引节点 E x t 4 Ext4 Ext4Ext4 对未分配的 inode 做了标记使 FSCK在检查磁盘时将其整块的忽略掉大大缩短磁盘检测时间 日志 j o u r n a l i n g \textcolor{#4183c4}{journaling} journaling 日志journaling机制是现代文件系统如Linux Ext3/Ext4、Windows NTFS解决崩溃一致性问题的主流解决方案借鉴于数据库系统的设计思想日志系统将将文件系统的更新组织为事务transaction使得文件系统的状态为完成或未完成日志机制将文件系统的状态划分为三种状态 1.日志的写入2.事务的提交3.检查点的添加 #mermaid-svg-qe4O4uWPNHk8LaLz {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-qe4O4uWPNHk8LaLz .error-icon{fill:#552222;}#mermaid-svg-qe4O4uWPNHk8LaLz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qe4O4uWPNHk8LaLz .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-qe4O4uWPNHk8LaLz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qe4O4uWPNHk8LaLz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qe4O4uWPNHk8LaLz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qe4O4uWPNHk8LaLz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qe4O4uWPNHk8LaLz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qe4O4uWPNHk8LaLz .marker.cross{stroke:#333333;}#mermaid-svg-qe4O4uWPNHk8LaLz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qe4O4uWPNHk8LaLz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qe4O4uWPNHk8LaLz .cluster-label text{fill:#333;}#mermaid-svg-qe4O4uWPNHk8LaLz .cluster-label span{color:#333;}#mermaid-svg-qe4O4uWPNHk8LaLz .label text,#mermaid-svg-qe4O4uWPNHk8LaLz span{fill:#333;color:#333;}#mermaid-svg-qe4O4uWPNHk8LaLz .node rect,#mermaid-svg-qe4O4uWPNHk8LaLz .node circle,#mermaid-svg-qe4O4uWPNHk8LaLz .node ellipse,#mermaid-svg-qe4O4uWPNHk8LaLz .node polygon,#mermaid-svg-qe4O4uWPNHk8LaLz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qe4O4uWPNHk8LaLz .node .label{text-align:center;}#mermaid-svg-qe4O4uWPNHk8LaLz .node.clickable{cursor:pointer;}#mermaid-svg-qe4O4uWPNHk8LaLz .arrowheadPath{fill:#333333;}#mermaid-svg-qe4O4uWPNHk8LaLz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qe4O4uWPNHk8LaLz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qe4O4uWPNHk8LaLz .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-qe4O4uWPNHk8LaLz .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-qe4O4uWPNHk8LaLz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qe4O4uWPNHk8LaLz .cluster text{fill:#333;}#mermaid-svg-qe4O4uWPNHk8LaLz .cluster span{color:#333;}#mermaid-svg-qe4O4uWPNHk8LaLz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qe4O4uWPNHk8LaLz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 日志的写入 事务的提交 检查点的添加 日志的写入 在日志机制中每次对文件系统的修改都会首先被写入到一个专门的日志文件中。这个日志文件记录了所有的更改操作包括数据的读、写、删除等。即对元数据索引节点、位图等和数据块做待做更新以日志形式写入磁盘。 实质上日志是一个无名字的文件对应inode号为8这种写入操作确保了即使在系统突然崩溃的情况下文件系统也可以通过这个日志来恢复到一致的状态。因为即使某些修改尚未完全应用到实际的文件系统中它们在日志中仍然被记录下来从而可以在恢复过程中重新应用。 事务的提交 t r a n s a c t i o n \textcolor{#4183c4}{transaction} transaction 在数据库管理中一个事务是一系列的操作这些操作要么全部成功要么全部失败以确保数据的一致性。在文件系统中日志机制同样支持 事务transaction的概念。当一系列的修改操作被写入日志后它们被组织成一个事务。只有当这个事务的所有修改都被成功记录到日志中时才会被称为事务已提交committed意味着这些修改现在可以被应用到实际的文件系统中。如果在事务提交之前系统崩溃由于这些更改已经被记录在日志中文件系统可以在重启后重新应用这些更改确保数据的一致性。硬件扇区只保证单位512B写入为原子的为了保证原子性所以每一个事务结束标志的大小应小于512B。 检查点的添加 c h e c k p o i n t \textcolor{#4183c4}{check point} checkpoint 检查点check point是在文件系统中的某一特定时间点所有的事务都已经被提交的状态。在日志机制中检查点起到了一个重要的作用因为它标记了一个时间点从那时起即使发生崩溃文件系统也可以从这个检查点开始恢复而不是从头开始。当系统运行时会定期添加检查点。这意味着如果系统在检查点之后崩溃重启后恢复过程可以从这个检查点开始而不是从头开始。这大大减少了恢复时间。 通过这三种状态的管理和操作日志机制为现代文件系统提供了强大的崩溃一致性保护确保了数据的完整性和可靠性。 j b d 2 J o u r n a l i n g B l o c k D r i v e r \textcolor{#4183c4}{jbd2Journaling Block Driver} jbd2JournalingBlockDriver 在Ext4文件系统中日志机制在 jbd2Journaling Block Driver 模块中实现该模块用于管理缓冲区。 Ext4 文件数据系统 #mermaid-svg-CjrXufXTy5uhtsAN {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-CjrXufXTy5uhtsAN .error-icon{fill:#552222;}#mermaid-svg-CjrXufXTy5uhtsAN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CjrXufXTy5uhtsAN .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-CjrXufXTy5uhtsAN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CjrXufXTy5uhtsAN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CjrXufXTy5uhtsAN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CjrXufXTy5uhtsAN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CjrXufXTy5uhtsAN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CjrXufXTy5uhtsAN .marker.cross{stroke:#333333;}#mermaid-svg-CjrXufXTy5uhtsAN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CjrXufXTy5uhtsAN defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-CjrXufXTy5uhtsAN g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-CjrXufXTy5uhtsAN g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-CjrXufXTy5uhtsAN g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-CjrXufXTy5uhtsAN g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-CjrXufXTy5uhtsAN g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-CjrXufXTy5uhtsAN .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-CjrXufXTy5uhtsAN .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-CjrXufXTy5uhtsAN .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-CjrXufXTy5uhtsAN .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-CjrXufXTy5uhtsAN .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-CjrXufXTy5uhtsAN .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-CjrXufXTy5uhtsAN .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-CjrXufXTy5uhtsAN .edgeLabel .label text{fill:#333;}#mermaid-svg-CjrXufXTy5uhtsAN .label div .edgeLabel{color:#333;}#mermaid-svg-CjrXufXTy5uhtsAN .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-CjrXufXTy5uhtsAN .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-CjrXufXTy5uhtsAN .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-CjrXufXTy5uhtsAN .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-CjrXufXTy5uhtsAN .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-CjrXufXTy5uhtsAN .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CjrXufXTy5uhtsAN .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CjrXufXTy5uhtsAN #statediagram-barbEnd{fill:#333333;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CjrXufXTy5uhtsAN .cluster-label,#mermaid-svg-CjrXufXTy5uhtsAN .nodeLabel{color:#131300;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-CjrXufXTy5uhtsAN .note-edge{stroke-dasharray:5;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-note text{fill:black;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram-note .nodeLabel{color:black;}#mermaid-svg-CjrXufXTy5uhtsAN .statediagram .edgeLabel{color:red;}#mermaid-svg-CjrXufXTy5uhtsAN #dependencyStart,#mermaid-svg-CjrXufXTy5uhtsAN #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-CjrXufXTy5uhtsAN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 块缓冲区 数据或恢复时写入 缓冲被管理 数据记录 正常读写 正常读 内核 元数据缓冲 jbd2 数据缓冲 日志区 磁盘 引入jbd2之后文件系统中的数据在内核、块缓冲区buffer cache、磁盘之间的流动如上Mermaid状态图所示。将内核对 缓冲buffer 的更新记录到磁盘中的日志空间中 #mermaid-svg-2hhfw79zNxY0nmer {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-2hhfw79zNxY0nmer .error-icon{fill:#552222;}#mermaid-svg-2hhfw79zNxY0nmer .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2hhfw79zNxY0nmer .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-2hhfw79zNxY0nmer .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2hhfw79zNxY0nmer .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2hhfw79zNxY0nmer .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2hhfw79zNxY0nmer .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2hhfw79zNxY0nmer .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2hhfw79zNxY0nmer .marker.cross{stroke:#333333;}#mermaid-svg-2hhfw79zNxY0nmer svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2hhfw79zNxY0nmer .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2hhfw79zNxY0nmer .cluster-label text{fill:#333;}#mermaid-svg-2hhfw79zNxY0nmer .cluster-label span{color:#333;}#mermaid-svg-2hhfw79zNxY0nmer .label text,#mermaid-svg-2hhfw79zNxY0nmer span{fill:#333;color:#333;}#mermaid-svg-2hhfw79zNxY0nmer .node rect,#mermaid-svg-2hhfw79zNxY0nmer .node circle,#mermaid-svg-2hhfw79zNxY0nmer .node ellipse,#mermaid-svg-2hhfw79zNxY0nmer .node polygon,#mermaid-svg-2hhfw79zNxY0nmer .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2hhfw79zNxY0nmer .node .label{text-align:center;}#mermaid-svg-2hhfw79zNxY0nmer .node.clickable{cursor:pointer;}#mermaid-svg-2hhfw79zNxY0nmer .arrowheadPath{fill:#333333;}#mermaid-svg-2hhfw79zNxY0nmer .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2hhfw79zNxY0nmer .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2hhfw79zNxY0nmer .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-2hhfw79zNxY0nmer .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-2hhfw79zNxY0nmer .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2hhfw79zNxY0nmer .cluster text{fill:#333;}#mermaid-svg-2hhfw79zNxY0nmer .cluster span{color:#333;}#mermaid-svg-2hhfw79zNxY0nmer div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2hhfw79zNxY0nmer :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数据记录 jbd2 管理缓冲区 块缓冲区 jbd2在管理过程中Ext4系统将日志系统分为三类Journal、Ordered、Writeback三种模式。 journal模式用户数据、元数据可靠、两次写入、较慢Ordered模式元数据更新写入顺序(先写磁盘再写日志、高性能)Writeback模式记录元数据更新不保证顺序(可靠性最低、性能最高) 模式选择上Ordered模式在性能和可靠性上取得了较好的平衡所以Ordered模式是Ext4文件系统中的缺省模式。 1.主要的数据结构 1) 原子操作描述符 h a n d l e − t 原子操作描述符 一个原子操作 \textcolor{#4183c4}{handle _ - t原子操作描述符一个原子操作} handle−​t原子操作描述符一个原子操作 文件系统需要保证其与更新相关的系统调用如write以原子的方式进行处理而这些系统调用通常由多个I/O此操作组成——原子操作。 每个原子操作的大小到达阈值内核操作里的nblocks值时后续I/O操作将添加到后i一个原子操作。 jbd2中原子操作的数据结构为struct jbd2_journal_handle,主要成员如下图所示 //源文件include/linux/jbd2.hstruct jbd2_journal_handle{union{transaction_t * h_transaction; /*属于哪个事务*/journal_t *h_journal; /*属于哪个日志*/};int h_total_credits; /*允许添加到日志的剩余缓冲区数目*/...};typedef struct jbd2_journal_handle handle_t; /*原子操作描述符*/struct jbd2_journal_handle的部分成员 jbd2_journal_handle_t 是 Linux内核中用于处理日志块设备的结构。它是一个原子句柄用于收集单个高级原子更新期间发生的所有低级更改。原子句柄确保高级更新要么发生要么不发生因为实际对文件系统的更改只有在将原子句柄记录在日志中后才会被刷新。此外jbd2_journal_handle_t 还可以将多个原子句柄分组成单个事务然后在固定时间段后或者日志中没有足够的空间来容纳它时将事务写入日志。事务具有多种状态包括运行中、锁定、刷新、提交和完成。基于事务状态JBD能够确定需要重新应用到文件系统的事务。 2) 事务结构 s t r u c t t r a n s a t i o n − s \textcolor{#4183c4}{struct ~transation_-s} struct transation−​s 为了提高读写效率确保数据的完整性和一致性jbd2 将若干原子操作组成一个事务以事务作为单位进行日志读写具有生命周期性。这些操作要么全部完成要么全部不完成以确保数据的一致性。 在jbd2中事务具有五个状态分别是 运行状态Running事务开始执行尚未提交或回滚。准备提交状态Ready to commit事务的所有操作都已完成并准备好提交。提交状态Committing事务正在被提交。一旦提交成功事务就会从数据库中删除。回滚状态Rolling back事务因为某种原因需要回滚即撤销已经执行的操作。完成状态Done事务已经成功提交或回滚不再对数据库进行任何操作。 这种事务结构允许jbd2在处理大量数据时保持高效同时确保数据的完整性和一致性。通过将多个原子操作组合成一个事务jbd2可以减少日志的I/O操作次数提高系统的性能。同时事务的生命周期性使得jbd2可以有效地管理事务的状态和转换以适应不同的情况和需求。 //源文件 include/linux/jbd2.h struct transaction_s {int state; // 事务状态// 其他成员变量 };只有处于运行状态的事务可以进行原子操作 这些成员变量定义了struct transaction_s结构体的属性和行为。 3) 日志结构 s t r u c t j o u r n a l − s \textcolor{#4183c4}{struct ~journal_-s} struct journal−​s 在Linux内核中日志结构的主要数据结构是struct journal_s定义在include/linux/jbd2.h文件中。在这个数据结构中你可以找到关于日志的详细信息包括日志的初始化、加载、清除、事务处理等操作。这个数据结构在Linux内核中扮演着非常重要的角色用于管理文件系统的日志功能。 //源文件 include/linux/jbd2.h struct journal_s {int timestamp;char message[100];int logLevel; }; /*在这个示例中struct journal_s 包含了一个整数类型的时间戳 timestamp 一个长度为100的字符数组 message 用于存储消息内容 以及一个整数类型的 logLevel 用于表示日志级别。这个结构体可以根据实际需求进行扩展和修改。*/2.原子操作的生成 O r d e r e d \textcolor{#4183c4}{Ordered} Ordered 在 Ordered 模式下一个原子操作涉及若干个缓冲区的更新为了将元数据缓冲区中的数据及时更新生成一个原子操作jbd2将对这些元数据缓冲区进行管理。内核在jbd2 中获取对将要更新的元数据缓冲区的写权限以防止覆盖仍处于提交状态的事务中同一缓冲区中的内容。 由此当内核更新元数据缓冲区时jbd2 能及时地获取这些更新操作并将这些更新操作加入原子操作描述符中以生成新的原子操作。原子操作的生成过程如下图所示具体分四个步骤。 1) 获取原子操作描述符 调用 ext4_journal_start() 参数nblocks指定原子操作包含更新缓冲区域数阈值 2) 将元数据缓冲区纳入管理 e x t 4 − j o u r n a l − g e t − w r i t e − a c c e s s ( ) \textcolor{#4183c4}{ext4_-journal_-get_-write_-access()} ext4−​journal−​get−​write−​access() 内核通过调用函数ext4_journal_get_write_access ,获取磁盘元数据块除数据位图外所映射缓冲区的写权限。由于数据位图的更新涉及数据块的分配和释放因此其所映射的缓冲区具有更严苛的写权限。内核通过调用函数ext4_journal_get_undo_access()获取该类缓冲区的写权限。此外内核通过调用函数ext4_journal_get_create_access()获取新建元数据缓冲区的写权限。这三个函数在执行时都先通过调用函数jbd2_journal_add_journal_head()将当前元数据缓冲区纳人jbd2 的管理。 3) 获取原数据缓冲区的更新 在元数据缓冲区完成更新操作后内核通过调用函数jbd2_journal_dirty_metadata()通知jbd2 发生了元数据缓冲区更新操作。 4) 将更新操作加入当前原子操作描述符中 达到阈值jbd2生成一个原子操作。 3.事务提交 当生成的原子操作数量达到阙值jbd2将事务推人锁定状态并将其加入等待提交的队列中。openEuler 专门维护了一个内核线程提交事务每个Ext4 文件系统都对应一个kjournald 内核线程。该线程每隔一定的时间在等待提交队列中选择一个事务并通过调用函数 kjournald2()把该事务提交到磁盘的日志区。事务提交主要由函数 kjournald2()调用的函数 jbd2_journal_commit_transaction()完成。 j b d 2 − j o u r n a l − c o m m i t − t r a n s a c t i o n ( ) \textcolor{#4183c4}{ jbd2_-journal_-commit_-transaction()} jbd2−​journal−​commit−​transaction() 1调用函数 jbd2_journal_commit_transaction()将当前事务中元数据所关联的数据缓冲区中的内容写人磁盘第5行。 2调用函数 jbd2_journal_write_metadata_buffer()将元数据缓冲区中的数据写人磁盘的日志区中。具体地jbd2先创建一个新的元数据缓冲区然后将当前元数据缓冲区的内容复制至这个新的元数据缓冲区( 第28行)再将新的元数据缓冲区映射到日志区的某个数据块最后完成写人。 源文件fs/jbd2/commit.c void jbd2_journal_commit_transaction(journal_t * journal) { //将数据缓冲区的内容写人磁盘 err journal_ submit_data_buffers(journal, commit_transaction); while (commit_ transaction - › t_buffers) / jh commit_ transaction - t_ buffers; //将元数据缓冲区写人日志区 Flags jbd2_ journal _write_metadata_buffer( commit_ transaction, jh, wbuf [bufs], blocknr) ; //源文件Es/jbd2/journal.c int jba2_ journal _write_metadata_buffer(transaction_t * transaction, struct journal head *jh_ in,struct buffer_head ** bh out, sector_t blocknr) { //创建新元数据缓冲区 new_bh alloc_buffer_head (GEP_NOFS__GEP NOFAIL) ; init_buffernew_bh, NULL, NULL 1/初始化新元数据缓冲区 new_jh journal_add_journal_headnew_bh //纳人 jbd2 的管理 new _page jh2bh(jh_ in) - b_ page; //当前元数据缓冲区对应的物理页 mapped_data kmap_atomic(new_page) ; //获得该页起始地址 //页内容复制到 tmp memcpy tmp, mapped_data new_offset, bh_ in - b_size) ; new_page virt_to_page (tmp) ; //将 tmp 转换成新页 new_page /将新页设为新元数据缓冲区对应页 set_bh_page new_bh,new_page, new_offset //新元数据缓冲区映射到日志区中块号blocknr 的数据块new_bh-b_blocknr blocknr set_ buffer_dirty (new_bh) ; //将 new_bh 标记为脏4.崩溃的恢复 d o − o n e − p a s s ( ) \textcolor{#4183c4}{ do_-one_-pass()} do−​one−​pass() 崩溃的恢复流程如下 /源文件fs/jbd2/recovery. c 1/当传人参数 PASS. SCAN 时 unsigned int first_commit_ ID, next_commit_ ID; 1/临时记录起点与终点 sb journal -j_superblock next_commit_ ID be32_to_ cpu(sb - s_ sequence) ; first_commit_ ID next_ commit_ID; /起点为目志区超级块记录的起始数据失易 ifpass PASS_SCANinfo-start_transaction first_commit_ID //遍历日志区查看哪些日志区数据块需要恢复到磁盘以此找到日志区数据块的终点 done: if (pass PASS_SCAN) info - end _transaction next_commit_ ID; //当传入参数 PASS_REPLAY 时 while (1) { 1/遍历日志区的数据块 err jread(bh, journal, next_log_ block) ; //读下一个数据块到bh中 tagp bh - b_ data[ sizeof (journal_header_t//找到描述符块 //根据描述符块记录的映射关系逐一处理数据块 whiletagp - bh-b_data tag_bytesjournal - j_blocksize - descr_csum_size) / /读其中一个日志区数据块到 obh 中 err jreadobh,journal,io_block 1/从描述符块获得该日志区数据应被写入的磁盘数据块号 blocknr read _tag_block(journal, tag)函数 do_one_pass将日志数据写回磁盘原始位置的关键代码 jbd2 在首次调用函数 do_one_pass() 时以PASS_SCAN 作为输入参数用于方便日志区的回收和遍历。函数会读取超级块获取起点并遍历日志区获取终点。当 jbd2 再次调用函数 do_one_pass() 时以PASS_REPLAY 作为输入参数。函数会遍历数据块并获取与磁盘中数据块的映射关系然后将日志中的数据块内容读入缓冲区并标记为 obh 。接着找到磁盘中该数据块在内存中对应的缓冲区标记为 nbh并将 obh 中的内容复制到 nbh 中。最后将 nbh 标记为脏脏的缓冲区将被自动写回磁盘中。 #mermaid-svg-X6lbDfMosnuCyIwE {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-X6lbDfMosnuCyIwE .error-icon{fill:#552222;}#mermaid-svg-X6lbDfMosnuCyIwE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-X6lbDfMosnuCyIwE .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-X6lbDfMosnuCyIwE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-X6lbDfMosnuCyIwE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-X6lbDfMosnuCyIwE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-X6lbDfMosnuCyIwE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-X6lbDfMosnuCyIwE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-X6lbDfMosnuCyIwE .marker.cross{stroke:#333333;}#mermaid-svg-X6lbDfMosnuCyIwE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-X6lbDfMosnuCyIwE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-X6lbDfMosnuCyIwE .cluster-label text{fill:#333;}#mermaid-svg-X6lbDfMosnuCyIwE .cluster-label span{color:#333;}#mermaid-svg-X6lbDfMosnuCyIwE .label text,#mermaid-svg-X6lbDfMosnuCyIwE span{fill:#333;color:#333;}#mermaid-svg-X6lbDfMosnuCyIwE .node rect,#mermaid-svg-X6lbDfMosnuCyIwE .node circle,#mermaid-svg-X6lbDfMosnuCyIwE .node ellipse,#mermaid-svg-X6lbDfMosnuCyIwE .node polygon,#mermaid-svg-X6lbDfMosnuCyIwE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-X6lbDfMosnuCyIwE .node .label{text-align:center;}#mermaid-svg-X6lbDfMosnuCyIwE .node.clickable{cursor:pointer;}#mermaid-svg-X6lbDfMosnuCyIwE .arrowheadPath{fill:#333333;}#mermaid-svg-X6lbDfMosnuCyIwE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-X6lbDfMosnuCyIwE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-X6lbDfMosnuCyIwE .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-X6lbDfMosnuCyIwE .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-X6lbDfMosnuCyIwE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-X6lbDfMosnuCyIwE .cluster text{fill:#333;}#mermaid-svg-X6lbDfMosnuCyIwE .cluster span{color:#333;}#mermaid-svg-X6lbDfMosnuCyIwE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-X6lbDfMosnuCyIwE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} obh nbh 脏 日志机制相对于 FSCK 而言可以大大缩短磁盘崩溃恢复时间从而在崩溃并重新启动后加快恢复速度。日志机制有效地保证了文件系统元数据的一致性。在更新元数据时首先将元数据写入日志区域然后再更改目标位置的元数据。这样无论是在写入日志还是写入元数据时系统发生崩溃都不会对文件系统造成严重影响。 6. 当传入参数为 PASS_SCAN 时* 获取日志区的起点和终点。* 记录起点为日志区超级块记录的起始数据块。* 如果传入的参数是 PASS_SCAN则将起点设置为第一个提交的ID。* 遍历日志区查看哪些日志区数据块需要恢复到磁盘以此找到日志区数据块的终点。如果传入的参数是 PASS_SCAN则将终点设置为下一个提交的ID。 7. 当传入参数为 PASS_REPLAY 时* 遍历日志区的数据块。* 读取下一个数据块到 bh 中。* 找到描述符块并根据描述符块记录的映射关系逐一处理数据块。* 读取其中一个日志区数据块到 obh 中。* 从描述符块获得该日志区数据应被写入的磁盘数据块号。根据上述梳理这段代码似乎是在处理文件系统日志的恢复过程特别是当系统崩溃后需要从磁盘中恢复数据时。它首先通过 PASS_SCAN 参数确定日志区的起点和终点然后根据这些信息在 PASS_REPLAY 参数下恢复数据。#mermaid-svg-YGQ3GENwht0hE5zC {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-YGQ3GENwht0hE5zC .error-icon{fill:#552222;}#mermaid-svg-YGQ3GENwht0hE5zC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YGQ3GENwht0hE5zC .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-YGQ3GENwht0hE5zC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YGQ3GENwht0hE5zC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YGQ3GENwht0hE5zC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YGQ3GENwht0hE5zC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YGQ3GENwht0hE5zC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YGQ3GENwht0hE5zC .marker.cross{stroke:#333333;}#mermaid-svg-YGQ3GENwht0hE5zC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YGQ3GENwht0hE5zC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YGQ3GENwht0hE5zC .cluster-label text{fill:#333;}#mermaid-svg-YGQ3GENwht0hE5zC .cluster-label span{color:#333;}#mermaid-svg-YGQ3GENwht0hE5zC .label text,#mermaid-svg-YGQ3GENwht0hE5zC span{fill:#333;color:#333;}#mermaid-svg-YGQ3GENwht0hE5zC .node rect,#mermaid-svg-YGQ3GENwht0hE5zC .node circle,#mermaid-svg-YGQ3GENwht0hE5zC .node ellipse,#mermaid-svg-YGQ3GENwht0hE5zC .node polygon,#mermaid-svg-YGQ3GENwht0hE5zC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YGQ3GENwht0hE5zC .node .label{text-align:center;}#mermaid-svg-YGQ3GENwht0hE5zC .node.clickable{cursor:pointer;}#mermaid-svg-YGQ3GENwht0hE5zC .arrowheadPath{fill:#333333;}#mermaid-svg-YGQ3GENwht0hE5zC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YGQ3GENwht0hE5zC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YGQ3GENwht0hE5zC .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-YGQ3GENwht0hE5zC .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-YGQ3GENwht0hE5zC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YGQ3GENwht0hE5zC .cluster text{fill:#333;}#mermaid-svg-YGQ3GENwht0hE5zC .cluster span{color:#333;}#mermaid-svg-YGQ3GENwht0hE5zC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YGQ3GENwht0hE5zC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 传人参数 参数类型 PASS_SCAN PASS_REPLAY 获取起点和终点 遍历日志区的数据块 读取数据块到缓冲区 根据描述符块处理数据块 从描述符块获取磁盘数据块号 虚拟文件系统 简介 虚拟文件系统 V i r t u a l F i l e S y s t e m V F S 虚拟文件系统Virtual File SystemVFS 虚拟文件系统VirtualFileSystemVFS 现代操作系统支持同时使用多种文件系统。 在计算机科学中虚拟文件系统Virtual File SystemVFS是一个抽象层它允许应用程序和操作系统与各种不同类型的物理文件系统进行交互。VFS 隐藏了物理文件系统的底层细节使应用程序和操作系统能够以统一、标准化的方式来访问和管理文件和目录。 通过使用 VFS操作系统可以同时支持多种不同的文件系统例如EXT4、NTFS、FAT32等。这样做的目的是为了提供更大的灵活性和可扩展性因为新的文件系统或对现有文件系统的改进可以很容易地添加到系统中而无需对应用程序或操作系统进行任何修改。 此外VFS 还提供了一些额外的功能和优点包括 可移植性应用程序可以在不同的操作系统或平台上运行只需进行少量修改或无需修改因为 VFS 隐藏了底层文件系统的差异。性能优化VFS 可以根据需要缓存文件数据和元数据从而提高访问速度。安全性VFS 可以提供额外的安全层例如权限控制和加密以确保文件系统的安全性和完整性。集成和互操作性VFS 可以与其他软件组件和服务集成例如网络文件共享和分布式文件系统。 #mermaid-svg-2Zj31mhYDveDCt1r {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-2Zj31mhYDveDCt1r .error-icon{fill:#552222;}#mermaid-svg-2Zj31mhYDveDCt1r .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2Zj31mhYDveDCt1r .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-2Zj31mhYDveDCt1r .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2Zj31mhYDveDCt1r .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2Zj31mhYDveDCt1r .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2Zj31mhYDveDCt1r .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2Zj31mhYDveDCt1r .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2Zj31mhYDveDCt1r .marker.cross{stroke:#333333;}#mermaid-svg-2Zj31mhYDveDCt1r svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2Zj31mhYDveDCt1r .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2Zj31mhYDveDCt1r .cluster-label text{fill:#333;}#mermaid-svg-2Zj31mhYDveDCt1r .cluster-label span{color:#333;}#mermaid-svg-2Zj31mhYDveDCt1r .label text,#mermaid-svg-2Zj31mhYDveDCt1r span{fill:#333;color:#333;}#mermaid-svg-2Zj31mhYDveDCt1r .node rect,#mermaid-svg-2Zj31mhYDveDCt1r .node circle,#mermaid-svg-2Zj31mhYDveDCt1r .node ellipse,#mermaid-svg-2Zj31mhYDveDCt1r .node polygon,#mermaid-svg-2Zj31mhYDveDCt1r .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2Zj31mhYDveDCt1r .node .label{text-align:center;}#mermaid-svg-2Zj31mhYDveDCt1r .node.clickable{cursor:pointer;}#mermaid-svg-2Zj31mhYDveDCt1r .arrowheadPath{fill:#333333;}#mermaid-svg-2Zj31mhYDveDCt1r .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2Zj31mhYDveDCt1r .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2Zj31mhYDveDCt1r .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-2Zj31mhYDveDCt1r .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-2Zj31mhYDveDCt1r .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2Zj31mhYDveDCt1r .cluster text{fill:#333;}#mermaid-svg-2Zj31mhYDveDCt1r .cluster span{color:#333;}#mermaid-svg-2Zj31mhYDveDCt1r div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2Zj31mhYDveDCt1r :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 可移植性 性能优化 安全性 集成和互操作性 数据结构先欠着等大家可以先投票~
http://www.pierceye.com/news/821766/

相关文章:

  • 内江 网站建设网站后台登录地址
  • 网站建设合同副本临沂建设局官方网站
  • 林州网站建设哪家好网站做电子链接标识申请好吗
  • 石家庄开发网站建设263企业邮箱登录邮箱
  • 青岛公司建设网站电子商务网站开发技术论文
  • 龙华网站的建设建设网站教程视频视频
  • 威海高区建设局网站品牌网站建设多少钱
  • 网站php网站空间新乡河南网站建设
  • 你第一个物流网站建设方案信诚网络公司网站
  • 企业建站什么网站好wordpress管理员后台
  • 南京网站开发价格两个wordpress共用一个数据库
  • 番禺制作网站平台柳城网站制作
  • 网站建设相关视频教程网页设计布局有哪几种方法
  • 能接做网站的活的网站上海建网站方案
  • 免费网站软件app大全飘雪影院手机免费观看免费
  • 怎么做类似淘宝的网站石家庄网络开发公司
  • 专业SEO教程网站广东省住房与城乡建设部网站
  • 360免费建站为什么注册不了雨灿网站建设
  • 益阳市建设局网站在家来料加工
  • 邵阳网站设计宠物网站 html模板
  • 网站域名以co与com有什么不同18款禁用黄a免费
  • 农村电商网站建设方案wordpress官网密码错误
  • 婚庆公司网站建设doc高端网站建设推广
  • 做房地产一级市场的看什么网站网站建建设公司和网络自建
  • 搞一个网站要多少钱长治做网站哪家好
  • 德州口碑好的网站制作公司网站运营托管咨询
  • 东阳网站建设价格广州最好的网站设计
  • 襄垣网站建设宝塔面板怎么搭建网站
  • 电影网站源码access广州网站建设排名一览表
  • 做论坛网站多少钱企业做网站有用吗天涯