千家信息网

linux mtd的概念是什么

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,本篇内容主要讲解"linux mtd的概念是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"linux mtd的概念是什么"吧!在linux中,mtd是
千家信息网最后更新 2026年10月31日linux mtd的概念是什么

本篇内容主要讲解"linux mtd的概念是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"linux mtd的概念是什么"吧!

在linux中,mtd是指"内存技术设备",是存储设备中的一个子系统。linux引入MTD系统是为了给NOR FLASH和NAND FLASH设备提供统一接口。MTD设备通常可分为四层:设备节点、MTD设备层、MTD原始设备层、硬件驱动层。

本教程操作环境:linux5.9.8系统、Dell G3电脑。

Linux MTD是什么?

MTD全称"Memory Technology Device",意思为"内存技术设备",是Linux的存储设备中的一个子系统。

在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口。MTD将文件系统与底层FLASH存储器进行了隔离。

设计此MTD系统的目的是,对于内存类的设备,提供一个抽象层,一个接口,使得对于硬件驱动设计者来说,只需要去提供最简单的底层硬件设备的读/写/擦除函数就可以了,数据对于上层使用者来说是如何表示的,可以不关心,因为MTD存储设备子系统都帮你做好了。

MTD框架

Linux的MTD设备位于drivers/mtd/下面。

MTD文件下的内容如下:

MTD设备通常可分为四层

上到下依次是:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。

1.cmdlinepart.c

当mtd分区表由u-boot通过cmd参数传输给linux时,linux内核可以不用对mtdparts进行注册添加,只需要将MTD中的command line partition选项开启即可。使用这种的方法u-boot下需要对MTD进行支持,且所传输的mtd分区参数要符合格式要求。

2.devices文件夹

当我们有一个spi flash设备时且要使用mtd进行管理,我们一般会将其放在devices文件夹下,如devices文件夹下面的m25p80.c就是一个典型的spi flash设备。

3.chips/nand/onenand文件夹

nand flash 驱动在nand文件夹下;

onenand flash 驱动在onenand文件夹下;

nor flash比较杂,下面几个文件下都会有:

chips:cfi/jedec接口通用驱动

devices:nor flash底层驱动(spi flash)

maps:nor flash映射关系相关函数

4.核心文件

mtdchar.c : MTD字符设备接口相关实现,设备号31;

mtdblock.c : MTD块设备接口相关实现,设备号90,;

mtdcore.c: MTD原始设备接口相关实现;

mtdpart.c : MTD分区接口相关实现。

5.ubi

ubifs文件的支持层,当使用ubifs文件系统时,需要将Device Drivers -> Memory Technology Device (MTD) support -> UBI -Unsorted block image 中的Enable UBI选中。

将File systems -> Miscellaneous filesystems中的UBIFS file system support选中。

MTD分区表的实现

在开机过程从console经常可以看到类似以下信息,

0x000000000000-0x000000100000 : "Bootloade"0x000000100000-0x000002000000 : "Kernel"0x000002000000-0x000003000000 : "User"0x000003000000-0x000008000000 : "File System"

这就是MTD给我们一种最直观的表示形式,给我们展示了内存中各模块的分区结构,但这些分区是怎样实现的呢?分区表的实现方式有几种,下面进行分别说明:

注:分区表实现的前提是MTD设备驱动已经成功了,否则连驱动都没成功就无分区可说了。

1.内核中添加

在内核中添加这是一个比较经常使用的方法,随便一本驱动移植的书上应该都有,主要就是在平台设备里面添加mtd_partition,添加类似下面的信息,这边就不过多描述

struct mtd_partition s3c_nand_part[] = {    {        .name       = "Bootloader",        .offset     = 0,        .size       = (1 * SZ_1M),        .mask_flags = MTD_CAP_NANDFLASH,    },    {        .name       = "Kernel",        .offset     = (1 * SZ_1M),        .size       = (31 * SZ_1M) ,        .mask_flags = MTD_CAP_NANDFLASH,    },    {        .name       = "User",        .offset     = (32 * SZ_1M),        .size       = (16 * SZ_1M) ,    },    {        .name       = "File System",        .offset     = (48 * SZ_1M),        .size       = (96 * SZ_1M),    }};static struct s3c_nand_set s3c_nand_sets[] = {    [0] = {        .name       = "nand",        .nr_chips   = 1,        .nr_partitions  = ARRAY_SIZE(s3c_nand_part),        .partitions = ok6410_nand_part,    },};static struct s3c_platform_nand s3c_nand_info = {    .tacls      = 25,    .twrph0     = 55,    .twrph2     = 40,    .nr_sets    = ARRAY_SIZE(s3c_nand_sets),    .sets       = ok6410_nand_sets,};static void __init s3c_machine_init(void){    s3c_nand_set_platdata(&s3c_nand_info); }

因为我们的MTD驱动已经完成了,当device和driver匹配后会调用驱动中的probe接口函数,我们需要在probe函数里面调用add_mtd_partitions(s3c_mtd, sets->partitions, sets->nr_partitions);实现分区表的添加。

2.u-boot传参

在u-boot下可以通过添加mtdparts信息到bootargs中,u-boot启动后会将bootargs中的信息传送给kernel,,kernel在启动的时候会解析bootargs中mtdparts的部分,这边举个例子:

mtdparts=nand.0:1M(Bootloader)ro,31M(Kernel)ro,16M(User),96M(File System),更具体的mtdparts格式可以查阅下相关资料。

