RK平臺RAM和ROM容量計算

聲明

版權聲明:博文爲原創內容,可以轉載或引用,但須在明顯位置標明原文作者和出處,未經同意不得擅自修改本文內容!博客地址:http://blog.csdn.net/luzhenrong45


RK平臺RAM和ROM容量計算

1. RAM 簡介

RAM(random access memory),隨機存取存儲器,又稱作“隨機存儲器”,對於Android設備來說,它還有一個更通俗常見的名稱,叫 運行內存(簡稱運存)。一般來說,主流的Android設備有512M、768M、1G、2G等容量,現在高配手機都已經有3G、4G運行內存了。運行內存,通常是作爲操作系統或其他正在運行程序的臨時存儲介質,也稱作系統內存。就好比計算機中的內存條,如果內存條容量越大,計算機就有更多的內存來存儲同時運行的任務,這樣系統響應的速度也就越快,RAM在手機中就起到了這個作用。

拿RAM容量來說,其容量又分標稱容量、實際容量和可用容量三種。標稱容量即市場上一些手機廠商宣稱的設備參數的容量,即運行內存1G、2G、4G這些。而事實上,實際容量肯定會比標稱容量少一些,這其除了一些小量的損耗(算法、顆粒的不同)之外,部分手機還會被GPU佔用一部分RAM。

1GB的設備看到的實際容量會是0.7 GB ~ 0.8 GB。而可用容量又會比實際容量再少一些,因爲系統本身以及後臺程序也需要佔用一部分內存。

那麼,怎麼獲取運行內存(RAM)的標稱容量與實際容量呢?下面,以一塊RK3188的Android開發板,來簡單介紹一下。
  

1.1 RAM 實際容量的計算

我們知道,在linux下面,可以通過以下命令查看系統內存信息。

cat /proc/meminfo

Android內核是基於Linux的二次開發,當然也可以通過此命令進行內存參數的查看。例如:1 GB內存的Android設備情況如下所示:
meminfo_1GB

以上信息中,我們在這裏只需要重點關注 MemTotalMemFree, 即RAM實際容量RAM可用容量

  • MemTotal: 運行內存實際容量,所有可用RAM大小(即物理內存減去一些預留位和內核的二進制代碼大小),這個就是我們前面說的RAM實際容量了。

  • MemFree: 運行內存剩餘容量,LowFree與HighFree的總和,留着未使用的內存,,這個就是我們前面說的RAM可用容量了。

因此,通過查看/proc/meminfo,便可獲得設備運行內存的實際容量。

shell環境下,可以通過以下命令截取RAM實際容量:

cat /proc/meminfo |grep MemTotal|awk '{print $2" "$3}'

getMemInfo

