中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

天津營銷網(wǎng)站建設(shè)公司哪家好虎撲體育網(wǎng)體育

天津營銷網(wǎng)站建設(shè)公司哪家好,虎撲體育網(wǎng)體育,網(wǎng)頁設(shè)計(jì)做網(wǎng)站,訪問緊急升級(jí)中通知問升級(jí)Tina Linux 存儲(chǔ)開發(fā)指南 1 概述 1.1 編寫目的 介紹TinaLinux Flash,分區(qū),文件系統(tǒng)等存儲(chǔ)相關(guān)信息,指導(dǎo)方案的開發(fā)定制。 1.2 適用范圍 Tina V3.0 及其后續(xù)版本。 1.3 相關(guān)人員 適用于TinaLinux 平臺(tái)的客戶及相關(guān)技術(shù)人員。 2 分區(qū)管…

Tina Linux 存儲(chǔ)開發(fā)指南

1 概述

1.1 編寫目的

介紹TinaLinux Flash,分區(qū),文件系統(tǒng)等存儲(chǔ)相關(guān)信息,指導(dǎo)方案的開發(fā)定制。

1.2 適用范圍

Tina V3.0 及其后續(xù)版本。

1.3 相關(guān)人員

適用于TinaLinux 平臺(tái)的客戶及相關(guān)技術(shù)人員。

2 分區(qū)管理

2.1 分區(qū)配置文件

在全志平臺(tái)中,通過sys_partition.fex 文件配置分區(qū)。在Tina 中,可以在lunch 選擇方案后,通過命令cconfigs 快速跳轉(zhuǎn)到分區(qū)配置目錄,通常情況下,其路徑如下。

tina/device/config/chips/<芯片編號(hào)>/configs/<方案名>/linux/sys_partition.fex
tina/device/config/chips/<芯片編號(hào)>/configs/<方案名>/linux/sys_partition_nor.fex
#以上路徑不存在,則使用
tina/device/config/chips/<芯片編號(hào)>/configs/<方案名>/sys_partition.fex

說明
sys_partition_nor.fex 適用于nor。
sys_partition.fex 適用于rawnand/spinand/mmc。

2.2 分區(qū)配置格式

以rootfs 分區(qū)為例:

[partition]
name = rootfs
size = 20480
downloadfile = "rootfs.fex"
user_type = 0x8000

每個(gè)分區(qū)以[partition] 標(biāo)識(shí),分區(qū)屬性及其意義如下表。

屬性含義必選備注
name分區(qū)名Y
size分區(qū)大小Y單位:扇區(qū)(512B),注1
downlodefile分區(qū)燒入的鏡像文件N注2
verify量產(chǎn)后校驗(yàn)標(biāo)識(shí)N(默認(rèn))1:使能;0:禁用,注3
user_type分區(qū)屬性N注 4
keydata量產(chǎn)時(shí)是否擦除本分區(qū)N0x8000:使用;其他無效

說明:

  1. 最后一個(gè)分區(qū)(UDISK),不設(shè)置size,表示分配所有剩余空間。
  2. downloadfile 支持絕對(duì)路徑和相對(duì)路徑,相對(duì)于tina/out/<方案名>/image。
  3. verify 決定是否校驗(yàn)downloadfile 中指定的鏡像,若為ext4 稀疏鏡像,務(wù)必禁用。
  4. 歷史遺留,目前只對(duì)UBI 方案有效。bit0為1 時(shí),表示創(chuàng)建靜態(tài)卷,反之為動(dòng)態(tài)卷。

創(chuàng)建downloadfile 的資源鏡像包看章節(jié)分區(qū)資源鏡像文件。
[partition] 標(biāo)識(shí)用戶空間的邏輯分區(qū),在UBI 方案中,表現(xiàn)為UBI 卷。此外,在sys_partiton.fex中存在特殊的配置MBR,用于配置MBR 空間大小,此配置在UBI 方案中無效。例如:

[mbr]
size = 2048

MBR 分區(qū)以Kbyte 為單位,對(duì)用戶不可見,屬于隱藏空間,其大小也必須滿足對(duì)齊原則。

警告
一般情況下,不建議用戶修改mbr 分區(qū)的大小。

2.3 常見分區(qū)及其用途

分區(qū)名用途大小備注
boot內(nèi)核鏡像分區(qū)比實(shí)際鏡像等大或稍大即可
rootfs根文件系統(tǒng)鏡像比實(shí)際鏡像等大或稍大即可
extend擴(kuò)展系統(tǒng)鏡像參考OTA 文檔參考OTA 文檔僅小容量OTA 方案使用
recovery恢復(fù)系統(tǒng)鏡像參考OTA 文檔僅限大容量OTA 方案使用
private存儲(chǔ)SN、MAC 等數(shù)據(jù)使用默認(rèn)大小即可量產(chǎn)時(shí)默認(rèn)不丟失
misc存儲(chǔ)系統(tǒng)狀態(tài)、刷機(jī)狀態(tài)使用默認(rèn)大小即可
env存放Uboot 使用的數(shù)據(jù)使用默認(rèn)大小即可
pstore內(nèi)核奔潰日志轉(zhuǎn)存分區(qū)使用默認(rèn)大小即可
rootfs_data根目錄覆蓋分區(qū)根據(jù)需求配置注1
UDISK用戶數(shù)據(jù)分區(qū)不需要配置大小注2

說明:

  1. rootfs_data 分區(qū)通過overlayfs 覆蓋根文件系統(tǒng),以支持squashfs 根文件系統(tǒng)的可寫,此時(shí)對(duì)根文件系統(tǒng)寫入的數(shù)
    據(jù)實(shí)際是保存到rootfs_data 分區(qū),因此rootfs_data 分區(qū)的容量標(biāo)識(shí)著根文件系統(tǒng)最大可寫數(shù)據(jù)量。
  2. UDISK 作為最后一個(gè)分區(qū),不需要設(shè)置size,表示分配剩余所有空間給UDISK。

2.4 分區(qū)大小與對(duì)齊

分區(qū)大小的對(duì)齊要求與不同介質(zhì)(nor/nand/mmc)、不同存儲(chǔ)方案相關(guān)。不按對(duì)齊要求配置,可能出現(xiàn)文件系統(tǒng)異常,分區(qū)邊界數(shù)據(jù)丟失等現(xiàn)象。對(duì)齊規(guī)則如下表。

介質(zhì)對(duì)齊大小備注
nor64K對(duì)齊物理擦除塊大小,注1
(nftl) spinand驅(qū)動(dòng)超級(jí)塊大小注2
(ubi) spinand2 × 物理塊- 2 × 頁注3
rawnand驅(qū)動(dòng)超級(jí)塊大小與物料相關(guān),16M 對(duì)齊可基本兼容
emmc16M與物料相關(guān),16M 對(duì)齊可基本兼容

說明

  1. nor 的擦除塊常見為64K,即在sys_partition_nor.fex 中分區(qū)size 進(jìn)行128 對(duì)齊。在id 表配置為4K 擦除且使能內(nèi)核CONFIG_MTD_SPI_NOR_USE_4K_SECTORS 時(shí),也可使用4K 對(duì)齊。推薦使用默認(rèn)64K 對(duì)齊。
  2. 在常見的128M Spi Nand 中,為256K 對(duì)齊,即在sys_partition.fex 中分區(qū)size 進(jìn)行512 對(duì)齊。
  3. 在常見的128M Spi Nand 中,需要和邏輯擦除塊(super block)對(duì)齊,1 個(gè)super block 包含兩個(gè)物理擦除塊,常見的物理擦除塊128K,1 個(gè)邏輯的超級(jí)塊為256K,但是需要使用每個(gè)物理塊的第一個(gè)page(2K)來作為ubi 所需的信息頭部,所以實(shí)際的為(256k-2*2k),為252K 對(duì)齊,即在sys_partition.fex 中分區(qū)size 進(jìn)行504 對(duì)齊。

警告
如果分區(qū)不對(duì)齊,可能會(huì)出現(xiàn)以下情況。
? nor/rawnand/spinand 可能會(huì)導(dǎo)致數(shù)據(jù)丟失。
? mmc 不會(huì)造成數(shù)據(jù)丟失,但可能導(dǎo)致性能損失。

如果分區(qū)使用ubifs 文件系統(tǒng),分區(qū)最小為5M ,否則大概率提示空間不夠。
如果分區(qū)使用ext4 文件系統(tǒng),分區(qū)最小為3M ,否則無法形成日志,會(huì)有掉電變磚風(fēng)險(xiǎn)。

技巧

  1. 在ext4 與日志章節(jié)有描述判斷創(chuàng)建的ext4 文件系統(tǒng)是否支持日志的方法。
  2. 在分區(qū)資源鏡像文件章節(jié)指導(dǎo)如何創(chuàng)建帶文件系統(tǒng)的資源鏡像、分區(qū)大小、文件系統(tǒng)大小、文件大小更多內(nèi)容,請(qǐng)參考總?cè)萘空f明。

2.5 分區(qū)與文件系統(tǒng)

常見的分區(qū)與文件系統(tǒng)對(duì)應(yīng)關(guān)系如下表。

分區(qū)名默認(rèn)文件系統(tǒng)文件系統(tǒng)特性備注
rootfssquashfs壓縮、只讀為了安全,根文件系統(tǒng)建議只讀
rootfs_datajffs2/ext4/ubifs可寫注1
UIDSKjffs2/ext4/ubifs可寫注1
bootvfat裸數(shù)據(jù)分區(qū),部分方案為vfat
privatevfat注2
miscnone裸數(shù)據(jù)分區(qū)
envnone裸數(shù)據(jù)分區(qū)
pstorepstore轉(zhuǎn)存奔潰日志

