2011年6月19日 星期日

Introduction cpufreq


Linux Device Driver是架構在mechanism和policy之間,Mechanism定義了應該提供哪些功能(what capabilities are provided),而policy定義應該如何使用這些功能(how the capabilities are to be used),這樣的分層可以簡化設計,因為policy或mechanism的改變,另外一個可以不需要更動。一般而言,Linux Device Driver都是policy free,只提供Device本身的capabilities,而沒有policy,有時候會在上面再設計一個policy,比如這次的主題cpufreq就提供了一些governors(performance、powersave、userspace、conservative和ondemand) 提供了一些調動CPU頻率的policy,然而每個CPU的CPU frequence的設定方式都不同,所以,每個CPU都有自己的driver來達到CPU frequency scaling,比如Intel的Enhanced SpeedStep或AMD的PowerNow!。

在cpufreq這個sub-system中也提供了一些sys的interface可以操控policy,這邊大概提一下governors.txt中提到的幾個重點。
首先,CPU的frequency policy我們稱為governors,共有Performance、Powersave、Userspace、Ondemand和Conservative等五種。您可以透過讀取/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors知道system提供了哪些的governors,也可以透過/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies了解CPU提供了幾種CPU frequency。透過讀取/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor可以知道現在的governor為何?而要改變governor則是寫入到該檔案,藉由讀取/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_frequencies可以讀取現在的CPU頻率。
    接下來介紹一下各個governor的規則,
  • Performance會always用最高的頻率執行,
  • Powersave會always用最低的頻率執行,
  • 當user使用Userspace時,可以讓user透過寫入/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed改變CPU的頻率,
  • Ondemand則會根據系統的loading來調整頻率,當系統的loading高於/sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold時,就會立刻將CPU調到最高頻率運行,之後再慢慢的降下來,
  • conservative和Ondemand類似,conservative有/sys/devices/system/cpu/cpu0/cpufreq/conservative/up_threshold/sys/devices/system/cpu/cpu0/cpufreq/conservative/down_threshold當系統loading超過up_threshold時,就會調高CPU的頻率,當低於down_threshold就會調降CPU的頻率,
由於ondemand變換CPU頻率過大,所以使用ondemand的CPU必須有能力快速切換CPU的頻率,不然很容易當機。

您也可以透過一些utility如cpufreq-info讀取相關資訊,基本上都還是透過讀取上述的那些檔案內容列印出來而已。

由cpufreq-info可以知道目前是acpi-cpufreq這個driver(應該猜得出是Intel的CPU),還有其他資訊。
    參考資料:
  • Linux Documentation / cpu-freq / governors.txt
  • Linux Documentation / cpu-freq / user-guide.txt
  • https://wiki.archlinux.org/index.php/CPU_Frequency_Scaling
  • http://blog.csdn.net/guoshaobei/archive/2010/12/21/6090359.aspx
  • http://software.intel.com/en-us/articles/enhanced-intel-speedstepr-technology-and-demand-based-switching-on-linux/



2011年6月5日 星期日

ELF之學習心得01


目前Linux的主要的可執行檔格式是ELF(Executable and Linking Format),ELF為COFF格式的後繼者,主要特徵是可擁有多個section,並且有32-bit與64-bit的數值用以區別其格式屬於32-bit或是64-bit。主要缺點是ELF設計時有一個假設,每個系統只會有一個ABI(Application Binary Interface),但是事實上這是錯的,如SYSV至少就有SVR、Solaris、SCO等ABI。(詳細內容請閱讀參考資料)

    ELF主要有三種類型的object files:
  • A relocatable file holds code and data suitable for linking with other object files to create an executable or a shared object file.
  • An executable file holds a program suitable for execution.
  • A shared object file holds code and data suitable for linking in two contexts. First, the link editor may process it with other relocatable and shared object files to create another object file. Second, the dynamic linker combines it with an executable file and other shared objects to create a process image.


這是ELF的layout,所謂的Linking View是指以檔案呈現之ELF(左圖),而Execution View則是指被載入到RAM上執行的ELF(右圖)。

    主要的section包含
  1. .text,存放程式碼的區域。
  2. .data用於存放已經初始化的變數。
  3. .bss用於存放未初始化的變數或者內容初始化為0的,該區域不占檔案空間。
  4. .rodata用於存放read-only data。
  5. 其他section和使用者自訂section後面再慢慢介紹。
這些以"."開頭的section為系統保留之section,使用者可以自訂section,但是應該避免使用"."開頭。
#include <stdio.h>

int i0 = 0;
int i1 = 1;
static int si0 = 0;
static int si1 = 1;
const int ci0 = 0;
const int ci1 = 1;
const static int csi0 = 0;
const static int csi1 = 1;

int main(void)
{
    return 0;
}


objdump -x a.out 

SYMBOL TABLE:
0000000000601034 l   O .bss     0000000000000004  si0
000000000060101c l   O .data    0000000000000004  si1
00000000004005b4 l   O .rodata  0000000000000004  csi0
00000000004005b8 l   O .rodata  0000000000000004  csi1
00000000004005b0 g   O .rodata  0000000000000004  ci1
0000000000601030 g   O .bss     0000000000000004  i0
00000000004005ac g   O .rodata  0000000000000004  ci0
0000000000601018 g   O .data    0000000000000004  i1
根據前面的規則用const修飾的變數會被放置在.rodata中,有ci0、ci1、csi0、csi1。未初始化的變數或者內容初始化為0的都會被放置在.bss中,有i0、si0。已經初始化的變數則放在.data中,有i1、si1。