亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

linux下內存大小、起始地址的解析與修改 2013-04-08 16:18:09

2019-11-09 16:11:37
字體:
來源:轉載
供稿:網友
linux下內存大小、起始地址的解析與修改2013-04-08 16:18:09

分類: LINUX

在實際的工作中,由于產品型號的不同,經常需要調整linux所管理的內存的大小,而內核在啟動階段,會兩次去解析從uboot傳遞過來的關于內存的信息,具體如下:

一、解析從uboot傳遞過來的tag(在parse_tags中處理)

在uboot的do_bootm_linux()函數中,會創建一系列需要傳遞給內核的tag,所有的tag以鏈表形式鏈接到指定的物理內存中。setup_start_tag用來建立起始的tag,而起始的物理地址由bd->bi_boot_params指定,

static void setup_start_tag (bd_t *bd){    params =(struct tag*) bd->bi_boot_params;    params->hdr.tag= ATAG_CORE;    params->hdr.size= tag_size (tag_core);    params->u.core.flags= 0;    params->u.core.pagesize= 0;    params->u.core.rootdev= 0;    params = tag_next(params);}

bi_boot_params是在board_init中初始化的,此地址是與內核協商一致的用來存放tag的基址。

intboard_init (void)

{

…………

    gd->bd->bi_boot_params =CFG_BOOT_PARAMS;

…………

}

而內存的tag是在setup_memory_tags()函數中創建的,其hdr.tag指定了tag的類型為ATAG_MEM

static int __init parse_tag_mem32(conststruct tag *tag){    if (meminfo.nr_banks>= NR_BANKS){        PRintk(KERN_WARNING         "Ignoring memory bank 0x%08x size %dKB/n",            tag->u.mem.start, tag->u.mem.size/ 1024);        return -EINVAL;    }    arm_add_memory(tag->u.mem.start, tag->u.mem.size);    return 0;}__tagtable(ATAG_MEM, parse_tag_mem32);

在內核中,會通過__tagtable 宏來建立起相關的struct tagtable的數據結構,并放入".taglist.init" 段中,

#define__tag __used __attribute__((__section__(".taglist.init")))

#define__tagtable(tag, fn) /

static structtagtable __tagtable_##fn __tag = { tag, fn }

static int __init parse_tag_mem32(conststruct tag *tag){    return arm_add_memory(tag->u.mem.start, tag->u.mem.size);}__tagtable(ATAG_MEM, parse_tag_mem32);

而在start_kernel()->setup_arch()->parse_tags()函數中會根據從指定的物理內存中解析出來的tag的類型(即在uboot中寫入的hdr.tag)去解析不同的tag。

在內核中此物理內存地址是在MACHINE_START中定義的,其中的boot_params與uboot中的bi_boot_params數據段指向相同的物理內存地址。因此是在uboot中寫入tag,在內核中此地址解析tag。

MACHINE_START(hi3520v100,"hi3520v100")    .phys_io    = IO_SPACE_PHYS_START,    .io_pg_offst    =(IO_ADDRESS(IO_SPACE_PHYS_START)>> 18)& 0xfffc,     .boot_params    = PHYS_OFFSET+ 0x100,    .map_io        = hisilicon_map_io,    .init_irq    = hisilicon_init_irq,    .timer        =&hisilicon_timer,    .init_machine    = hisilicon_init_machine,MACHINE_ENDstruct tagtable{    __u32 tag;    int (*parse)(conststruct tag *);};

在parse_tags()中,會根據讀出來的tag的類型,即hdr.tag與從".taglist.init"段中的struct tagtable中的tag字段比較,如果相等,便執行struct tagtable中的parse()函數,對內存的tag來講,其類型是ATAG_MEM,解析函數是parse_tag_mem32();

static int __init parse_tag_mem32(conststruct tag *tag){    if (meminfo.nr_banks>= NR_BANKS){        printk(KERN_WARNING         "Ignoring memory bank 0x%08x size %dKB/n",            tag->u.mem.start, tag->u.mem.size/ 1024);        return -EINVAL;    }    arm_add_memory(tag->u.mem.start, tag->u.mem.size);    return 0;}__tagtable(ATAG_MEM, parse_tag_mem32);

在內核中,物理內存的起始地址和大小存放在一個struct meminfo meminfo的全局變量中,

struct meminfo{    int nr_banks;    struct membank bank[NR_BANKS];}; struct membank{    unsigned long start;    unsigned long size;    int node;};

nr_banks表示內核總共管理了多少個bank。

structmembank記錄了內核中各個bank的信息,start表示起始地址,size表示此bank的大小,node表示此bank屬于哪個內存結點。