JAVA環境下:

   /**
     * 獲取運行內存實際容量(KB)
     * 
     */
    public static double getMemTotalSize() {

        double memorySize =  1 * 1024 * 1024;//1GB;
        BufferedReader bufferedReader = null;
        File file = new File("/proc/meminfo");
        if(file.exists()) {
            try {
                bufferedReader = new BufferedReader(new FileReader("/proc/meminfo"), 8192);
                String line = null;
                String content = null;
                while ((line = bufferedReader.readLine()) != null) {
                    if(line.indexOf("MemTotal:") != -1) {
                        content = line.substring(line.indexOf("MemTotal:"));
                        memorySize = Double.parseDouble(content.replaceAll("\\D+", ""));
                        //Log.i(TAG, "get memory size: " + memorySize + " KB");
                        break;
                    }
                }
            } catch (IOException e) {
                Log.w(TAG, "couldn't get memory size in " + MEMORY_PATH + ",memory size defaults to 1GB.");
                memorySize = DEFAULT_MEMORY_SIZE_IN_KB;
            } finally {
                if (bufferedReader != null) {
                    try {
                        bufferedReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }else {
            Log.w(TAG, MEMORY_PATH + " not exist, memory size defaults to 1GB.");
            memorySize=DEFAULT_MEMORY_SIZE_IN_KB;
        }
        return memorySize;
    }

RAM可用容量也可以通過以上類似的方式進行獲取。

另外說一下,Android本身也提供了標準API用於獲取運存信息:

meminfo


1.2 RAM 標稱容量的計算

那麼,RAM 標稱容量呢,比如設備廠商宣稱的 1GB, 2GB這些參數,又該如何獲取?查找了一番,發現Android(RK平臺)並沒有直接提供直接的API用於獲取RAM標稱容量,怎麼辦呢?
想到一個折衷的辦法,如上面所說,1GB內存標稱的設備,實際容量有700MB左右。那麼,對獲取到的實際容量進行向上取整處理,便可以得到盒子的標稱內存。至於向上取整可以使用Math類提供的ceil函數實現,如下方式獲取。(沒有辦法的辦法)

    /**
     * 獲取運行內存標稱容量(GB)
     * 
     */
    public static String getMemNominalSize() {
        String size= String.format("%.2f",Math.ceil(getMemTotalSize()/1024/1024));
        Log.i(TAG, "get memory size: " + size + "GB");
        return size;
    }

目前設備使用的是這種向上取整的方式來獲取RAM標稱容量,也沒什麼問題。不過,Android沒有提供獲取RAM標稱容量的接口,始終感覺缺點什麼。而且,心裏總感覺通過這樣的方式來獲取參數有點“委婉”。
後來有留意到,DDR (可以理解爲內存的一種型號,在這裏可以當成RAM來對待)相關的內核日誌中,其實是有打印運行內存標稱容量的!如截圖中的關鍵字:Total Capability
getRAMInDDR

看了一下內核代碼,這個只是在內核中打印出了相關的參數信息,並沒有向頂層提供接口。
因此,如果有必要的話,也是可以通過在內核層自己增加查詢接口(比如 sys 或 proc),提供給頂層應用調用。


2. ROM 簡介

2.1 ROM究竟指什麼?

一般說到RAM,都會說到ROM,這兩個像是一對歡喜冤家,誰也離不開誰,總會成對出現。在嵌入式尤其智能手機領域,RAM一般說的就是運行內存,而對於ROM,則有幾個常見的說法。

  1. 首先,在智能手機,尤其 Android 設備盛行的今天,常常會聽到給手機“刷機”,給手機“刷了一個新ROM”, “手機刷成板磚”這樣的說法。這裏的ROM指的是刷機所使用系統固件(只讀內存鏡像),常用於手機定製系統玩家的圈子中。常見的 ROM image 有 img、zip 等格式,前者通常用fastboot程序等刷機工具通過數據線刷入(線刷),後者通常用 recovery 模式從 sd刷入(卡刷),
    因此 img 鏡像也被稱爲線刷包,zip 鏡像也被稱爲卡刷包。
    拿RK3188來說,量產刷機所用的ROM鏡像一般包含 system.img、boot.img、kernel.img、misc.img和recovery.img。以上鏡像也可以打包爲統一固件(update.img)。

  2. 在智能手機領域,ROM還指手機智能操作系統。很多定製系統玩家也會統一將定製過操作系統稱爲 ROM。 像比較有名的 小米的 MIUI, 錘子的 Smartisan OS,魅族的 Flyme, CM團隊的 CyanogenMod…可謂是百家齊放,各有各家的奇葩特色。

  3. 而從根本上來講,ROM其實只是只讀存儲器(Read-Only Memory)的簡稱,是一種只能讀出事先所存數據的固態半導體存儲器。 前面我們說到的ROM刷機鏡像,ROM操作系統,說到底都是“存儲”在這種存儲介質上的,並且持有持久性,斷電不丟失的特性。

對於我的開發板來說,採用Nandflash作爲我們的ROM存儲介質。按照百度百科的介紹,Nandflash內存是flash內存的一種,具有容量較大,改寫速度快等優點,適用於大量數據的存儲,因而在業界得到了越來越廣泛的應用,如嵌入式產品中包括數碼相機、MP3隨身聽記憶卡、體積小巧的U盤等。
同樣地,Android提供了獲取內部存儲容量,內部和外部SDCard存儲空間容量的API接口,卻也沒有給頂層應用開發直接提供獲取Nandflash(ROM)存儲總容量的接口。
既然沒有直接提供,那就想辦法吧。只要肯想,辦法總是有的。Nandflash說到底只是一種flash內存器件,對於Android設備來說,不管是4GB還是8GB的flash容量,Android系統最後都是通過對這塊Nandflash進行劃分利用,即所謂的分區。分區之後,Android各個分區才能各司其職,保證系統正常運行。那麼,對於一塊Nandflash,Android是怎樣進行劃分的呢?各個分區又各自佔用了多少容量呢?
下面簡單介紹一下Nandflash存儲容量的一些相關獲取和計算方式。


2.2 Nandflash 實際容量的計算

Android下面,查看各分區容量(實際容量),有好幾種方法,下面列出常用的兩種,即通過linux sys文件系統和proc文件系統查看分區信息。

2.2.1 方式一:使用sys文件系統計算ROM容量

首先使用以下命令查看block塊設備有哪些

ls /sys/class/block/

可以發現block目錄下有一系列類似的目錄,實際上,該目錄下的所有子目錄代表着系統中當前被發現的所有塊設備,其中,mtdbolck0 - mtdblock9 這十個目錄,便是設備系統對Nandflash進行分區所形成的block塊設備:
這裏寫圖片描述
隨便進一個目錄看看,看看有什麼東西,比如 mtdblock0, 可以發現mtdblock0下面還有好多節點或子目錄。
這裏寫圖片描述

其中有一個size節點,我們想知道的分區容量,便可以通過此節點獲取。cat命令查看size大小:
這裏寫圖片描述

可以知道 mtdblock0 的 size爲8192個單位 ,需要注意一下的是,這裏的顯示單位是records,1records = 512byte,也就是說,mtdblock0的容量大小爲:

8192 records = 8192 * 512 byte = 4 * 1024 * 1024 byte = 4 Mb

類似地,其他幾個mtdblock分區的大小,也可以通過以上的方式進行計算,而各個分區容量之和,便是這塊Nand-flash的存儲容量。

注意,這裏計算出來的,是Nandflash的 實際容量,而非標稱容量。至於Nandflash的標稱容量的計算,下面會介紹。

2.2.2 方式二:使用proc文件系統計算ROM容量

獲取各分區容量信息,還可以通過proc文件系統進行查看。我們知道,linux下面,通過 cat /proc/partitions 可以文件地知道系統本身的分區情況。同樣地,Android也可以通過這樣的方式查看分區信息。
這裏寫圖片描述

同樣可以清楚地看出有mtdblock0 - mtdblock9 10個分區,不僅如此,各個分區的容量信息也非常直觀地顯示了出來,如上圖紅色圈出來的部分。同樣需要注意的是,這裏的顯示單位是blocks,1blocks = 1KB。還是拿mtdblock0進行計算:

4096 blocks = 4096 KB = 4 *1024 KB = 4 MB

計算結果與上面 sys文件系統計算出來是一樣的!
將10個分區的容量之和相加,便可以得到Nandflash的存儲容量(實際容量)。比如shell下面,通過以下方式,便可以很快計算其容量和:

cat /proc/partitions | awk 'BEGIN{sum=0} {sum+=$3} END{print sum}'

這裏寫圖片描述

也就是說,Nandflash的實際存儲容量爲:3768320 KB = 3680 MB = 3.59375 GB

3768320 KB = 3680 MB = 3.59375 GB

將以上兩個步驟統一起來,統一爲一條命令來計算Nandflash容量(單位:GB):

cat /proc/partitions|awk 'BEGIN{sum=0} {if(NR>=3) {sum+=$3} } END{print expr sum/1024/1024}'

這裏寫圖片描述
通過以上兩種方式,便可以獲取到Nandflash存儲容量(實際容量)。

2.3 Nandflash 標稱容量的計算

前面說的Nandflash容量指的都是實際容量。那麼,怎麼獲取Nandflash的標稱容量呢,即4GB 或 8GB這樣的參數?還是同樣的,Android沒有提供直接的API接口供頂層調用。另外,通過以上介紹可以知道,通過分區信息也只能獲取到Nandflash的實際容量,難道還要像運行內存那樣,對獲取到的Nandflash實際容量進行向上取整,進而獲得標稱容量?
當然,使用向上取整的方式也是可以計算Nandflash標稱容量的. Nandflash標稱容量爲4GB的設備,實際容量爲3.59375 GB左右,取上取整能得到準確的 4GB。8GB的設備,實際容量爲7.2GB左右,向上取整也能得到8GB標稱容量。
但是,不排除某些異常情況下,比如flash內存顆粒出現問題(Nandflash驅動會自動跳過壞塊),這樣有可能導致8 GB的Nandflash計算出來的實際容量只有6.999GB的話,這樣向上取整隻能得到7 GB。因此,使用這樣的方式計算Nandflash標稱容量在某些極端情況下是存在計算誤差的!
那麼,除了向上取整,別無他法了麼?答案肯定是否定的,只要肯想,辦法總是有的!
前面我們一直在說Nandflash,卻忽略了一點,Nandflash 並不是一開始焊接到板子上面就可以正常使用的,這是需要內核Nandflash驅動支持的。那麼,Nandflash驅動會不會給我們留下一些信息呢?
通過查閱內核Rockchip Nandflash驅動源碼,發現一個驚喜,感覺裏面會有我們想要的貓膩!如代碼顯示的,Nand-flash驅動會在系統起來後,創建/proc/rknand文件系統.
這裏寫圖片描述

繼續跟蹤 rkNand_proc_read 函數:

這裏寫圖片描述

其中,rknand_base_version 應該是驅動版本號,是一個固定的值:
這裏寫圖片描述

本來還想繼續跟蹤 proc_ftlread和proc_bufread 源碼,發現Rockchip並沒有開源這部分代碼,而是以ko閉源庫的形式提供給我們使用。(我們設備內核版本是3.0.36+,對應的Nand-flash驅動爲:rk30xxnand_ko.ko.3.0.36+)
這裏寫圖片描述

既然Rockchip沒有開源Nand-flash源碼,那我們只好單刀直入,直接查看系統起來後 /proc/rknand節點信息了:
這裏寫圖片描述

可以看到,/proc/rknand節點爲我們提供了很多很多 Nand-flash 方面的具體信息:
比如前面說的rknand_base_version的版本號: rknand_base.c version: 4.40 20130420
比如 Flash ID: 9194d7ad
不過這些都與我們無關,我們關注的是,Nand-flash驅動有沒有爲我們提供存儲容量方面的信息.你注意到了麼,上圖中圈中的Device Capacity,這個就是設備的Flash容量,而且是標稱容量!
我們可以很直觀地知道,這塊Nandflash的標稱容量是4096 MB,也就是4 GB!
知道了這一點,獲取Nand-flash標稱容量便輕而易舉了:

cat /proc/rknand | grep "Device Capacity" | awk '{print $3}' (單位:MB)

這裏寫圖片描述

Java編程環境下,可以使用以下方式獲取:

    /**
     * 獲取設備Flash存儲容量
     * 
     * @author lzr
     */
    public String getDeviceCapacity(Context context) {

        String capacity = DEFAULT_DEVICE_CAPACITY_IN_MB;
        FileReader fileReader = null;
        BufferedReader bufferedReader = null;
        File file = new File(RKNAND_PATH);
        if(file.exists()) {
            try {
                fileReader = new FileReader(RKNAND_PATH);
                bufferedReader = new BufferedReader(fileReader, DEFAULT_FILE_SIZE);
                String line = null;
                while ((line = bufferedReader.readLine()) != null) {
                    if(line.indexOf("Device Capacity:") != -1) {
                        capacity = line.substring(line.indexOf("Device Capacity:")).replaceAll("\\D+", "");
                        Log.i(TAG, "get device capacity: " + capacity + " MB");
                        break;
                    }
                }
            }catch (IOException e) {
                Log.w(TAG, "couldn't get device capacity in " + RKNAND_PATH + ",storage capacity defaults to 4GB.");
                capacity=DEFAULT_DEVICE_CAPACITY_IN_MB;
            }finally {
                if (bufferedReader != null) {
                    try {
                        bufferedReader.close();
                    } catch (IOException e) {
                    }
                }
            }
        }else {
            Log.w(TAG, RKNAND_PATH + " not exist, storage capacity defaults to 4GB.");
            capacity=DEFAULT_DEVICE_CAPACITY_IN_MB;
        }

        return formatSize(context,Long.valueOf(capacity) * 1024 * 1024L);
    }

通過以上方式,對於RAM與ROM容量,就可以正確計算其標稱容量和實際容量了!


3. 再說點什麼

  • 以上對RAM及ROM的介紹,適用於Rockchip平臺。對於其他非RK平臺,可能計算方式稍微不一致,需要做適當的調整和修改。

  • 通俗一點來理解RAM和ROM,就是Android中的RAM和ROM分別對應電腦的內存和硬盤,內存負責程序的運行以及數據交換,有了它,電腦中的軟件才能運行,並有了進程;而硬盤就是一塊存儲空間,您可以存儲各種各樣的文件,包括視頻、照片、音樂、軟件等。

  • 在Android設備中,RAM決定了Android設備可以同時運行多少應用程序以及運行速度;而ROM決定了Android設備的存儲空間大小。ROM包含了安卓系統、軟件、用戶文件(照片、視頻等)。而用戶存儲的文件只佔據ROM空間,是不影響RAM空間的。其次,ROM空間的大小對系統運行速度的影響是微乎其微的;影響Android設備運行速度的最主要因素是RAM。

發佈了60 篇原創文章 · 獲贊 173 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章