說明

  1. 可寫的分區(qū),nor 為jffs2;UBI 方案為ubifs;其他為ext4。
  2. private 默認(rèn)為裸數(shù)據(jù),使用dragonSN 工具燒錄后會(huì)成為vfat 文件系統(tǒng)。

只讀文件系統(tǒng)推薦使用squashfs??蓪懳募到y(tǒng),nor 推薦jffs2,UBI 方案推薦ubifs,其他推薦ext4。更多文件系統(tǒng)信息,請(qǐng)參考文件系統(tǒng)支持情況。

2.6 分區(qū)資源鏡像文件

在sys_partition.fex中通過downloadfile 指定需要燒錄到分區(qū)的資源鏡像文件。大多數(shù)情況下,資源鏡像文件都構(gòu)建在文件系統(tǒng)上,通過某些命令實(shí)現(xiàn)把系統(tǒng)需要的文件,例如音頻文件、視頻文件等資源,打包成一個(gè)帶文件系統(tǒng)的鏡像包,并在燒錄時(shí)把鏡像包燒寫入存儲(chǔ)
介質(zhì)。
創(chuàng)建不同文件系統(tǒng)鏡像的命令不一樣,常見有以下幾種:

文件系統(tǒng)創(chuàng)建鏡像命令
vfatmkfs.vfat
ext4make_ext4fs
ubifsmkfs.ubifs
squashfsmksquashfs4

為了最大程度利用空間,一般會(huì)使文件系統(tǒng)等于物理分區(qū)大小,即創(chuàng)建文件系統(tǒng)時(shí)使用分區(qū)表劃定的分區(qū)大小來創(chuàng)建。

如果不希望硬編碼大小,則可在打包時(shí)從分區(qū)表獲得大小,再傳給文件系統(tǒng)創(chuàng)建工具,具體的實(shí)現(xiàn)可以參考tina/scripts/pack_img.sh 中的make_data_res() 和make_user_res() 等函數(shù)。

2.6.1 創(chuàng)建squashfs 鏡像

生成squashfs 的命令,可參考編譯過程的log 得到,或者在網(wǎng)上搜索squashfs 生成方式。
例如在scripts/pack_img.sh 中定義一個(gè)函數(shù)

function make_user_squash()
{
local SOURCE_DATE_EPOCH=$(${PACK_TOPDIR}/scripts/get_source_date_epoch.sh)
# 這一行指定要打包到文件系統(tǒng)的數(shù)據(jù)
local USER_PART_FILE_PATH=${PACK_TOPDIR}/target/allwinner/方案名字/user_sq
local USER_PART_SQUASHFS=${PACK_TOPDIR}/out/${PACK_BOARD}/image/user_sq.squashfs
local USER_PART_DOWNLOAD_FILE=${PACK_TOPDIR}/out/${PACK_BOARD}/image/user_sq.fex
cd ${ROOT_DIR}/image
[ -e $USER_PART_FILE_PATH ] && {
#這里用了gzip,需要更高壓縮率可改成xz
${PACK_TOPDIR}/out/host/bin/mksquashfs4 $USER_PART_FILE_PATH $USER_PART_SQUASHFS \
-noappend -root-owned -comp gzip -b 256k \
-processors 1 -fixed-time $SOURCE_DATE_EPOCH
dd if=${USER_PART_SQUASHFS} of=${USER_PART_DOWNLOAD_FILE} bs=128k conv=sync
}
cd -
}

找個(gè)地方調(diào)用下即可。
這里不用傳入分區(qū)表的原因是,制作squashfs 不需要指定文件系統(tǒng)大小,只讀的文件系統(tǒng)大小完全取決于文件內(nèi)容。

2.6.2 創(chuàng)建vfat 鏡像