Linux內核可以管理多個不連續的物理內存,每段連續的物理內存的大小和起始地址存在一個struct membank結構體中,有多少段物理內存,就有多少個bank。

parse_tag_mem32解析在uboot中建立的關于內存的tag,把其中的物理內存地址和大小填充到bank中。

二、解析從uboot傳遞過來的boot_command_line(在parse_cmdline函數中解析)。

boot_command_line命令行是在uboot的fix_bootargs()函數里建立的。即在uboot中看到的bootargs的環境變量

static void fix_bootargs(char*cmdline){….……    /* fix "mem=" params */    p = strstr(cmdline,"mem=");    if(!p){        sprintf(args," mem=%dM",gd->bd->bi_dram[0].size/0x200000);        strcat(cmdline,args);    }……………}

在內核中是通過early_mem()來解析boot_command_line中有關內存大小的參數行的。

static void __init early_mem(char**p){    static int usermem __initdata= 0;    unsigned long size, start;    /*     * If the user specifies memory size, we     * blow away any automatically generated     * size.     */    if (usermem== 0){        usermem = 1;        meminfo.nr_banks = 0;    }    start = PHYS_OFFSET;    size = memparse(*p, p);    if (**p== '@')        start = memparse(*p+ 1, p);    arm_add_memory(start,size);}__early_param("mem=", early_mem);

該函數解析從uboot傳遞進來的boot_command_line命令行參數中以“mem=”開頭的命令行,如果boot_command_line中有以“mem=”開頭的命令行,就調用該函數解析“mem=”之后的關于內存的信息,

把內存的大小寫到對應的bank中去,內存的基地址在此處是一個默認值。如果有兩段不連續的物理內存,可以在boot_command_line中設置如下內容即可:

mem=72M@0xe2000000mem=128M@0xe8000000

在此處,定義了static int usermem __initdata = 0,從而設置meminfo.nr_banks= 0,這樣把前面解析uboot的tag所賦值的bank內容又重寫了,所以相當于前面解析tag的操作沒有生效,起作用的還是此處的解析boot_command_line的操作。

三、以上是內核啟動過程中所做的兩次解析內存參數的操作,在實際應用中需要修改linux內存大小時可以采取相應的方法:

1、 修改uboot中內存相關的tags或者bootargs的命令行參數。這種做法雖然可以修改linux管理的內存的大小,但是由于要修改uboot,這樣會對產品生產中增加困難,而且bootloader在原則上是要盡量少做改動,防止由于修改bootloader造成板子無法啟動等問題,所以此方法不推薦使用。

2、 通過在解析boot_command_line之前修改其中的”mem=”之后的相關內容來修改linux所管理的內存大小,這樣可以做到不同產品間的兼容性,而且后續的產品升級等方面也比較簡單容易操作。

在海思平臺上實現了這種做法。

void__init hikio_fix_meminfo(char *cmdline,struct meminfo *mi)

{

……………….

    strcpy(p,p+8);

    strcat(cmdline," mem=72M");

    mi->bank[0].size = 72*0x100000;

}

然后在解析cmdline之前執行此函數。hikio_fix_meminfo(from,&meminfo);/*wangqian fix for cost-down boards*/

memcpy(boot_command_line, from,COMMAND_LINE_SIZE);

boot_command_line[COMMAND_LINE_SIZE-1] ='/0';

parse_cmdline(cmdline_p, from);

