Tuesday, August 14, 2012

RW 4.2 Mint Choco

RW 透過攔截Linux硬碟讀寫,將讀寫資料緩衝在高速儲存裝置(目前是記憶體),提升系統效能。

RW 4.2 Mint Choco 實現以下功能:
  1. 將系統讀寫過的硬碟資料緩衝在記憶體
  2. 關機時將緩衝資料寫回硬碟
  3. 每10分鐘會掃描緩衝的資料,把很少存取的資料寫回硬碟並釋放記憶體
我把 ArchLinux x64 + Gnome 3 裝在普通USB2.0隨身碟上,並載入 RW 進行測試,實際使用的效果相當不錯,常常測試完就懶的回去用原本的OS了。(其實是因為 Gnome 3.5 比 我原本OS的 awesome wm 好看多了...)

平常使用記憶體大概用掉2G,不過Chrome本身就用掉1G... (Chrome吃記憶體真是太可怕了)

風險和問題:
  1. 目前只在 ArchLinux x64 測試過,不確定是否能在 32bit OS 運作。
  2. 這版還在測試階段,所以只支援緩衝一顆硬碟。而且沒有容錯機制,所以請隨時注意記憶體剩餘量
  3. 還未提供保護機制,如果系統非正常關閉,有很大機會導致檔案系統毀損。(重開機時 fsck 可能可以修復,不過應該會有資料遺失)
RW Mint Choco下載: https://github.com/pzread/rw/tarball/mint-choco
編譯與安裝說明在檔案 INSTALL

fio 512MB隨機讀寫跟512MB循序讀寫測試: https://github.com/pzread/rw/blob/mint-choco/testdata/result
























Saturday, August 11, 2012

拼音輸入法

今天試了一下Linux下的拼音輸入法,一開始用 Google拼音輸入法,後來改用 ibus-pinyin。自動選字都比原來的新酷音好很多,不過對拼音輸入法拼音方式十分不熟悉。



Monday, August 6, 2012

Linux Driver打印資料到螢幕上

雖然有 printk , pr_alert 等函式可以把一些debug資料打印到螢幕跟log檔中,但是用起來總是不太方便(前面都會被加上打印的時間之類的)。

所以試著直接open tty設備,write資料到tty上,沒想到真的成功把資料打印在螢幕上。

PS. 打印資料到螢幕上應該是由User Mode程式來做才對,不過某些狀況就是不太允許這麼做 (ex. 正在關機時)


















Code:
struct file *tty;
mm_segment_t old_fs;

tty = filp_open("/dev/pts/0",O_RDWR,0);
//顯示在XWindows下的terminal所以用 /dev/pts/0 ,如果是一般文字界面下用 /dev/tty0

old_fs = set_fs(KERNEL_DS);

tty->f_op->write(tty,"Hello Screen!\n",strlen("Hello Screen!\n"),NULL);

set_fs(old_fs);
filp_close(tty,0);

Sunday, August 5, 2012

rw 硬碟讀寫緩衝展示

"rw" 利用Hook的方式,不需要重新編譯Kernel就可以提供記憶體緩衝硬碟讀寫功能,增加Linux執行速度。目前有一些問題尚未解決。

圖中測試環境是在安裝在USB 2.0一般隨身碟上的Linux,連續或隨機讀寫速度都超過200MB/s。



Tuesday, July 31, 2012

維基大典

剛剛才發現維基百科有文言版。電子在文言中稱作"子"嗎?


電晶體


電晶體者,電子儀器之本也。蓋西方有人自沙中煉藥,曰為硅。硅有十四子,其外圍有四,與別硅扣環,求其穩定。後西人於硅中參入磷,使其多一子,曰為負型;或參入硼,使其少一子,曰為正型。 後人以兩負型中夾以少量正型,或兩正型中夾以少量負型而用。其外觀如水晶,故名為電晶,取電之晶體也。 電晶有三極,名曰集基射。若以基輸以訊,射接於地,集接於電,可於集取得數倍於基之訊,故可取訊之放大效果也。 或以集輸以電,射接於地,基輸以是,可於射取得否。數電晶相乘,可判是非也。

http://zh-classical.wikipedia.org/wiki/%E9%9B%BB%E6%99%B6%E9%AB%94

Sunday, July 22, 2012

dmenu_wrapper 把dmenu候選按照使用頻率排序

dmenu 是一個輕量級的程式執行器,可以快速找尋你想執行的程式。

網路上其實有不少它的wrapper,可以讓 dmenu 顯示的候選選項按照被選到的頻率排序。不過一直找不到適合的來使用(如 Yeganesh  是用 Haskell 寫的,Haskell套件有點大),所以最後決定自己寫一個。


 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<dirent.h>