为了使kernel能够解析mtdparts信息,我们需要将内核中的Device Drivers -> Memory Technology Device (MTD) support ->Command line partition table parsing选项开启,这在上面已经说过。

在内核中添加分区表的时候,我们是在平台设备里面加入mtd_partition信息。这边通过u-boot传参则取消平台设备里面的partition信息,那我们需要怎样解析u-boot的传过来的mtdparts呢。

u-boot传参过来后,cmdlinepart.c中会将这些参数解析好,存在里面LIST_HEAD(part_parsers)链表里面,然后我们在驱动的probe函数中,通过调用mtd_device_parse_register(mtd, probe_types,&ppdata, NULL, 0);函数。

mtd_device_parse_register()函数位于drivers/mtd/mtdcore.c 中,内容如下:

int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,                  struct mtd_part_parser_data *parser_data,                  const struct mtd_partition *parts,                  int nr_parts){    int err;    struct mtd_partition *real_parts;    err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);    if (err <= 0 && nr_parts && parts) {        real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,                     GFP_KERNEL);        if (!real_parts)            err = -ENOMEM;        else            err = nr_parts;    }    if (err > 0) {        err = add_mtd_partitions(mtd, real_parts, err);        kfree(real_parts);    } else if (err == 0) {        err = add_mtd_device(mtd);        if (err == 1)            err = -ENODEV;    }    return err;}

可以看到该函数会先执行parse_mtd_partitions(mtd, types, &real_parts, parser_data);函数,后面还是通过add_mtd_partitions()函数来实现分区表的添加。

parse_mtd_partitions()函数位于drivers/mtd/mtdpart.c中,内容如下:

int parse_mtd_partitions(struct mtd_info *master, const char *const *types,             struct mtd_partition **pparts,             struct mtd_part_parser_data *data){    struct mtd_part_parser *parser;    int ret = 0;    if (!types)        types = default_mtd_part_types;    for ( ; ret <= 0 && *types; types++) {        parser = get_partition_parser(*types);        if (!parser && !request_module("%s", *types))            parser = get_partition_parser(*types);        if (!parser)            continue;        ret = (*parser->parse_fn)(master, pparts, data);        put_partition_parser(parser);        if (ret > 0) {            printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",                   ret, parser->name, master->name);            break;        }    }    return ret;}

进入parse_mtd_partitions()函数会先判断types的类型,如果为空则给默认值,types的类型一般就两种,如下:

static const char * const default_mtd_part_types[] = {    "cmdlinepart",    "ofpart",    NULL};

第一个"cmdlinepart"即u-boot传参的方式,第二个"ofpart"即下面要讲到的使用dts传参的方式,判断完类型后,就通过get_partition_parser去解析part_parsers链表里面的数据,这样就完成u-boot参数的解析。

3.dts传参

在Linux3.14以后的linux版本中,加入一个新的知识DTS(Device tree),dts其实就是为了解决ARM Linux中的冗余代码,在Linux2.6版本的arch/arm/plat.xxx和arch/arm/mach.xxx中充斥着大量的垃圾代码,采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码,关于dts可以自行查阅资料。

dts传参的原理其实和u-boot一样,区别在于:u-boot的时候是通过cmdlinepart.c文件实现分区信息写入LIST_HEAD(part_parsers)链表,dts则是用过ofpart.c文件实现分区信息写入LIST_HEAD(part_parsers)链表,所以同样要把ofpart.c文件的宏打开,在调用mtd_device_parse_register(mtd, probe_types,&ppdata, NULL, 0);函数的时候types要设置成ofpart。

如果去对比Linux2.6版本和Linux3.14版本,会发现drivers/mtd/ofpart.c和drivers/mtd/mtdpart.c文件有所不同,Linux3.8版本里面多了Device tree这一部分的内容,感兴趣的可以自己深究下。

这边举个dts的例子:

 pinctrl-0 = <&s3c_nand_flash>;    ranges = <0 0 0x000000000000 0x000008000000>;   /* CS0: NAND */    nand@0,0 {        partition@1 {            label = "Bootloader";            reg = <0x000000000000 0x000000100000>;        };        partition@2 {            label = "Kernel";            reg = <0x000000100000 0x000002000000>;        };        partition@3 {            label = "User";            reg = <0x000002000000 0x000003000000>;        };        partition@4 {            label = "File System";            reg = <0x000003000000 0x000008000000>;        };    };

到此,相信大家对"linux mtd的概念是什么"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

设备 文件 函数 驱动 信息 接口 分区表 内容 内核 文件夹 版本 硬件 系统 内存 参数 就是 时候 存储 概念 原始 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司经营范围 互联网科技公司电话 互联网与新科技 世界互联网领先科技成果 南京欣网互联网科技 上海致骋互联网科技 润盈互联网科技 撒么互联网科技公司 联恩商钥互联网科技有限公司 深圳国际航运科技和互联网 哈尔滨新华互联网科技学院 宁波青枫互联网科技有限公司 荆州市昕露互联网络科技有限公司 科技赋能视角下互联网保险发展 美国互联网科技实力 黑科技 体验场景 互联网大会 上海钢联属于互联网科技股吗 互联网相关科技技术 上海创道互联网络科技有限公司 科技信息时代互联网发展 互联网科技有限公司 工业互联网科技新基建 互联网科技资迅 天扬科技互联网广告 甘肃拓世互联网科技有限公司 互联网科技实习生岗位职责 和信科技工业互联网 中国互联网十大科技股排名 江苏苏星互联网科技有限公司 互联网公司属于科技吗
0