這種方法可以很方便的根據不同的產品型號修改內存的大小,而且只需要修改內核部分,不用去對uboot進行改動,所以是最方便快捷的方式。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
永久免费毛片在线播放不卡| 中文字幕日韩av| 在线精品国产欧美| 精品久久久久人成| 国产精品私拍pans大尺度在线| 精品国产精品自拍| 亚洲精品视频免费| 亚洲精品福利在线观看| 久久成人精品一区二区三区| 国产亚洲一区二区精品| 亚洲欧洲激情在线| 57pao国产成人免费| 久久99久久99精品中文字幕| 国产亚洲xxx| 久久久精品欧美| 午夜精品久久久久久久久久久久久| 国产成人综合一区二区三区| 国产精品三级美女白浆呻吟| 日韩国产精品视频| 国产成人精品日本亚洲专区61| 亚洲国产精品成人一区二区| 91大神福利视频在线| 日韩中文字幕av| 国产精品亚洲网站| 国产精欧美一区二区三区| 久久免费视频这里只有精品| 亚洲精品成a人在线观看| 欧美多人爱爱视频网站| 亚洲国产日韩欧美在线图片| 91性高湖久久久久久久久_久久99| 欧美交受高潮1| 欧美日韩免费网站| 国产欧美精品日韩精品| 欧美国产日韩xxxxx| 欧美亚洲国产日本| 亚洲电影在线观看| 91精品久久久久久综合乱菊| 成人免费xxxxx在线观看| 中文字幕亚洲综合久久筱田步美| 国产精品激情自拍| 一区二区三区视频免费在线观看| 日韩在线观看免费高清| 久久精品国产亚洲精品2020| 久久99精品久久久久久琪琪| 亚洲欧美一区二区激情| 亚洲欧美日本伦理| 97国产精品人人爽人人做| 亚洲成人久久一区| 久久成人av网站| 亚洲男女自偷自拍图片另类| 欧美精品videos另类日本| 国产91成人video| 在线精品视频视频中文字幕| 亚洲天堂男人天堂女人天堂| 国产精品视频网站| 亚洲伊人一本大道中文字幕| 欧美专区在线播放| 日韩国产在线看| 国产欧美日韩专区发布| 国产精品96久久久久久| 亚洲性视频网站| 91精品国产91久久久| 欧美日韩国产va另类| 中文字幕少妇一区二区三区| 91wwwcom在线观看| 九九热这里只有精品免费看| 欧美精品成人在线| 91亚洲国产成人精品性色| 亚洲第一精品自拍| 亚洲综合自拍一区| 97视频人免费观看| 亚洲国产欧美久久| 日韩在线资源网| 中国日韩欧美久久久久久久久| 久久久久五月天| 欧美成人午夜激情| 欧美多人爱爱视频网站| 亚洲一区二区三区四区视频| 久久久久久国产| 国产精品久久久久久久一区探花| 欧美日韩色婷婷| 亚洲欧洲xxxx| 国产精品va在线播放我和闺蜜| 精品久久久久久久久久国产| 国产美女精品视频免费观看| 久久影院资源网| 成人羞羞国产免费| 欧美精品性视频| 欧美国产精品人人做人人爱| 成人xvideos免费视频| 日韩电影免费观看在线观看| 国外日韩电影在线观看| 国产精品影院在线观看| 国产精品欧美风情| 久久久久国产精品免费| 亚洲欧洲一区二区三区久久| 波霸ol色综合久久| 美女av一区二区三区| 亚洲欧美精品伊人久久| 亚洲久久久久久久久久久| xvideos亚洲| 精品久久久久久久久久久久久久| 国产色视频一区| 78m国产成人精品视频| 成人中心免费视频| 精品久久香蕉国产线看观看亚洲| 日韩男女性生活视频| 日韩hd视频在线观看| 色777狠狠综合秋免鲁丝| 欧美黑人xxxⅹ高潮交| 国产精品男女猛烈高潮激情| 亚洲精品国产精品乱码不99按摩| 狠狠色香婷婷久久亚洲精品| 亚洲国产日韩一区| 亚洲天堂男人天堂女人天堂| 欧美色图在线视频| 色阁综合伊人av| 日韩高清a**址| 精品亚洲永久免费精品| 国产成人精品一区二区三区| 日本高清不卡的在线| 国产婷婷成人久久av免费高清| 中文字幕一区日韩电影| 中文字幕亚洲天堂| 日韩在线视频观看| 日韩中文字幕国产| 亚洲电影免费观看高清| 精品五月天久久| 久久精品国产96久久久香蕉| 色七七影院综合| 精品国产一区二区三区四区在线观看| 国产成人精品久久亚洲高清不卡| 91欧美精品成人综合在线观看| 亚洲r级在线观看| 国产精品久久久久一区二区| 国产精品久久久久久av福利| 亚洲国产一区二区三区在线观看| 成人免费淫片视频软件| 亚洲精品在线观看www| 亚洲精品久久久久国产| 国产精品一区二区性色av| 日韩大陆欧美高清视频区| 国产香蕉97碰碰久久人人| 91精品国产一区| 九九热99久久久国产盗摄| 国产精品爽爽ⅴa在线观看| 国产精品国产三级国产aⅴ浪潮| 在线观看精品自拍私拍| 精品成人av一区| 亚洲免费视频在线观看| 日韩精品中文字幕在线观看| 国产91在线视频| 欧美寡妇偷汉性猛交| 亚洲人成网7777777国产| 欧美裸身视频免费观看| 成人免费网站在线看| 国产福利视频一区二区| 欧美最顶级丰满的aⅴ艳星| 国产精品视频xxx| 在线国产精品视频| 视频一区视频二区国产精品| 久久久久99精品久久久久| 高清亚洲成在人网站天堂| 国产精品久久不能|