mkfs.vfat <輸出鏡像> -C <文件系統(tǒng)大小>
mcopy -s -v -i <輸出鏡像> <資源文件所在文件夾>/* ::

可參考pack_img.sh(在其中搜索mkfs.vfat 找到相關(guān)代碼)。

2.6.3 創(chuàng)建ext4 鏡像

使用tina/out/host/bin/make_ext4fs 創(chuàng)建ext4 鏡像,推薦的使用方法如下:

make_ext4fs -l <文件系統(tǒng)大小> -b <塊大小> -m 0 -j <日志塊個(gè)數(shù)> <輸出的鏡像保存路徑> <資源文件所在文件
夾>

其中,
? -m 0: 表示不需要要為root 保留空間。
? -j < 日志塊個(gè)數(shù)>: 日志總大小為塊大小* 日志塊個(gè)數(shù)。

例如:

make_ext4fs -l 20m -b 1024 -m 0 -j 1024 ${ROOT_DIR}/img/data.fex ${FILE_PATH}

如果空間不夠大,會(huì)顯示類似如下的錯(cuò)誤日志:

$ ./bin/make_ext4fs -l 10m -b 1024 -m 0 -j 1024 data.fex ./bin
Creating filesystem with parameters:
Size: 10485760
Block size: 1024
Blocks per group: 8192
Inodes per group: 1280
Inode size: 256
Journal blocks: 1024
Label:
Blocks: 10240
Block groups: 2
Reserved blocks: 0
Reserved block group size: 63
error: ext4_allocate_best_fit_partial: failed to allocate 7483 blocks, out of space?

上述錯(cuò)誤中,資源文件達(dá)到100+M,但是創(chuàng)建的鏡像-l 指定的大小只有10M,導(dǎo)致空間不夠而報(bào)錯(cuò)。只需要擴(kuò)大鏡像大小即可。
如需使用分區(qū)大小作為文件系統(tǒng)大小,可參考pack_img.sh(在其中搜索make_ext4fs 找到相關(guān)代碼)。

技巧
鏡像大小可以根據(jù)分區(qū)大小設(shè)置,也可以根據(jù)資源大小設(shè)置,后通過稀疏和resize 處理,即可保證最短燒錄時(shí)間和動(dòng)態(tài)匹配分區(qū)大小。見稀疏ext4 鏡像和動(dòng)態(tài)resize 章節(jié)。

2.6.3.1 稀疏ext4 鏡像

如果資源文件只有10M,但創(chuàng)建了100M 的鏡像文件,導(dǎo)致燒錄100M 的文件拖慢了燒錄速度。此時(shí)可以采用稀疏ext4 鏡像。

tina/out/host/bin/img2simg <原鏡像> <輸出鏡像>

稀疏鏡像的原理,類似與把文件系統(tǒng)沒用到的無效數(shù)據(jù)全刪掉,把文件系統(tǒng)壓縮??蓞⒖紁ack_img.sh 中的函數(shù)sparse_ext4() 的實(shí)現(xiàn)與運(yùn)用。

2.6.3.2 動(dòng)態(tài)resize

如果擔(dān)心創(chuàng)建鏡像時(shí)指定的大小與實(shí)際的分區(qū)大小不匹配,可以在設(shè)備啟動(dòng)后執(zhí)行resize2fs 動(dòng)態(tài)調(diào)整文件系統(tǒng)的大小。
例如:

resize2fs /dev/by-name/UDISK

命令后不指定大小,則默認(rèn)為分區(qū)大小。通過這方法可以讓打包鏡像創(chuàng)建的文件系統(tǒng)大小匹配分區(qū)大小。
此命令可直接寫入啟動(dòng)腳本,在掛載前執(zhí)行。每次啟動(dòng)都執(zhí)行一遍不會(huì)有不良影響。

2.6.4 創(chuàng)建ubifs 鏡像

使用tina/out/host/bin/make.ubifs 創(chuàng)建ubifs 鏡像,推薦的使用方法如下:

mkfs.ubifs -x <壓縮方式> -b <超級(jí)頁大小> -e <邏輯擦除塊大小> -c <最大邏輯擦除塊個(gè)數(shù)> -r <資源文件所在
文件夾> -o <輸出的鏡像保存路徑>
壓縮方式可選none lzo zlib, 壓縮率zlib > lzo > none
對(duì)常見的128MB spinand,1 page = 2048 bytes, 1 block = 64 page, 則
超級(jí)頁大小為2048 * 2 = 4096
邏輯擦除塊大小為2048 * 2 * 64 = 262144
最大邏輯擦除塊個(gè)數(shù),可簡單設(shè)置為一個(gè)較大的值,例如128MB / ( 2048 bytes * 2 * 64) = 512
則最終的命令為:
mkfs.ubifs -x zlib -b 4096 -e 262144 -c 512 -r ${FILE_PATH} -o ${ROOT_DIR}/img/data_ubifs.
fex

2.7 根文件系統(tǒng)改用ubifs

使用suqashfs + overlayfs(ubifs) 方案實(shí)現(xiàn)根目錄可寫,但是ubifs 會(huì)占用大量的空間存放元數(shù)據(jù),造成空間浪費(fèi)。理論上,UBIFS 可直接作為根文件系統(tǒng),其穩(wěn)定性和可壓縮性足夠保證安全和提高空間利用率。

警告
請(qǐng)謹(jǐn)慎使用,UBIFS 作為根文件系統(tǒng)只是理論安全,全志暫無量產(chǎn)方案佐證。

修改步驟如下:

  1. 執(zhí)行cdevice ,修改跳轉(zhuǎn)目錄下的Makefile 在FEATURES 變量中添加ubifs 和nand
  2. 執(zhí)行make menuconfig 使能在Target Image 頁面下使能ubifs 在Utilities->mtdutils
    頁面中使能mtd-utils-mkfs.ubifs
  3. 執(zhí)行cconfigs ,修改跳轉(zhuǎn)目錄下的env-XXX.cfg 把rootfstype 值改為ubifs 在對(duì)應(yīng)
    存儲(chǔ)介質(zhì)的setargs_XXX 的root 值改為root=ubi0_X ,其中X 表示對(duì)應(yīng)的第幾個(gè)分區(qū);刪除
    ubi.block 項(xiàng)。
  4. 執(zhí)行make kernel_menuconfig,取消使能overlayfs
  5. 在sys_partition.fex 中刪除rootfs_data 分區(qū)

2.8 總?cè)萘空f明

在全志的驅(qū)動(dòng)中,會(huì)預(yù)留一部分空間存儲(chǔ)特殊數(shù)據(jù),因此提供給用戶分區(qū)空間不等于實(shí)際Flash總?cè)萘俊?/p>

分區(qū)表可用空間= flash總?cè)萘? 保留空間

不同存儲(chǔ)介質(zhì),其保留空間會(huì)有差異。

存儲(chǔ)介質(zhì)保留空間備注
nor512K對(duì)應(yīng)bootloader 分區(qū),包含分區(qū)表,boot0,uboot
(nftl) nand總?cè)萘康?/10~1/8注1,注2
(UBI) spinand
mmc20M包含boot0,uboot 等

最新spinor 的存儲(chǔ)分布, 隱藏空間1MB,其中mbr 占用16KB,mbr 往前共占用1008KB,uboot 往前共占用64KB,其中包括boot0 和uboot 中間4KB 的預(yù)留區(qū)域,這段區(qū)域用于存放flash 的spi 采樣點(diǎn)等信息。

|boot0|4kb|uboot|mbr |分區(qū)表可見的用戶分區(qū)|

說明

  1. (nftl) nand 的隱藏空間對(duì)用戶不可見,包含分區(qū)表MBR 分區(qū),boot0,uboot, 磨損算法、壞塊保留等。對(duì)128M 的
    spinand 來說,用戶可用空間一般為108M。

  2. 由于出廠壞塊的存在,可能會(huì)導(dǎo)致每一顆Flash 呈現(xiàn)的用戶可用總?cè)萘坎煌?#xff0c;但全志(nftl) nand 保證總?cè)萘坎粫?huì)隨著使
    用過程出現(xiàn)壞塊而導(dǎo)致可用容量減少。

  3. UBI 方案中,除了必要的mtd 物理分區(qū)之外(boot0/uboot/pstore 等),其余空間劃分到一個(gè)mtd 物理分區(qū)。在此
    mtd 物理分區(qū)中根據(jù)sys_partition.fex 的劃分構(gòu)建ubi 卷。UBI 的機(jī)制,每個(gè)塊都需要預(yù)留1~2 個(gè)頁作為EC/VID
    頭。因此可用容量會(huì)小于mtd 物理分區(qū)容量。

對(duì)于非ubi 方案,用戶空間可通過下面的命令查看用戶可用分區(qū)大小,大小單位為KB。

# cat /proc/partitions
major minor #blocks name
93 0 112384 nand0
93 1 256 nand0p1
93 2 5120 nand0p2
93 3 10240 nand0p3
93 4 10240 nand0p4
93 5 7168 nand0p5
93 6 64 nand0p6
93 7 512 nand0p7
93 8 256 nand0p8
93 9 76463 nand0p9

如例子中的結(jié)果,nand0 分為多個(gè)分區(qū),每個(gè)nand0px 對(duì)應(yīng)一個(gè)分區(qū)表中的分區(qū)。對(duì)于ubi 方案,整個(gè)nand 分為若干mtd??墒褂靡韵旅畈榭?/p>

# cat /proc/mtd
dev: size erasesize name
mtd0: 00100000 00040000 "boot0"
mtd1: 00300000 00040000 "uboot"
mtd2: 00100000 00040000 "secure_storage"
mtd3: 00080000 00040000 "pstore"
mtd4: 07a80000 00040000 "sys"

如例子中的結(jié)果,整個(gè)nand 分為5 個(gè)mtd。
? mtd0 存放boot0, size 1 MB
? mtd1 存放uboot, size 3 MB
? mtd2 存放secure_storage, size 1 MB
? mtd3 存放pstore, size 512 KB
? mtd4 則會(huì)進(jìn)一步分為多個(gè)ubi 卷,占用剩余所有空間

以上所有mtd 的size 相加,應(yīng)該恰好等于flash 總size。分區(qū)表中定義的每個(gè)邏輯分區(qū),會(huì)對(duì)應(yīng)mtd sys 上的ubi 卷。可使用以下命令查看

# ubinfo -a
UBI version: 1
Count of UBI devices: 1
UBI control device major/minor: 10:51
Present UBI devices: ubi0
ubi0
Volumes count: 12
Logical eraseblock size: 258048 bytes, 252.0 KiB
Total amount of logical eraseblocks: 489 (126185472 bytes, 120.3 MiB)
Amount of available logical eraseblocks: 0 (0 bytes)
Maximum count of volumes 128
Count of bad physical eraseblocks: 1
Count of reserved physical eraseblocks: 19
Current maximum erase counter value: 3
Minimum input/output unit size: 4096 bytes
Character device major/minor: 247:0
Present volumes: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
Volume ID: 0 (on ubi0)
Type: static
Alignment: 1
Size: 1 LEBs (258048 bytes, 252.0 KiB)
Data bytes: 258048 bytes (252.0 KiB)
State: OK
Name: mbr
Character device major/minor: 247:1
-----------------------------------
Volume ID: 1 (on ubi0)
Type: dynamic
Alignment: 1
Size: 2 LEBs (516096 bytes, 504.0 KiB)
State: OK
Name: boot-resource
Character device major/minor: 247:2
-----------------------------------
... #此處省略若干卷
-----------------------------------
Volume ID: 11 (on ubi0)
Type: dynamic
Alignment: 1
Size: 242 LEBs (62447616 bytes, 59.6 MiB)
State: OK
Name: UDISK
Character device major/minor: 247:12

如例子中的結(jié)果
? volume 0 為mbr, 占1 LEBs(252 KB),對(duì)應(yīng)分區(qū)表本身
? volume 1 為boot-resource, 占2 LEBs(504 KB),對(duì)應(yīng)分區(qū)表中第一個(gè)分區(qū)
? …
? volume 11 為UDISK, 占242 LEBs(59.8 MB),對(duì)應(yīng)分區(qū)表中最后一個(gè)分區(qū)
常見的關(guān)于容量的疑惑與解答。

  1. 問:df 查看UDISK 分區(qū)大小,明明分區(qū)有50M,怎么顯示總大小只有40+M?
    答:df 顯示的是文件系統(tǒng)的大小,文件系統(tǒng)本身需要額外的空間存儲(chǔ)元數(shù)據(jù),導(dǎo)致實(shí)際可用空間
    會(huì)比分區(qū)大小略少。
  2. 問:df 查看boot 分區(qū)大小,為什么顯示的大小比實(shí)際分區(qū)大?
    答:boot 分區(qū)是通過鏡像燒寫的形式格式化的fs,創(chuàng)建鏡像時(shí)設(shè)置的文件系統(tǒng)的大小并不等于分
    區(qū)實(shí)際大小,導(dǎo)致此時(shí)文件系統(tǒng)大小并不能體現(xiàn)實(shí)際分區(qū)大小。
  3. 問:df 查看squashfs 使用率總是100%?
    答:squashfs 是只讀壓縮文件系統(tǒng),文件系統(tǒng)大小取決于總文件大小,使用率總是100%,跟分
    區(qū)大小無關(guān)。

說明

  1. 文件大小
    我們常說的文件大小,指的是文件內(nèi)容有多少字節(jié)。但在一個(gè)文件系統(tǒng)中,空間分配以塊為單位,必然會(huì)造成內(nèi)部碎片。假
    設(shè)塊為4K,如果文件大小為1K,文件系統(tǒng)依然為其分配4K 的塊,就會(huì)造成3K 的空間浪費(fèi)。
  2. 文件系統(tǒng)大小
    文件系統(tǒng)大小,指的是文件系統(tǒng)元數(shù)據(jù)中標(biāo)識(shí)的可用大小。形象來說,是df 命令或者statfs() 函數(shù)反饋的大小。文件系
    統(tǒng)大小不一定等于分區(qū)大小,既可大于分區(qū)大小,也可小于分區(qū)大小。
  3. 分區(qū)大小
    在劃分分區(qū)時(shí)規(guī)定的大小,往往是sys_partition.fex 中指定的大小。

2.9 特殊隱藏空間

不管是nor,nand 還是mmc,都需要一些隱藏空間存儲(chǔ)特殊數(shù)據(jù),例如boot0/uboot/dtb/sys_config。用戶無法使用這些隱藏空間。
此外,nand 驅(qū)動(dòng)還需要額外的空間以實(shí)現(xiàn)磨損平衡、壞塊管理算法,因此nand 的隱藏空間更大。

隱藏空間大小見總?cè)萘空f明。

3 系統(tǒng)掛載

Tina 目前支持兩種啟動(dòng)方式,分別是busybox 和procd,不同啟動(dòng)方式,其自動(dòng)掛載的配置不同。
此處的自動(dòng)掛載指開機(jī)冷掛載以及熱插拔掛載,其中冷掛載指啟動(dòng)時(shí)掛載,熱掛載指TF/U 盤等插拔設(shè)備時(shí)的掛載。

3.1 塊設(shè)備節(jié)點(diǎn)

Tina 中設(shè)備節(jié)點(diǎn)都在/dev 目錄下,對(duì)于不同存儲(chǔ)介質(zhì),生成的設(shè)備節(jié)點(diǎn)會(huì)不一樣。

存儲(chǔ)介質(zhì)設(shè)備節(jié)點(diǎn)備注
nand/dev/nand{a,b,c…}MBR 分區(qū)表
nand/dev/nand0p{1,2,3…}GPT 分區(qū)表
mmc/dev/mmcblk0p{1,2,3…}
nor/dev/mtdblock{0,1,2…}
TF卡/dev/mmcblk{0,1}p{1,2…}注1
U 盤/dev/sda{1,2…}
SATA硬盤/dev/sda{1,2…}

說明

  1. 若使用mmc 做內(nèi)部存儲(chǔ)介質(zhì),由于mmc 占用了mmcblk0的設(shè)備名,此時(shí)TF 卡的設(shè)備名序號(hào)遞增為mmcblk1,否則生
    成mmcblk0的設(shè)備名。因此配置fstab 時(shí)尤其注意TF 設(shè)備名是否正確。
    對(duì)sys_partition.fex 中設(shè)置的內(nèi)部存儲(chǔ)介質(zhì)的設(shè)備節(jié)點(diǎn),會(huì)自動(dòng)動(dòng)態(tài)在/dev/by-name 中創(chuàng)建軟鏈
    接。例如:
root@TinaLinux:/# ll /dev/by-name/
drwxr-xr-x 2 root root 220 Mar 1 15:05 .
drwxr-xr-x 7 root root 3060 Mar 1 15:05 ..
lrwxrwxrwx 1 root root 12 Mar 1 15:05 UDISK -> /dev/nand0p9
lrwxrwxrwx 1 root root 12 Mar 1 15:05 boot -> /dev/nand0p2
lrwxrwxrwx 1 root root 12 Mar 1 15:05 env -> /dev/nand0p1
lrwxrwxrwx 1 root root 12 Mar 1 15:05 misc -> /dev/nand0p6
lrwxrwxrwx 1 root root 12 Mar 1 15:05 private -> /dev/nand0p8
lrwxrwxrwx 1 root root 12 Mar 1 15:05 pstore -> /dev/nand0p7
lrwxrwxrwx 1 root root 12 Mar 1 15:05 recovery -> /dev/nand0p5
lrwxrwxrwx 1 root root 12 Mar 1 15:05 rootfs -> /dev/nand0p3
lrwxrwxrwx 1 root root 12 Mar 1 15:05 rootfs_data -> /dev/nand0p4

因此,在fstab 也可以使用/dev/by-name/XXXX的形式匹配設(shè)備。塊設(shè)備如果有分區(qū),會(huì)形成分區(qū)設(shè)備節(jié)點(diǎn),以mmc、U 盤為例介紹設(shè)備節(jié)點(diǎn)名與分區(qū)的關(guān)系:

設(shè)備節(jié)點(diǎn)名含義
/dev/mmcblk0表示整個(gè)mmc 空間,包含所有分區(qū)
/dev/mmcblk0p1表示mmc 中的第1 個(gè)分區(qū)
/dev/mmcblk0p2表示mmc 中的第2 個(gè)分區(qū)
/dev/sda表示整個(gè)U 盤,包含所有分區(qū)
/dev/sda1表示U 盤內(nèi)的第1 個(gè)分區(qū)
/dev/sda2表示U 盤內(nèi)的第2 個(gè)分區(qū)

熱插拔塊設(shè)備分區(qū)有以下特殊情況。

  1. 塊設(shè)備沒有分區(qū)
    有一些特殊的TF 卡/U 盤沒有分區(qū),而是直接使用整個(gè)存儲(chǔ),表現(xiàn)為只有/dev/mmcblk1 和
    /dev/sda ,而沒有分區(qū)節(jié)點(diǎn)/dev/mmcblk1p1 和/dev/sda1 。此時(shí)需要直接掛載整個(gè)存儲(chǔ)
    設(shè)備,Tina 大部分方案都支持這種特殊情況。
  2. 塊設(shè)備有多個(gè)分區(qū)
    有一些特殊的TF 卡/U 盤被分為多個(gè)分區(qū),表現(xiàn)為存在多個(gè)/dev/mmcblk1p{1,2…} 和
    /dev/sda{1,2…}。默認(rèn)情況下,Tina 的fstab 配置為只支持掛載熱插拔存儲(chǔ)設(shè)備的第一個(gè)
    分區(qū)到/mnt/SDCARD 或者/mnt/exUDISK。

3.2 掛載點(diǎn)

3.2.1 默認(rèn)掛載設(shè)備目錄

Tina 中對(duì)常見的分區(qū)和熱插拔塊設(shè)備,有默認(rèn)的掛載點(diǎn)。

存儲(chǔ)介質(zhì)掛載節(jié)點(diǎn)設(shè)備節(jié)點(diǎn)備注
nor/nand/mmc/mnt/UDISK/dev/by-name/UDISK注1
TF 卡/mnt/SDCARD 或/mnt/extsd/dev/mmcblk{0,1}p1注2
U 盤/mnt/exUDISK/dev/sda1注3
SATA 磁盤/mnt/exUDISK/dev/sda1注3

說明

  1. /dev/by-name/UDISK 為sys_partition.fex 的UDISK 分區(qū)的軟連接。
  2. 當(dāng)無分區(qū)時(shí),默認(rèn)掛載整個(gè)TF 卡; 當(dāng)有1 個(gè)或多個(gè)分區(qū)時(shí),只掛載第一分區(qū)。
  3. 當(dāng)無分區(qū)時(shí),默認(rèn)掛載整個(gè)設(shè)備(/dev/sda),當(dāng)有1 個(gè)或多個(gè)分區(qū)時(shí),只掛載第一個(gè)分區(qū)。

3.2.2 新建掛載點(diǎn)

掛載文件系統(tǒng)需要有掛載點(diǎn)。
如果掛載點(diǎn)所在目錄可寫,則在掛載之前先創(chuàng)建目錄即可。

mkdir -p xxx

若掛載點(diǎn)所在目錄為只讀,則需要在制作文件系統(tǒng)時(shí)提前創(chuàng)建好。
如創(chuàng)建非空目錄,則在對(duì)應(yīng)方案的base-files 目錄創(chuàng)建。

procd-init: target/allwinner/方案/base-files
busybox-init: target/allwinner/方案/busybox-init-base-files

如創(chuàng)建空目錄,由于git 不管理空目錄,因此需在Makefile 中動(dòng)態(tài)創(chuàng)建,可仿照現(xiàn)有Makefile中創(chuàng)建UDISK 目錄的寫法。

procd-init: package/base-files/Makefile
busybox-init: package/busybox-init-base-files/Makefile

3.3 procd 啟動(dòng)下的掛載

procd 啟動(dòng)時(shí),自動(dòng)掛載由procd、fstools、fstab 配合完成。如果需要修改冷/熱掛載規(guī)則,只需要修改fstab 配置文件即可。
SDK 中,配置文件位于:

tina/target/allwinner/<方案名>/base-files/etc

若只是調(diào)試或臨時(shí)修改掛載規(guī)則,只需要修改小機(jī)端的配置文件:

/etc/config/fstab

3.3.1 fstab 編寫格式

fstab 由多個(gè)config 組成,每個(gè)config 的基本格式示例如下:

config ‘xxxx’
option xxxx ‘xx’
option xxxx ‘xx’
option xxxx ‘xx’

config 有3 種類型,分別是mount|global|swap 。Tina SDK 中沒使用swap,在本文中不做介紹。

3.3.2 global 類型config

global 類型的config 是全局配置,示例如下。

config 'global'
option anon_swap '0'
option anon_mount '0'
option auto_swap '1'
option auto_mount '1'
option delay_root '5'
option check_fs '1'

配置項(xiàng)的意義如下表:

配置名稱可選值意義
anon_mount0/1注1
anon_swap0/1swap 使用,此處省略
auto_mount0/1只適用于設(shè)置熱插拔是否自動(dòng)掛載塊設(shè)備
auto_swap0/1swap 使用,此處忽略
check_fs0/1建議配置為1,注2
delay_root1,2,3…注3

說明

  1. anon_mount: 當(dāng)fstab 中無匹配要掛載設(shè)備的uuid/label/device 屬性的配置節(jié)時(shí), 是否采用默認(rèn)掛載為
    /mnt/“$device-name”。
  2. check_fs: 是否在掛載前用/usr/sbin/e2fsck 檢查文件系統(tǒng)一致性(只適用于ext 系統(tǒng))。
  3. delay_root: 對(duì)應(yīng)fstab 中target 為”/” 或”/overlay” 的設(shè)備節(jié)點(diǎn)不存在時(shí),最長等待delay_root 秒。

3.3.3 mount 類型config

mount 類型的config 是具體的設(shè)備掛載配置,示例如下

config 'mount'
option target '/mnt/UDISK'
option device '/dev/by-name/UDISK'
option options 'rw,sync'
option enabled '1'

配置項(xiàng)的意義如下表:

配置名稱意義備注
target掛載點(diǎn)必須是絕對(duì)路徑,必須有效
device設(shè)備名通過設(shè)備名指定待掛載的設(shè)備,注1
uuid設(shè)備UUID通過fs 的UUID 指定待掛載的設(shè)備,注1
label設(shè)備label通過fs 的label 指定待掛載的設(shè)備,注1
enabled是否使能該節(jié)點(diǎn)是否有效(0/1)
options掛載屬性例如只讀掛載等,注2
  1. device/uuid/label 是匹配掛載的設(shè)備,三者中至少要有一個(gè)有效。

  2. 默認(rèn)掛載支持的屬性如下表:

配置名稱意義缺省值
ro / rw只讀/ 可讀寫rw
nosuid / suid忽略suid/sgid 的文件屬性suid
nodev / dev不允許/允許訪問設(shè)備文件dev
noexec / exec不允許/允許執(zhí)行程序exec
sync / async同步/異步寫入async
mand / nomand允許/不允許強(qiáng)制鎖nomand
irsync同步更新文件夾無效
noatime / atime不更新/更新訪問時(shí)間(atime)atime
nodiratime / diratime不更新/更新目錄訪問時(shí)間(atime)diratime
relatime / norelatime允許/不允許根據(jù)ctime/mtime 更新actime norelatime
strictatime禁止根據(jù)內(nèi)核行為來更新atime, 但允許用戶空間修改無效

3.4 busybox 啟動(dòng)下的掛載

busybox 啟動(dòng)時(shí),通過pseudo_init 和rcS 完成大部分默認(rèn)的掛載工作。

存儲(chǔ)節(jié)點(diǎn)掛載路徑用途
/dev/by-name/UDISK/mnt/UDISK用戶數(shù)據(jù)
/dev/by-name/rootfs_data/overlay作為overlay 使得rootfs 可寫
/dev/mmcblk{0,1}p1/mnt/SDCARD 或/mnt/extsdTF 卡
/dev/sda1/mnt/exUDISKU 盤

busybox 啟動(dòng)使用默認(rèn)掛載配置即可,如果需要修改,需要自行修改腳本。

tina/package/busybox-init-base-files/busybox-init-base-files/usr/bin/hotplug.sh

3.5 掛載文件系統(tǒng)

在分區(qū)表中增加的分區(qū)默認(rèn)是空分區(qū),如需掛載成文件系統(tǒng)使用,則首先需要在分區(qū)中寫入一個(gè)文件系統(tǒng)。
方式一,在PC 端預(yù)先生成好一個(gè)文件系統(tǒng),并在分區(qū)表中指定為download_file,則啟動(dòng)后可直接掛載。例如rootfs 分區(qū)就是在PC 端制作好文件系統(tǒng),燒錄時(shí)寫入rootfs 分區(qū)。
方式二,在小機(jī)端進(jìn)行格式化。例如UDISK 分區(qū)就是在第一次啟動(dòng)時(shí),由啟動(dòng)腳本進(jìn)行格式化??蛻艨勺孕性谀骋粏?dòng)腳本或應(yīng)用中調(diào)用格式化工具(mkfs.xxx)進(jìn)行格式化。如需參考,可仿照UDISK 分區(qū)的格式化:

procd-init: package/base-files/files/lib/preinit/79_format_partition
busybox-init: package/busybox-init-base-files/files/pseudo_init

3.5.1 注意事項(xiàng)

一些格式化工具并未默認(rèn)選中,需要時(shí)請(qǐng)自行在make menuconfig 界面配置。部分文件系統(tǒng)對(duì)分區(qū)大小有最低要求,如ext4,ubifs,如果在小機(jī)端調(diào)用格式化分區(qū)時(shí)報(bào)錯(cuò),可根據(jù)報(bào)錯(cuò)信息提示增大分區(qū)。
對(duì)于private 分區(qū)默認(rèn)為空,使用DragonSN 工具寫號(hào)后,則為vfat 格式的文件系統(tǒng)。對(duì)于ubi 方案來說,如果需要使用基于塊設(shè)備的文件系統(tǒng),則需要在ubi 之上模擬塊設(shè)備。在用戶空間可調(diào)用ubiblock 工具完成,注意這樣模擬出的塊設(shè)備是只讀的,如需可寫建議直接使用
ubifs。

詳見后文ubi 方案特殊說明。

4 文件系統(tǒng)支持情況

存儲(chǔ)介質(zhì)jffs2squashfsext4vfatntfsexfatubifs
(NFTL) nandNYYYYNN
(UBI) spinandNYY(ro)Y(ro)Y(ro)NY
mmcNYYYYNN
norYYNNNNN
TF 卡NNYYYNN
U 盤NNYYYNN

說明

  1. (ro) 表示只能實(shí)現(xiàn)只讀: ubi 卷可通過模擬塊設(shè)備,實(shí)現(xiàn)塊文件系統(tǒng)的讀,但不支持寫。
  2. vfat(fat32)使用內(nèi)核原生的支持,exfat 需要在Linux-5.7 后社區(qū)才正式支持,因此此處標(biāo)注為不支持。
  3. ntfs 依賴于第三方工具ntfs-3g。
  4. TF 卡/U 盤等,建議使用vfat 實(shí)現(xiàn)Window/Linux/MacOS 的最大兼容參考文章《多平臺(tái)大型文件系統(tǒng)比較》。
  5. vfat/ntfs/exfat 等Window 文件系統(tǒng),不建議用做嵌入式存儲(chǔ),除非您能保證其掉電安全和移植文件系統(tǒng)修復(fù)工具。

警告
關(guān)于文件系統(tǒng)的選擇,有以下幾點(diǎn)需要注意:

  1. 全志NFTL nand 可使用塊文件系統(tǒng)(ext4) 全志在驅(qū)動(dòng)中實(shí)現(xiàn)磨損平衡和壞塊管理,向上呈現(xiàn)為塊設(shè)
    備。因此可支持ext4,不需要且不支持常見的flash 文件系統(tǒng)(jffs2/yaffs/ubifs 等)。
  2. 為了保證掉電不變磚,根文件系統(tǒng)務(wù)必只讀(squashfs),或者ext4 掛載為ro 模式。
  3. ext4/ubifs 等文件系統(tǒng)分區(qū)大小必須足夠大,以確保能正確創(chuàng)建日志塊,否則有掉電變磚風(fēng)險(xiǎn)分區(qū)大小
    請(qǐng)參考章節(jié)分區(qū)大小與對(duì)齊。

4.1 ext4 與日志

4.1.1 ext4 的日志

與服務(wù)器等長期穩(wěn)定供電的情況不同,嵌入式設(shè)備隨時(shí)有掉電的可能。不管在任意時(shí)間掉電,文件系統(tǒng)都需要保持一致性,換句話說,保證文件不會(huì)因?yàn)榈綦妬G失。如果文件系統(tǒng)只讀,則不需要日志。日志只是確保寫的安全。

說明
什么是文件系統(tǒng)的一致性?
文件系統(tǒng)元數(shù)據(jù)塊記錄了有什么文件,數(shù)據(jù)塊則保存了實(shí)際的文件內(nèi)容。一致性則表示,元數(shù)據(jù)塊記錄了存在某個(gè)文件,必定存
在對(duì)應(yīng)的數(shù)據(jù)塊,換句話說,就是保證元數(shù)據(jù)和數(shù)據(jù)的一致。
如果出現(xiàn),元數(shù)據(jù)記錄文件A 存在,但文件A 的數(shù)據(jù)塊是無效的,或者明明數(shù)據(jù)塊是有效的,但元數(shù)據(jù)并沒任何記錄,導(dǎo)致系
統(tǒng)并不知道文件存在,就出現(xiàn)了文件系統(tǒng)的不一致。

警告
保證文件不丟失,只保證之前寫入的文件數(shù)據(jù)正常,而非正在寫,且因?yàn)榈綦妼?dǎo)致沒寫完整的文件。對(duì)大多數(shù)文
件系統(tǒng)而言,更多時(shí)候會(huì)直接丟棄這沒寫完整的文件以保證一致性。

ext4 通過日志的形式保證文件系統(tǒng)一致性。其支持3 種日志模式:

日志模式原理特點(diǎn)
journal元數(shù)據(jù)與數(shù)據(jù)都寫入日志最安全,但性能最慢
writeback只有元數(shù)據(jù)寫入日志,但不保證數(shù)據(jù)先落盤性能最快,但最不安全
ordered只有元數(shù)據(jù)寫入日志,且保證數(shù)據(jù)先落盤,元數(shù)據(jù)后落盤折中,默認(rèn)方案

考慮安全和性能的折中,建議使用ordered 的日志模式。系統(tǒng)默認(rèn)使用的就是ordered 模式。我們在mount 命令中顯示的掛載參數(shù)可顯示使用的哪種日志。

$mount
/dev/by-name/UDISK on /mnt/UDISK type ext4 (rw,....,data=ordered)

4.1.2 分區(qū)大小與日志

有時(shí)候分區(qū)太小,系統(tǒng)會(huì)默認(rèn)把日志功能關(guān)閉??梢酝ㄟ^以下方法判斷:

$dumpe2fs <分區(qū)or 鏡像文件>
...
Filesystem features: has_journal ...
...
Journal backup: inode blocks
Journal features: (none)
日志大小: 1024k
Journal length: 1024
Journal sequence: 0x00000001
Journal start: 0
...

在Filesystem features 中有has_journal 的標(biāo)志表示支持日志。在Jorunal 片段中也詳細(xì)描述了日志塊的大小等信息。
如果創(chuàng)建的文件系統(tǒng)沒有日志,對(duì)大多數(shù)用戶而言,擴(kuò)大分區(qū)大小是最簡單的做法。專業(yè)的做法可以通過縮小塊大小,取消預(yù)留塊等方式為日志騰挪出空間。
按以往經(jīng)驗(yàn),對(duì)小容量(<100M) 的存儲(chǔ)而言,在資源文件之外預(yù)留3-5M 的空間用于文件系統(tǒng)的元數(shù)據(jù)即可。

4.1.3 修復(fù)ext4

ext4 文件系統(tǒng)每次重啟后,建議都進(jìn)行一次修復(fù),確保文件系統(tǒng)穩(wěn)定。
修復(fù)可以參考以下命令:

e2fsck -y <分區(qū)>

4.1.4 修復(fù)fat

TF 卡掛載fat 文件系統(tǒng),fat 文件系統(tǒng)不是日志型文件系統(tǒng),在掉電、帶電插拔等場景下不能保證文件系統(tǒng)數(shù)據(jù)的安全,所以建議啟動(dòng)都進(jìn)行一次修復(fù)。修復(fù)可以參考以下命令:

fsck_msdos -pfS /dev/mmcblk0p1

如章節(jié)global 類型config中描述,如果使用procd 引導(dǎo)啟動(dòng),在fstab 中使能check_fs,也可實(shí)現(xiàn)在掛載前自動(dòng)修復(fù)。

5 UBI VS. NFTL

對(duì)nand 存儲(chǔ)介質(zhì),全志有兩套解決方案,分別是NFTL spi/raw nand 和UBI spi nand。UBI 存儲(chǔ)方案常用于小容量spinand,其實(shí)現(xiàn)原理跟NFTL 存儲(chǔ)方案完全不同。

5.1 NFTL Nand

這是全志實(shí)現(xiàn)的不開源的Nand 驅(qū)動(dòng),NFTL 全稱為NAND Flash Translation Layer,其可實(shí)現(xiàn)屏蔽Nand 的特性,對(duì)上呈現(xiàn)為塊設(shè)備。
我們常見的mmc 設(shè)備也是塊設(shè)備,可以簡單理解為,MMC = Nand Flash + 控制器+NFTL。所以通過全志的NFTL nand 驅(qū)動(dòng)后,我們可以像mmc 設(shè)備一樣,以塊設(shè)備操作Nand。
例如,上層可以直接裸讀寫塊設(shè)備,常見的ota 更新也是基于這樣的實(shí)現(xiàn):

dd if=boot.fex of=/dev/by-name/boot

技巧

詳細(xì)的OTA 方法,請(qǐng)參見OTA 相關(guān)文檔。

全志的NFTL Nand 驅(qū)動(dòng)中,預(yù)留一部分空間做算法和關(guān)鍵數(shù)據(jù)保存。預(yù)留空間大致為1/10 ~1/8 的可用空間。這里的可用空間是指剔除出廠壞塊之外的空間。由于每一顆Flash 的出廠壞塊數(shù)量不盡相同,因此最終呈現(xiàn)給用戶的可用空間不盡相同。用戶也不需要擔(dān)心使用過程中出現(xiàn)的壞塊導(dǎo)致用戶可用空間變小,在算法實(shí)現(xiàn)中,使用壞塊會(huì)體現(xiàn)在預(yù)留空間而不是用戶空間。
此外,Nand 的磨損平衡、壞塊管理等特性全由NFTL 驅(qū)動(dòng)實(shí)現(xiàn)。換句話說,驅(qū)動(dòng)保證用戶數(shù)據(jù)的穩(wěn)定,用戶可將其按塊設(shè)備使用。

5.2 UBI (spi) Nand

當(dāng)前UBI 方案僅適用于小容量spinand。
UBI 方案是社區(qū)普遍使用的Flash 存儲(chǔ)方案,其構(gòu)建在mtd 設(shè)備之上,由UBI 子系統(tǒng)屏蔽Nand 特性,對(duì)接UBIFS 文件系統(tǒng)。其層次結(jié)構(gòu)由上往下大致如下:

層次層級(jí)功能
0 (最上層)UBIFSubifs 文件系統(tǒng)
1 UBI子系統(tǒng)Nand 特性管理
2MTD 子系統(tǒng)封裝Flash,向上提供統(tǒng)一接口
3 (最下層)Flash具體的Flash 驅(qū)動(dòng)

我們把MTD 分區(qū)稱為物理分區(qū),把UBI 卷(分區(qū)) 成為邏輯分區(qū),因?yàn)?br /> ? MTD 分區(qū)是按Flash 的物理地址區(qū)間劃分分區(qū)
? UBI 卷(分區(qū)) 是動(dòng)態(tài)映射的區(qū)間
全志的UBI 方案中,創(chuàng)建了這些MTD 物理分區(qū):

分區(qū)名大小作用
boot04/8 個(gè)物理塊存放boot0
uboot4/20M存放uboot
secure storage8 個(gè)物理塊存放關(guān)鍵數(shù)據(jù)
pstore512K奔潰日志轉(zhuǎn)存
sys剩余空間提供給ubi 子系統(tǒng)劃分邏輯分區(qū)

驅(qū)動(dòng)會(huì)在sys 的MTD 物理分區(qū)上根據(jù)sys_partition.fex構(gòu)建UBI 邏輯分區(qū)(卷)。
UBI 設(shè)備向上呈現(xiàn)為字符設(shè)備,無法直接使用諸如ext4 這樣基于塊設(shè)備的文件系統(tǒng)。但UBI 子系統(tǒng)支持模擬只讀的塊設(shè)備,即把UBI 邏輯卷模擬成只讀的塊設(shè)備。基于此,可以做到根文件系統(tǒng)依然使用squashfs 這樣的塊文件系統(tǒng)。
社區(qū)為UBI 設(shè)備專門設(shè)計(jì)了ubifs 文件系統(tǒng)。經(jīng)過驗(yàn)證,其配合UBI 子系統(tǒng)可保證數(shù)據(jù)掉電安全以及提供通用文件系統(tǒng)所有功能,甚至還提供文件系統(tǒng)壓縮功能。
除此之外,UBI 設(shè)備更新(OTA 更新)也不能直接裸寫設(shè)備,需要通過ubiupdateval 命令更新。
技巧:詳細(xì)的OTA 方法,請(qǐng)參見OTA 相關(guān)文檔。

5.3 ubi 相關(guān)工具

5.3.1 ubinfo

輸出指定ubi 設(shè)備信息。
例子:

ubinfo /dev/by-name/rootfs #查看rootfs卷的信息
ubinfo -a #查看所有卷的信息

可參考總?cè)萘空f明

5.3.2 ubiupdatevol

更新指定卷上的數(shù)據(jù)。
例子:

ubiupdatevol -t /dev/by-name/boot #清除boot卷的數(shù)據(jù)
ubiupdatevol /dev/by-name/boot /tmp/boot.img #將/tmp/boot.img寫到boot卷,卷上原有數(shù)據(jù)會(huì)完全丟失

可參考總?cè)萘空f明

可參考模擬塊設(shè)備

5.3.3 ubiblock

基于一個(gè)ubi 卷,生成模擬的只讀塊設(shè)備
例子:

ubiblock -c /dev/by-name/test #將test卷生成一個(gè)塊設(shè)備節(jié)點(diǎn)

可參考模擬塊設(shè)備

5.3.4 其他

在tina 方案上,燒錄固件時(shí)已經(jīng)完成mtd 和ubi 卷的創(chuàng)建,啟動(dòng)時(shí)自動(dòng)attach 并掛載對(duì)應(yīng)的分區(qū),無需再自行處理。因此以下命令一般不會(huì)用到。
ubiformat: 將裸mtd 格式化成ubi
ubiattach: 將mtd 關(guān)聯(lián)到ubi
ubidetach: 將ubi 與mtd 解除關(guān)聯(lián)ubimkvol: 創(chuàng)建ubi 卷
ubirmvol: 移除ubi 卷

6 rootfs_data 及UDISK

6.1 overlayfs 簡介

Tina 默認(rèn)根文件系統(tǒng)格式使用squashfs 格式,這是一種只讀壓縮的文件系統(tǒng)。很多應(yīng)用則需要文件系統(tǒng)可寫,特別是/etc 等存放較多配置文件的目錄,為了滿足可寫的需求,Tina 默認(rèn)使用overlayfs 技術(shù)。overlayfs 是一種堆疊文件系統(tǒng),可以將底層文件系統(tǒng)和頂層文件系統(tǒng)的目錄進(jìn)行合并呈現(xiàn)。

6.2 使用rootfs_data 作為overlayfs

Tina 常用的方式是專門劃分一個(gè)rootfs_data 分區(qū), 先格式化成可寫的文件系統(tǒng)(如ext4/ubifs), 再進(jìn)一步掛載為overyfs, 成為新的根, 讓上層應(yīng)用認(rèn)為rootfs 是可寫的。
rootfs_data 分區(qū)的大小就決定了應(yīng)用能修改多少文件。具體原理和細(xì)節(jié)請(qǐng)參考網(wǎng)上公開資料,此處僅舉簡單例子輔助理解。

  1. 底層(即rootfs 分區(qū)的文件系統(tǒng))不存在文件A,應(yīng)用創(chuàng)建A,則A 只存在于上層(即
    rootfs_data 分區(qū))。
  2. 底層存在文件B,應(yīng)用刪除B,則B 仍然存在于底層,但上層會(huì)創(chuàng)建一個(gè)特殊文件屏蔽掉,導(dǎo)
    致對(duì)應(yīng)用來說B 就看不到了,起到刪除的效果。
  3. 底層存在文件C,上層修改C,則C 會(huì)先被整個(gè)拷貝到上層,C 本身多大就需占用多大的上
    層空間,在這個(gè)基礎(chǔ)上應(yīng)用對(duì)上層的C 進(jìn)行修改。
    基于以上理解,可按需配置rootfs_data 的大小。一般開發(fā)期間會(huì)配置得較大,量產(chǎn)時(shí)可減小
    (考慮實(shí)際只會(huì)修改少量配置文件)甚至去除(需要確認(rèn)所有應(yīng)用均不依賴rootfs 可寫)。

6.3 使用UDISK 作為overlayfs

如果希望overlayfs 的空間盡可能較大,也可考慮直接使用UDISK 分區(qū)作為上層文件系統(tǒng)空間。
可將target/allwinner/xxx/base-files/etc/config/fstab 中的rootfs_data 分區(qū)及UDISK 分區(qū)的掛載配置disable 掉。

config 'mount'option target '/overlay'option device '/dev/by-name/rootfs_data'option options 'rw,sync,noatime'option enabled '0' #此行改成0
config 'mount'option target '/mnt/UDISK'option device '/dev/by-name/UDISK'option options 'rw,async,noatime'option enabled '0'

再新增一個(gè)配置,將UDISK 直接掛載到/overlay 目錄。

config 'mount'option target '/overlay'option device '/dev/by-name/UDISK'option options 'rw,sync,noatime'option enabled '1'

6.4 如何清空rootfs_data 和UDISK

出于恢復(fù)出廠設(shè)置或其他需要,有時(shí)需要清空rootfs_data 和UDISK。
一般不建議在文件系統(tǒng)仍處于掛載狀態(tài)時(shí)直接操作對(duì)應(yīng)的底層分區(qū),因此建議需要清空時(shí),不要直接操作對(duì)應(yīng)塊設(shè)備,而是先設(shè)置標(biāo)志并重啟,再在掛載對(duì)應(yīng)分區(qū)前的啟動(dòng)腳本中檢測到對(duì)應(yīng)標(biāo)志后,對(duì)分區(qū)進(jìn)行重新格式化。
當(dāng)前79_format_partition 中實(shí)現(xiàn)了一個(gè)clean_parts 功能, 會(huì)檢測env 分區(qū)中的parts_clean 變量并清空對(duì)應(yīng)分區(qū)的頭部。清空后,rootfs_data 和UDISK 分區(qū)會(huì)自動(dòng)重新觸發(fā)格式化。

# to clean rootfs_data and UDISK, please run
fw_setenv parts_clean rootfs_data:UDISK
reboot

具體實(shí)現(xiàn)請(qǐng)查看

package/base-files/files/lib/preinit/79_format_partition

7 關(guān)鍵數(shù)據(jù)保護(hù)

設(shè)備上保存的一些關(guān)鍵的數(shù)據(jù),例如mac,SN 號(hào)等,一般要求在重新刷機(jī)時(shí)不丟失。以下介紹刷機(jī)數(shù)據(jù)不丟失的解決方案。

7.1 邏輯分區(qū)保護(hù)方案

7.1.1 分區(qū)設(shè)置

此處的邏輯分區(qū),是指在分區(qū)表(sys_partition.fex/sys_partition_nor.fex) 中定義的分區(qū)。名字為private 的分區(qū)會(huì)特殊處理,默認(rèn)刷機(jī)數(shù)據(jù)不丟失。
其他名字的分區(qū),如果指定keydata=0x8000 屬性,則刷機(jī)數(shù)據(jù)不丟失。對(duì)于private 分區(qū)或設(shè)置了keydata=0x8000 屬性的分區(qū),請(qǐng)勿設(shè)置downloadfile。

7.1.2 實(shí)現(xiàn)原理

對(duì)private 分區(qū)(配置了keydata=0x8000 屬性同理) 保護(hù)的方式是,擦除之前先申請(qǐng)一片內(nèi)存,然后根據(jù)flash 中的舊分區(qū)表,讀出private 分區(qū)內(nèi)容。
接著進(jìn)行擦除,然后再按照新的分區(qū)表,將private 分區(qū)內(nèi)容寫回flash 上新分區(qū)所在位置。

7.1.3 常見用法

  1. 使用全志的DragonSN 工具,選擇私有key 模式,將key 寫入private 分區(qū)。寫入后private分區(qū)默認(rèn)會(huì)是一個(gè)vfat 文件系統(tǒng),啟動(dòng)后掛載/dev/by-name/private,即可讀出key。DragonSN 的具體用法請(qǐng)參考工具自帶文檔。
  2. 不使用DragonSN 工具, 由應(yīng)用自行負(fù)責(zé)寫入數(shù)據(jù)和讀出數(shù)據(jù), 直接在用戶空間操作/dev/by-name/private 節(jié)點(diǎn)即可。量產(chǎn)時(shí)可自行開發(fā)PC 端工具,通過adb 命令來完成key 的寫入。

7.1.4 ubi 方案特殊說明

7.1.4.1 模擬塊設(shè)備

對(duì)于nand nftl 方案,emmc 方案,nor 方案,邏輯分區(qū)是對(duì)應(yīng)到一個(gè)塊設(shè)備,即對(duì)于private分區(qū),可以直接讀寫/dev/by-name/private 節(jié)點(diǎn),也可以借助DragonSN 工具制作成一個(gè)vfat文件系統(tǒng),再掛載使用,掛載后文件系統(tǒng)是可讀寫的。
但對(duì)于nand ubi 方案,邏輯分區(qū)是對(duì)應(yīng)到ubi 卷,由于ubi 的特性,無法再直接寫數(shù)據(jù)到/dev/by-name/private 節(jié)點(diǎn),需要通過ubiupdatevol 工具來更新卷,或者自行在應(yīng)用中按照ubi 卷更新步驟操作。
當(dāng)基于ubi 卷構(gòu)建vfat 文件系統(tǒng)時(shí),需要先基于ubi 卷模擬塊設(shè)備,且掛載上的vfat 文件系統(tǒng)是只讀的。操作示例如下。

#查看private分區(qū)對(duì)應(yīng)的ubi節(jié)點(diǎn)
root@TinaLinux:/# ll /dev/by-name/private
lrwxrwxrwx 1 root root 11 Jan 1 00:00 /dev/by-name/private -> /dev/
ubi0_4
#創(chuàng)建模擬的塊設(shè)備
root@TinaLinux:/# ubiblock -c /dev/ubi0_4
block ubiblock0_4: created from ubi0:4(private)
#掛載
root@TinaLinux:/# mkdir /tmp/private
root@TinaLinux:/# mount -t vfat /dev/ubiblock0_4 /tmp/private/
#可以讀取內(nèi)容
root@TinaLinux:/# ls /tmp/private/
ULI magic.bin
#查看掛載情況,為ro
root@TinaLinux:/# mount | grep private
/dev/ubiblock0_4 on /tmp/private type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,
iocharset=iso8859-1,shortname=mixed,errors=remount-ro)

7.1.4.2 在設(shè)備端制作vfat 鏡像

由于ubifs 需占用17 個(gè)LEB,比較占空間,對(duì)于只在工廠一次性寫入信息,后續(xù)只讀的場景,一種可考慮的方案是使用vfat 文件系統(tǒng)。
首先選上kernel 的loopback 支持:

make kernel_menuconfig 選上Device Drivers --> [*] Block Devices --> <*>Loopback device
support

分區(qū)表中建立分區(qū),假設(shè)為test 分區(qū)隨后可以在小機(jī)端準(zhǔn)備一個(gè)vfat 鏡像:

dd if=/dev/zero of=/mnt/UDISK/test.img bs=1M count=1
mkfs.vfat /mnt/UDISK/test.img
mkdir -p /tmp/test
mount /mnt/UDISK/test.img /tmp/test
此時(shí)可向/tmp/test 寫入文件
umount /tmp/test

將鏡像寫入卷中:

ubiupdatevol /dev/by-name/test /mnt/UDISK/test

后續(xù)按上文介紹的方法,使用模擬塊設(shè)備掛載,注意使用模擬塊設(shè)備掛載后就是只讀的了。

7.1.5 可能造成數(shù)據(jù)丟失的情況

出現(xiàn)以下情況,會(huì)導(dǎo)致private 分區(qū)數(shù)據(jù)丟失。

  1. 配置了強(qiáng)制擦除,例如sys_config.fex 中配置了eraseflag = 0x11。
  2. 無法讀取flash 上的分區(qū)表或private 分區(qū)。這個(gè)可能的原因包括flash 上的數(shù)據(jù)被破壞了
    等。
  3. 新的分區(qū)表不包含private 分區(qū)。
  4. 在燒錄過程中掉電。如上所述,燒錄時(shí)是讀出-> 擦除-> 寫回,在擦除之后,寫回之前掉電,則數(shù)據(jù)丟失。
    檢測到private 分區(qū),開始執(zhí)行保護(hù)private 分區(qū)的代碼,但執(zhí)行過程中出錯(cuò),如malloc 失敗,private 無法讀取等,則會(huì)導(dǎo)致燒錄失敗。出現(xiàn)malloc 失敗問題一般是因?yàn)榘遄由蠠浟薃ndroid固件。因?yàn)榘沧康膒rivate 分區(qū)比較大,而tina 的uboot 分配給malloc 的空間比較小。
    這個(gè)時(shí)候,需要打包一份不保護(hù)private 分區(qū)的tina 固件先進(jìn)行一次燒錄,即可解決問題。具體的:將sys_config.fex 的eraseflag 改為0x11,強(qiáng)制擦除?;蛘吲R時(shí)移除sys_partition.fex中的private 分區(qū)。

7.2 物理區(qū)域保護(hù)方案

另一種保護(hù)數(shù)據(jù)不丟失的思路是,在flash 上劃定一塊物理區(qū)域,燒錄時(shí)默認(rèn)不擦除。在Tina 上實(shí)現(xiàn)的secure storage 區(qū)域即具有這種特性。secure storage 區(qū)域用于保存key,可代替private 分區(qū),理論上更為安全(被燒錄時(shí)誤擦除和被別的應(yīng)用誤寫的可能性較低)。

7.2.1 nand nftl 方案實(shí)現(xiàn)

nand nftl 方案中,預(yù)留了一塊物理區(qū)域,用于secure storage。這塊區(qū)域不是邏輯分區(qū),用戶空間不可見。燒錄時(shí)不會(huì)擦除這塊區(qū)域。在用戶空間讀寫secure storage 需要使用ioctl,由內(nèi)核nand 驅(qū)動(dòng)來協(xié)助完成。

7.2.2 nand ubi 方案實(shí)現(xiàn)

nand ubi 方案中,預(yù)留了一塊物理區(qū)域,用于secure storage,對(duì)上表現(xiàn)為一個(gè)mtd 分區(qū)。用戶空間可見。燒錄時(shí)不會(huì)擦除這塊區(qū)域。在用戶空間讀寫secure storage 需要使用ioctl,由內(nèi)核來協(xié)助完成。理論上也可以直接讀寫mtd 設(shè)備節(jié)點(diǎn),但不推薦,使用這種方式應(yīng)用需要自行處理壞塊等問題。

7.2.3 emmc 方案實(shí)現(xiàn)

預(yù)留了一塊物理區(qū)域,默認(rèn)是偏移6M-6.25M 的區(qū)域,作為secure storage。在用戶空間讀寫,可以直接通過mmcblk0 節(jié)點(diǎn)讀寫指定偏移。

7.2.4 nor 方案實(shí)現(xiàn)

暫未實(shí)現(xiàn)。

7.2.5 常見用法

  1. 使用全志的DragonSN 工具,選擇安全key 模式,將key 寫入secure storage 區(qū)域。啟動(dòng)后在用戶空間調(diào)用庫讀出key。DragonSN 的具體用法請(qǐng)參考工具自帶文檔。
  2. 不使用DragonSN 工具,由應(yīng)用自行在用戶空間調(diào)用庫寫入數(shù)據(jù)和讀出數(shù)據(jù)。量產(chǎn)時(shí)可自行開發(fā)PC 端工具,通過adb 命令來完成key 的寫入。

7.2.6 secure storage 格式

secure storage 有預(yù)設(shè)的格式,簡單總結(jié)如下
? secure storage 總大小為256KB,因?yàn)橛袀浞?#xff0c;所以實(shí)際能用128KB。
? 128KB 分為32 個(gè)item, 即每個(gè)item 是4KB。
? item0 用作secure_sotrage_map,所以用戶能用的實(shí)際為31 個(gè)item。
? 每個(gè)item 內(nèi)部為鍵值對(duì)的格式,包含CRC 校驗(yàn),其中用戶可存儲(chǔ)的key 長度最多為3KB。
? secure_storage_map 中是以“name:length” 的格式保存所有item 的信息,所以所有item的“name:length” 字符串長度總和不能超過secure_storage_map 中data 的長度。一般而言,31 個(gè)3KB 的key 可以滿足需求,如果無法滿足,例如需要更多數(shù)量的key,則一種解決方式是上層應(yīng)用自行將多個(gè)key 拼接起來,只要總大小不超過3KB 即可當(dāng)成一個(gè)key 寫入
secure storage。讀出時(shí)應(yīng)用自行反向解析出目標(biāo)key 即可。

7.2.7 在uboot 中讀寫

基于以上介紹的格式,uboot 中封裝了pst 命令。

pst - read data from secure storageerase flag in secure storage
Usage:
pst pst read|erase [name]
pst read, then dump all data
pst read name, then dump the dedicate data
pst write name, string, write the name = string
pst erase, then erase all secure storage data
pst erase key_burned_flag, then erase the dedicate data

7.2.8 在用戶空間讀寫

Tina 提供了讀寫庫。

make menuconfig 選中 Allwinner --> <*> libsec_key --> [*] Enable secure storage key support

如果選上demo,則會(huì)編譯出demo 程序sec_key_test。

root@TinaLinux:/# sec_key_test -h
-w <name> <data>: write key to sst and private
-r <name> <data>: read key from sst or private
-t 0: write some key to secure storage
-t 1: repetitve read + verify some key from secure storage
-t 2: repetitve write + verify some key from secure storage
-t 3: verify some key from secure storage
-t 4: write some key to private
-t 5: repetitve read + verify some key from private
-t 6: repetitve write + verify some key from private
-t 7: verify some key from private
-l : list
-d : printf hex
-h : help

更詳細(xì)的使用方式請(qǐng)參考:

tina/package/allwinner/libkey/readme.txt

7.3 secure storage 區(qū)域與private 分區(qū)比較

刷機(jī)不丟失的特性:
? private 分區(qū)每次刷機(jī),是先讀出到dram,擦除flash,再寫入flash。刷機(jī)中途掉電可能丟失
? secure storage 則是刷機(jī)過程完全不會(huì)擦除。理論上secure storage 的數(shù)據(jù)更安全。

用戶空間誤操作的可能:
? private 分區(qū)可以用常規(guī)分區(qū)更新命令清除掉。
? secure storage 需要通過ioctl 專用接口訪問。

數(shù)據(jù)格式:
? private 分區(qū)可以裸分區(qū)讀寫,也可以格式化成文件系統(tǒng)。
? secure storage 已限制為鍵值對(duì),key 的長度也有限制。

存放位置:
? private 分區(qū)大小由分區(qū)表配置,是一個(gè)可見的普通分區(qū)。
? secure storage 是flash 上的保留區(qū)域,大小固定,分區(qū)表中不可見。

? private 分區(qū)沒有備份,請(qǐng)避免寫入時(shí)掉電?;蛘咦孕性趐rivate 分區(qū)中構(gòu)建備份。
? secure storage 默認(rèn)是雙備份。

在uboot 訪問:
? private 分區(qū),uboot 通過通用的讀寫flash 接口或文件系統(tǒng)接口訪問,取決于數(shù)據(jù)格式。
? sectre storage 區(qū)域,有固定格式,通過uboot 提供的secure storage 專用接口訪問。

校驗(yàn):
? private 分區(qū)如果是裸數(shù)據(jù),是否校驗(yàn)由應(yīng)用自行處理。如果是文件系統(tǒng),則由文件系統(tǒng)特性決定。
? secure storage 格式中帶了crc 校驗(yàn)。

http://www.risenshineclean.com/news/56916.html

相關(guān)文章:

  • 499元做網(wǎng)站微信營銷技巧
  • 珠海市網(wǎng)站建設(shè)開發(fā)公司海南百度推廣公司
  • 網(wǎng)站建設(shè)的欄目百度推廣一個(gè)月費(fèi)用
  • 畢業(yè)設(shè)計(jì)網(wǎng)站做啥長沙建設(shè)網(wǎng)站制作
  • 如何建立一個(gè)網(wǎng)站放視頻適合小學(xué)生的新聞事件
  • 做二手網(wǎng)站有哪些2021百度熱搜年度榜
  • 佛山高端網(wǎng)站建設(shè)比較火的推廣軟件
  • 專業(yè)網(wǎng)站制作技術(shù)程序員培訓(xùn)機(jī)構(gòu)哪家好
  • 海安建設(shè)局網(wǎng)站刷評(píng)論網(wǎng)站推廣
  • 寧波趨勢信息科技有限公司網(wǎng)站seo排名優(yōu)化工具在線
  • 微信小程序萬能開掛器seo營銷推廣服務(wù)公司
  • wordpress不跳轉(zhuǎn)網(wǎng)站快速排名優(yōu)化價(jià)格
  • 水利部精神文明建設(shè)指導(dǎo)委員會(huì)網(wǎng)站免費(fèi)關(guān)鍵詞挖掘網(wǎng)站
  • 如何用kali做網(wǎng)站滲透廣州網(wǎng)站優(yōu)化外包
  • 網(wǎng)站引導(dǎo)頁在線做開網(wǎng)站怎么開
  • 網(wǎng)站成立時(shí)間查詢抖音關(guān)鍵詞搜索指數(shù)
  • 北京國稅局網(wǎng)站做票種核定時(shí)seo國外推廣軟件
  • 政府網(wǎng)站建設(shè)應(yīng)該注意百一度一下你就知道
  • 網(wǎng)站空間是指什么寧波seo公司排名
  • 網(wǎng)站群管理平臺(tái)建設(shè)谷歌google官網(wǎng)下載
  • 奇藝廣州網(wǎng)站建設(shè) 熊掌號(hào)汕尾網(wǎng)站seo
  • thinkphp做網(wǎng)站快刷網(wǎng)站
  • 國外有什么優(yōu)秀的網(wǎng)站推薦免費(fèi)seo視頻教學(xué)
  • 寶雞網(wǎng)站制作公司百度關(guān)鍵詞競價(jià)價(jià)格
  • 專業(yè)的標(biāo)志設(shè)計(jì)公司龍巖seo
  • 網(wǎng)站文案編輯怎么做浙江網(wǎng)站推廣公司
  • 福田專業(yè)網(wǎng)站建設(shè)公司最新病毒感染什么癥狀
  • 沂水縣的旅游景區(qū)的網(wǎng)站建設(shè)seo的基本步驟是什么
  • python做網(wǎng)站用什么軟件百度競價(jià)關(guān)鍵詞價(jià)格查詢
  • 網(wǎng)站框架怎么做旺道seo推廣