#include<limits.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<map>
#include<algorithm>
#include<string>

using namespace std;

char log[PATH_MAX + 1];
char path[65536];
char out[67108864 + 1];
char name[NAME_MAX + 1];
char tmp[4096];
map<string,int> dic;
pair<string,int> lis[262144];

bool cmp(const pair<string,int> &a,const pair<string,int> &b){
    if(a.second == b.second){
        return a.first < b.first;
    }
    return a.second > b.second;
}

int main(int argc,char **argv){
    int i;

    FILE *f;
    int prio;
    char *ptr;
    int fd;
    DIR *dir;
    struct dirent *dirent;
    struct dirent *result;
    struct stat st;
    map<string,int>::iterator it;
    int count;
    char *last;
    FILE *pipe;

    sprintf(log,"%s/.dmenu_wrapper_log",getenv("HOME"));
    if((f = fopen(log,"r")) != NULL){
        while(fgets(name,NAME_MAX,f)){
            name[strlen(name) - 1] = '\0';
            fgets(tmp,4096,f);
            sscanf(tmp,"%d",&prio);
            dic.insert(pair<string,int>(name,prio));
        }
        fclose(f);
    }

    dirent = (struct dirent*)malloc(sizeof(struct dirent) + NAME_MAX + 1);
    strcpy(path,getenv("PATH"));
    ptr = strtok(path,":");
    count = 0;
    while(ptr != NULL){
        fd = open(ptr,O_RDONLY);
        dir = fdopendir(fd);
        while(true){
            readdir_r(dir,dirent,&result);
            if(result == NULL){
                break;
            }
            fstatat(fd,result->d_name,&st,0);
            if(!S_ISREG(st.st_mode) || !(st.st_mode & S_IXUSR)){
                continue;
            }

            prio = 0;
            if((it = dic.find(result->d_name)) != dic.end()){
                prio = it->second;
            }
            lis[count] = pair<string,int>(result->d_name,prio);
            count++;
        }
        closedir(dir);

        ptr = strtok(NULL,":");
    }
    free(dirent);

    sort(lis,lis + count,cmp);
    strcpy(out,"echo -e \"");
    last = out + strlen(out);
    for(i = 0;i < count;i++){
        strcpy(last,lis[i].first.c_str());
        last += strlen(lis[i].first.c_str());
        strcpy(last,"\\n");
        last += 2;
    }
    last -= 2;
    strcpy(last,"\" | dmenu");
    last += strlen(last);
    for(i = 1;i < argc;i++){
        strcpy(last," \"");
        last += 2;
        strcpy(last,argv[i]);
        last += strlen(last);
        *last = '\"';
        last += 1;
    }

    pipe = popen(out,"r");
    name[0] = '\0';
    fgets(name,NAME_MAX,pipe);
    pclose(pipe);

    if(name[0] != '\0'){
        name[strlen(name) - 1] = '\0';
        
        if(fork() == 0){
            execlp(name,name,NULL);
        }

        it = dic.find(name);
        if(it != dic.end()){
            it->second++;
        }else{
            dic.insert(pair<string,int>(name,1));
        }

        if((f = fopen(log,"w")) != NULL){
            for(it = dic.begin();it != dic.end();it++){
                fprintf(f,"%s\n%d\n",it->first.c_str(),it->second);
            }
            fclose(f);
        }
    }

    return 0;
}
 

不能隨便將字串丟入strtok

雖然知道strtok會把傳入的字串切亂,剛剛還是把getenv("PATH")所取回的環境變數PATH丟進strtok,結果就發生奇怪的Bug

char *path;
char *ptr;

path = getenv("PATH");
ptr = strtok(path,":");
while(ptr != NULL){
    printf("%s\n",ptr);

    ptr = strtok(NULL,":");
}
//此程式的環境變數PATH已經被strtok切亂

execlp("ps","ps",NULL));
//execlp取到不正確的PATH,找不到ps這個程式

Saturday, July 14, 2012

Linux硬碟磁區讀寫保護

Block Driver層磁區讀寫保護,其實不太確定這個可以做甚麼...

用fdisk將原有的分割表清空,測試磁區 0 讀寫保護(MBR磁區)




















Reboot後正常啟動,分割表沒有被清空

Wednesday, July 11, 2012

Linux隱藏程序且不被Unhide偵測

透過一些不太標準的方法,可以隱藏指定程序,並且繞過隱藏程序檢查工具 Unhide 的偵測。

Source Code中隱藏程序的部份在hp_hook函式,其他的部份是把整個OS暫停。


