linux 文件擦除,linux文件系统如何使用emmc的擦除功能(Erase Trim Discard Sanitize)达到最优performance...

1、android init.rc中可以看到, 系统启动mount /data 目录时,mount命令添加了参数:discard

mount ext4 /emmc@usrdata /data noatime nosuid nodev wait noauto_da_alloc,discard

2、

mount的discard参数传递到ext4_mount函数的flags参数

//kernel/fs/ext4/super.c

static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,

const char *dev_name, void *data)

{return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super);

}

//kernel/fs/super.c

struct dentry *mount_bdev(struct file_system_type *fs_type,

int flags, const char *dev_name, void *data,

int (*fill_super)(struct super_block *, void *, int))

{

struct block_device *bdev;

struct super_block *s;

fmode_t mode = FMODE_READ | FMODE_EXCL;

int error = 0;

.................

s->s_flags = flags | MS_NOSEC;    //将mount flag保存在sb的s_flags成员中

s->s_mode = mode;

strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));

sb_set_blocksize(s, block_size(bdev));

error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);   //调用ext4的fill super :ext4_fill_super, 通过sb传递mount flag

.........................

return dget(s->s_root);

}

//kernel/fs/ext4/super.c

static int ext4_fill_super(struct super_block *sb, void *data, int silent)

{

...................

if (!parse_options((char *) data,sb, &journal_devnum,

&journal_ioprio, 0))

....................

static const struct mount_opts {

inttoken;

intmount_opt;

intflags;

} ext4_mount_opts[] = {

...........................

{Opt_discard, EXT4_MOUNT_DISCARD, MOPT_SET},

{Opt_nodiscard, EXT4_MOUNT_DISCARD, MOPT_CLEAR},

.............................................

}

2、/kernel/drivers/mmc/card/block.c

if (req && req->cmd_flags & REQ_DISCARD) {

...

ret = mmc_blk_issue_discard_rq(mq, req);

} else if (req && req->cmd_flags & REQ_FLUSH) {

/* complete ongoing async transfer before issuing flush */

if (card->host->areq)

mmc_blk_issue_rw_rq(mq, NULL);

ret = mmc_blk_issue_flush(mq, req);

} else {

ret = mmc_blk_issue_rw_rq(mq, req);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
eMMC(Embedded MultiMediaCard)是一种用于嵌入式系统的闪存存储设备,其擦写接口通常是通过 SD/MMC 协议实现的。下面是一种可能的 eMMC 擦写接口的实现方法: 1. 初始化 SD/MMC 控制器,使其进入 SPI 模式。 2. 发送 CMD0 命令,使 eMMC 进入空闲状态。 3. 发送 CMD1 命令,使 eMMC 进入初始化状态。 4. 发送 CMD2 命令,读取 eMMC 的 CID(Card Identification)。 5. 发送 CMD3 命令,读取 eMMC 的 RCA(Relative Card Address)。 6. 发送 CMD7 命令,选择 eMMC。 7. 发送 CMD9 命令,读取 eMMC 的 CSD(Card Specific Data)。 8. 根据 CSD 中的信息计算出 eMMC 的容量和页大小等参数。 9. 发送 CMD16 命令,设置 eMMC 的块大小。 10. 发送 CMD24 命令,写入指定块地址的数据。 11. 发送 CMD32 命令,设置擦除的起始块地址。 12. 发送 CMD33 命令,设置擦除的结束块地址。 13. 发送 CMD38 命令,开始擦除操作。 14. 等待擦除操作完成。 15. 发送 CMD12 命令,停止写入操作。 下面是一个 C++ 实现的示例代码: ```c++ // eMMC擦写接口实现 class EmmcWriter { public: EmmcWriter() : pageSize_(0), capacity_(0) {} // 初始化 void init() { // 初始化SD/MMC控制器,进入SPI模式 spiInit(); // 发送CMD0命令,使eMMC进入空闲状态 sendCommand(CMD0, 0); // 发送CMD1命令,使eMMC进入初始化状态 sendCommand(CMD1, 0); // 发送CMD2命令,读取eMMC的CID sendCommand(CMD2, 0); // 发送CMD3命令,读取eMMC的RCA sendCommand(CMD3, 0); // 发送CMD7命令,选择eMMC sendCommand(CMD7, 0); // 发送CMD9命令,读取eMMC的CSD uint32_t response[4]; sendCommand(CMD9, 0, response); // 计算容量和页大小等参数 capacity_ = calculateCapacity(response); pageSize_ = calculatePageSize(response); // 发送CMD16命令,设置eMMC的块大小 sendCommand(CMD16, pageSize_); } // 擦除指定地址范围的块 void eraseBlocks(uint32_t startBlock, uint32_t endBlock) { // 发送CMD32命令,设置擦除的起始块地址 sendCommand(CMD32, startBlock); // 发送CMD33命令,设置擦除的结束块地址 sendCommand(CMD33, endBlock); // 发送CMD38命令,开始擦除操作 sendCommand(CMD38, 0); // 等待擦除操作完成 while (getStatus() != STATUS_IDLE) {} // 发送CMD12命令,停止写入操作 sendCommand(CMD12, 0); } // 写入指定地址的块数据 void writeBlock(uint32_t blockAddr, const uint8_t* data, size_t blockSize) { // 发送CMD24命令,写入指定块地址的数据 sendCommand(CMD24, blockAddr); // 发送数据 spiWrite(data, blockSize); // 等待写入操作完成 while (getStatus() != STATUS_IDLE) {} // 发送CMD12命令,停止写入操作 sendCommand(CMD12, 0); } private: // 发送命令并读取响应 void sendCommand(uint8_t cmdIndex, uint32_t arg, uint32_t* response = nullptr) { // 发送命令 spiWriteCommand(cmdIndex, arg); // 读取响应 if (response != nullptr) { spiRead(response, getResponseLength(cmdIndex)); } } // 获取响应长度 uint32_t getResponseLength(uint8_t cmdIndex) { switch (cmdIndex) { case CMD2: case CMD9: case CMD10: return 4; default: return 1; } } // 获取状态 uint32_t getStatus() { uint32_t response; sendCommand(CMD13, 0, &response); return response & 0xF; } // 计算容量 uint64_t calculateCapacity(uint32_t* response) { uint32_t cSize = (response[1] >> 16) & 0xFFF; uint32_t cSizeMult = (response[1] >> 7) & 0x7F; uint32_t readBlLen = response[2] & 0xF; uint64_t blockCount = (cSize + 1) * (1 << (cSizeMult + 2)); uint64_t blockSize = 1 << readBlLen; return blockCount * blockSize; } // 计算页大小 uint32_t calculatePageSize(uint32_t* response) { uint32_t readBlLen = response[2] & 0xF; return 1 << readBlLen; } // SPI初始化 void spiInit() { // TODO: 初始化SPI控制器 } // SPI写命令和参数 void spiWriteCommand(uint8_t cmdIndex, uint32_t arg) { // TODO: 写入命令和参数 } // SPI写数据 void spiWrite(const uint8_t* data, size_t size) { // TODO: 写入数据 } uint32_t pageSize_; // 页大小 uint64_t capacity_; // 容量 }; ``` 需要注意的是,在实际的 eMMC 擦写接口实现中,还需要考虑错误处理、校验和等问题。此外,该示例代码中的 `spiInit()`、`spiWriteCommand()` 和 `spiWrite()` 函数需要根据具体的硬件平台进行实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值