由於隱藏程序過程如果發生進程切換,可能導致系統崩潰,但找不到新版本Linux Kernel中關閉整個OS進程切換的內建函式(以前有,但是新版Linux Kernel不希望開發者這麼做),只能關閉CPU單一核心進程切換(preempt_disable或是指令cli)。因此透過切換各CPU核心並執行preempt_disable,確定每個核心的進程切換都被關閉後才執行hp_hook函式。


目前發現在隱藏有視窗的程序時,執行Unhide檢測後,會出現奇怪的結果,原本該程序的PID沒被檢測到隱藏,但是檢測到原本不存在PID,原因不明。


Source Code:http://www.mediafire.com/?mroby9rj1uk2qc5
  1. 執行make編譯Driver,執行gcc -O2 app.c -o app編譯隱藏工具
  2. 先執行insmod hpmod.ko載入Driver,並執行./app (root權限),輸入要隱藏的PID
Hide vim前

Hide vim後,並確定vim正常運作

Sunday, July 8, 2012

FILCO Majestouch Ninja 87鍵茶軸開箱

Blog也多少應該發一些比較不那麼學術的東西:)


外盒,FILCO Majestouch NINJA Tenkeyless,還寫了一個"忍"


底面,有一朵有點詭異的紅花





















側面,型號是FKBN87M/EFB2,美式配置,茶軸,側刻鍵帽




台灣製造



盒子內部,配件蠻少的(跟Ducky比起來),有附上兩顆側刻版的Win鍵,忘記拍了...




鍵盤本體





















英刻的側刻鍵帽,其實打的時候除非光線真的很暗,不然還是喵的到字,不知道鍵位時(或是突然忘記?),足以辨識了





















跟Ducky一樣,都是斜的設計





















鍵盤燈其實不是很明顯,打字的時候會有點被鍵帽擋住





















拆下所有鍵帽,下面有一層塑膠底板,鐵板應該是在下面(之前用的Ducky 1087沒有塑膠板,鐵板直接裸露在外面)





















長鍵帽用的是平衡桿,Ducky是用衛星軸(一個鍵帽三個軸)





















長鍵帽下有扣環用來扣住平衡桿的鐵絲,應該可以拔下來(但是剛剛拔不下來,有點緊= =)





















最後是FILCO側邊低調的Logo,似乎是因為Ninja的關係,做成黑色的,其他款的好像是銀色的Logo






















用了一小段時間,感覺FILCO的品質真的相當不錯,做工細緻,多少會影響到打字的感受。
例如它的鍵帽就還蠻穩的,不會左右搖晃。側刻的設計其實打起來真的不錯,鍵帽摸起來很平滑舒服,突然忘記鍵位時還可以看一下。


我還是比較喜歡之前用的Ducky 1087的衛星軸設計,平衡桿沒弄好有時候會有怪聲,現在這把Backspace按鍵的平衡桿就有奇怪的咭咭聲XD,不知道是潤滑油不足還是甚麼原因。


跟同樣是87鍵的Ducky 1087比起來,這把鍵盤明顯比較重,多了一層塑膠上蓋應該也增加不少重量。

另外它的USB線是固定在鍵盤上的(Ducky是可以拔下來的設計),有時候帶出去線會卡到會比較不方便。

還有它的背面有兩根螺絲,直接被保固貼紙跟產品貼紙蓋住了(如下圖),根本就是不想讓你拆阿XD,不過據台灣FILCO代理商的售後服務非常好,還是不要亂動好了。


















不過FILCO沒有Ducky拉風的鍵盤絨布套阿XD (上面還有燙金的Ducky Logo),帶出去如果沒背背包的話,就只能直接拿在手上了。

補充一下,FILCO有出 Majestouch BLACKMajestouch NINJA 兩個系列的鍵盤,看起來都差不多,一樣是側刻,其實差異在BLACK是日文鍵盤,有多一些按鍵,NINJA則是一般比較常見的美式配置鍵盤。

Friday, July 6, 2012

Linux System API的分歧

Linux System API也太分歧了,同樣一個取得檔案屬性的API stat,system call就可以有
  1. stat
  2. lstat
  3. fstatat
  4. fstat
不同Linux平台還可以分64bit跟32bit版本(這可能是為了讓Linux Kernel可以在各種環境運作的關係,是頗有道理)

其實會發現fstatat只要傳入某些參數,其實幾乎完全可以取代stat跟lstat。
從Kernel Code來看,其實前3個函式實作上都只是簡單的前置處理,接著傳給一個 vfs_fstatat 函式作真正的處理。

不只stat,如getxattr,setxattr,listxattr,removexattr等都有這種狀況。

Windows的這方面就簡潔許多,Widnows有關檔案管理操作一切都從 CreateFile 開始,它會傳回一個Handle,之後不論任何有關該檔案的操作,皆使用這個Handle,並從這個Handle檢查權限,最後透過 CloseHandle 關閉Handle。

結果導致光虛擬化*stat跟*xattr就變成這樣。(如果在Windows下,其實*stat跟*xattr這類函式都不需要特別虛擬化,因為都是用Handle在操作,只要虛擬化 CreateFile 即可)


Thursday, July 5, 2012

部份完成ls指令相關虛擬化

經過多次的失敗跟嘗試,同功能的一段Code寫了數次後,完成虛擬化動作讓ls指令可以在虛擬化環境下正常顯示資料。

 完成syscall open,openat,lstat,getxattr,列舉資料夾檔案(readdir,getdents等)


Monday, July 2, 2012

Linux寫入資料到其他進程的記憶體

如果Process A要在Process B的某記憶體位置寫入資料,在Windows下可以使用Windows API WriteProcessMemory 。但在Linux下似乎找不到內建的相關函式可以用,或是相關的函式並沒有在Kernel中被導出(Export),因此經過測試,發現可以透過以下方法來實現。

Linux Driver函式透過syscall被呼叫時,虛擬記憶體User Mode部分是映射到呼叫syscall者的Process記憶體內容,因此像是copy_from_user之類的函式可以直接複製呼叫者的記憶體資料。

但是在這種情況下如果要寫入資料到其他Process的記憶體,就必須切換User Mode的映射。一般CPU的虛擬記憶體與物理記憶體映射對應是透過記憶體映射表,由CPU的CR3暫存器指向當前的記憶體映射表。


因此透過更改CR3暫存器,我們就可以暫時將User Mode的映射切換到其他Process,並透過copy_from_user或copy_to_user讀取或寫入到該Process。

部份Code(將Process A的資料複製到當前Process):
 
void *src;    //指向Process A的User Mode資料記憶體位置
void *dst;    //指向要寫入到當前(current)process的User Mode記憶體位置
void *buf;    //臨時緩衝區
int size;     //要複製的大小
struct task_struct *a_task;    //Process A的task_struct,a_task =  pid_task(find_vpid(Process A的PID),PIDTYPE_PID)
struct mm_struct *oldmm;

oldmm = current->mm;    //保存當前mm_struct
current->mm = a_task->mm;
current->active_mm = current->mm;    //如果當前Process不是一個Kernel Thread,active_mm = current->mm
load_cr3(current->mm->pgd);    //更新CR3
     
copy_from_user(buf,src,size);    //從Process A複製資料到緩衝區

current->mm = oldmm;    //恢復當前mm_struct
current->active_mm = current->mm;
load_cr3(current->mm->pgd);    //恢復CR3
     
copy_to_user(dst,buf,size);    //將緩衝區資料寫到當前Process的目標位置
 

一開始,我沒對current->mm和current->active_mm作替換,但是由於Linux在進程調度時,會根據current->mm載入CR3,為了避免呼叫完load_cr3後發生進程調度,導致CR3被改回去(經過測試,確定會發生此狀況),用preempt_disable()暫時關閉搶佔,保證從load_cr3到copy_to_user結束都不會發生進程調度。

但是後來測試時,發現對於size比較大時,會發生copy_to_user失敗的情形。追究原因,應該是因為copy_from_user和copy_to_user皆會發生Page Fault(複製時剛好該記憶體頁被置換出物理記憶體,這時會發生Page Fault,然後Linux去把該記憶體頁重新映射回物理記憶體中),但是關閉搶佔的情況下,是無法處理Page Fault,導致讀寫失敗。

Saturday, June 30, 2012

部份完成syscall open虛擬化


LASB(Linux Access SandBox)完成部份syscall open虛擬化

透過對於inode number的紀錄和處理,解決了ASB開發時遇到的FileSystem虛擬化問題,完成模擬
File and Dictionary
Symbolic Link
Hard Link

並透過NTFS的Open ID,此方法可以應用在ASB上解決問題


Thursday, January 19, 2012

Plextor 128GB M2P

外包裝




打開盒子




SSD本體




裝於筆電上,由於晶片組是HM55,需經過調整才能發揮完全效能

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\54533251-82be-4824-96c1-47b60b740d00\5d76a2ca-e8c0-402f-a133-2158492d58ad]
更改 Attributes 為 0
變更進階電源設定,處理器閒置停用改為停用閒置

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\intelppm]
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Processor]
Start改為4

測試平台:
Acer 4745G
SATA2 Intel RST 11.0.0.1032
Windows 7 64bit

調整前(C槽為安裝作業系統分割區)



調整後(並且在C槽安裝一些軟體和系統更新後測試)