2014年7月10日 星期四

do...while(0)的妙用

在C++中,有三种类型的循环语句:for, while, 和do...while, 但是在一般应用中作循环时, 我们可能用for和while要多一些,do...while相对不受重视。
    但是,最近在读我们项目的代码时,却发现了do...while的一些十分聪明的用法,不是用来做循环,而是用作其他来提高代码的健壮性。
1. do...while(0)消除goto语句。
通常,如果在一个函数中开始要分配一些资源,然后在中途执行过程中如果遇到错误则退出函数,当然,退出前先释放资源,我们的代码可能是这样:
version 1

bool Execute()
{
   // 分配资源
   int *p = new int;
   bool bOk(true);

   // 执行并进行错误处理
   bOk = func1();
   if(!bOk) 
   {
      delete p;   
      p = NULL;
      return false;
   }

   bOk = func2();
   if(!bOk) 
   {
      delete p;   
      p = NULL;
      return false;
   }

   bOk = func3();
   if(!bOk) 
   {
      delete p;   
      p = NULL;
      return false;
   }

   // ..........

   // 执行成功,释放资源并返回
    delete p;   
    p = NULL;
    return true;
   
}


这里一个最大的问题就是代码的冗余,而且我每增加一个操作,就需要做相应的错误处理,非常不灵活。于是我们想到了goto:
version 2
bool Execute()
{
   // 分配资源
   int *p = new int;
   bool bOk(true);

   // 执行并进行错误处理
   bOk = func1();
   if(!bOk) goto errorhandle;

   bOk = func2();
   if(!bOk) goto errorhandle;

   bOk = func3();
   if(!bOk) goto errorhandle;

   // ..........

   // 执行成功,释放资源并返回
    delete p;   
    p = NULL;
    return true;

errorhandle:
    delete p;   
    p = NULL;
    return false;
   
}


代码冗余是消除了,但是我们引入了C++中身份比较微妙的goto语句,虽然正确的使用goto可以大大提高程序的灵活性与简洁性,但太灵活的东西往往是很危险的,它会让我们的程序捉摸不定,那么怎么才能避免使用goto语句,又能消除代码冗余呢,请看do...while(0)循环:
version3

bool Execute()
{
   // 分配资源
   int *p = new int;

   bool bOk(true);
   do
   {
      // 执行并进行错误处理
      bOk = func1();
      if(!bOk) break;

      bOk = func2();
      if(!bOk) break;

      bOk = func3();
      if(!bOk) break;

      // ..........

   }while(0);

    // 释放资源
    delete p;   
    p = NULL;
    return bOk;
   
}


“漂亮!”, 看代码就行了,啥都不用说了...

2 宏定义中的do...while(0)
  如果你是C++程序员,我有理由相信你用过,或者接触过,至少听说过MFC, 在MFC的afx.h文件里面, 你会发现很多宏定义都是用了do...while(0)或do...while(false), 比如说:
#define AFXASSUME(cond)       do { bool __afx_condVal=!!(cond); ASSERT(__afx_condVal); __analysis_assume(__afx_condVal); } while(0) 
粗看我们就会觉得很奇怪,既然循环里面只执行了一次,我要这个看似多余的do...while(0)有什么意义呢? 
当然有!
为了看起来更清晰,这里用一个简单点的宏来演示:
#define SAFE_DELETE(p) do{ delete p; p = NULL} while(0)
假设这里去掉do...while(0),
#define SAFE_DELETE(p) delete p; p = NULL;
那么以下代码:
if(NULL != p) SAFE_DELETE(p)
else   ...do sth...
就有两个问题,
1) 因为if分支后有两个语句,else分支没有对应的if,编译失败
2) 假设没有else, SAFE_DELETE中的第二个语句无论if测试是否通过,会永远执行。
你可能发现,为了避免这两个问题,我不一定要用这个令人费解的do...while,  我直接用{}括起来就可以了
#define SAFE_DELETE(p) { delete p; p = NULL;}
的确,这样的话上面的问题是不存在了,但是我想对于C++程序员来讲,在每个语句后面加分号是一种约定俗成的习惯,这样的话,以下代码:
if(NULL != p) SAFE_DELETE(p);
else   ...do sth...
其else分支就无法通过编译了(原因同上),所以采用do...while(0)是做好的选择了。

也许你会说,我们代码的习惯是在每个判断后面加上{}, 就不会有这种问题了,也就不需要do...while了,如:
if(...) 
{
}
else
{
}
诚然,这是一个好的,应该提倡的编程习惯,但一般这样的宏都是作为library的一部分出现的,而对于一个library的作者,他所要做的就是让其库具有通用性,强壮性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。

Ref: http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html

2014年6月30日 星期一

typedef of function pointer

當你在宣告一個變數時是這樣的:
int ImVar;//<-----------------------1
當你在宣告一個函式時卻是這樣:
int ImFun(...);//---------------------2
變數宣告時名稱在最後面,而函式名稱卻在中間,
你會不會覺得這很奇怪?
本來用一個小括號括起來的參數定義就是函式名稱的附屬品
你可以當它是函式名稱的一部份。沒有了它函式名稱就不完整了。
(注意在C++中不同參數的同名函式在編譯器的內部函式名稱是不同的)

typedef int INT;//<------------------3
typedef int *PINT;//<--------------4
typedef int (*PINT);//<--------------5
3式是定義一個int的型態,名為INT
4式是定義一個int的指標型態,名為PINT
5式是定義一個指向int的指標型態,名為PINT
4式和5式的結果是等效的。

現在我們嘗試為函式定義型態:
typedef int IntFun(...);//<------------6
先注意到有關2式的說明,就不應再對為何函式名稱後還有(...)
6式定義一個型態(或返回)int函式,名稱為IntFun。
我們知道,函式名本身俱有隱性指標的性質,所以IntFun和 *IntFun是
等效的。
那麼可以明白的定義IntFun為指標嗎,應該可以的!直觀的感覺是套入
4式:
typedef int * IntFun(...);//<------------7
問題出來了,任何一個編譯器都會把7式解讀為:
定義一個型態(或返回)int *函式,名稱為IntFun。
這不是我們要的,那要如何指定指標('*')給IntFun而不是int呢?
答案就是括號,也就是套入5式而不是4式:
typedef int (*IntFun)(...);//<------------8
這就是原提問要的解答了,唯要注意的是
對型態的定義來說 4式和5式是等效的,
但對函式的定義來說6式和8式才是等效的;
那麼使用6式或8式效好?
一般都使用8弍,它有較好的可讀性,隱式指標總是令人較為困感的。
而且也不敢保證所有的編譯器都可以接受6式的敘述。

Ref: http://www.programmer-club.com.tw/ShowSameTitleN/c/25059.html

C 指標 函式指標 函式指標陣列

下面是一些範例(在64位元的機器中,指標為 8 bytes):
char (*p)[20];
sizeof(p) = 8
sizeof(p[0]) = 20
sizeof(p[1]) = 20
sizeof(*p) = 20
p =  malloc(sizeof(*p));
strcpy(*p, "Kenneth Kuan");
*p = Kenneth Kuan

char *p1;
p1 = (char*) malloc(sizeof(char)*20);
sizeof(p1) = 8
sizeof(*p1) = 1
sizeof(p1[0]) = 1
sizeof(p1[1]) = 1

char p2[20];
sizeof(p2) = 20
sizeof(*p2) = 1

char *p3[20];
sizeof(p3) = 160
sizeof(*p3) = 8
sizeof(p3[0]) = 8


每個函式名稱都是指向該函式的指標,當你建立名為 go_to_warp_speed(int speed)的函式時,你同時也建立了稱作 go_to_wrap_speed的指標變數。

建立函式指標:
int (*warp_fn)(int);
warp_fn = go_to_warp_speed;
warp_fn(4);

warp_fn(4); 跟呼叫 go_to_warp_speed(4)一樣。
在建立函式指標時,記得要指定回傳值型別和接受的參數。


enum response_type {DUMP, SECOND_CHANCE, MARRIAGE);
typedef struct {
    char *name;
    enum response_type type;
}

建立函式指標陣列:
void (*replies[])(response) = {dump, second_chance, marriage};

replies[DUMP] == dump
replies[DUMP]等同於dump函式的名稱

2014年6月25日 星期三

Linux Driver 開發概述

Device Driver 簡稱 Driver
裝置驅動程式用來將硬體本身的功能告訴作業系統,可視驅動程式爲硬體的靈魂,同時也可稱驅動程式為硬體和系統之間的橋樑。

裝置驅動程式可分為下列三類:
1. 字元裝置
    一個位元組(Byte)一個位元組讀取資料的裝置,一般會在驅動層實現 open(), close(), read(), write() and ioctl()等函數。
2. 區塊裝置
    一般是像磁碟一樣的裝置,進行讀寫時,每次只能傳輸一個或多個區塊,但是Linux可以讓應用程式像存取字元裝置一樣的存取區塊裝置。
3. 網路裝置
    主要是面對資料封包的接收和發送而設計的,網路裝置在Linux中是一種很特殊的裝置,不像字元裝置與區塊裝置的API函數,而是實現了一種通訊端界面,任何網路資料傳輸都可以透過通訊端來完成。

CPU有兩種指令:
1. 特權指令:Kernel mode可使用
2. 普通指令:Kernel mode and User mode可使用

模組是可以在執行時加入核心的程式,Linux kernel支援很多種模組,驅動程式就是其中最重要的一種,甚至檔案系統也可以寫成一個模組。利用insmod指令將模組加入正在執行的核心,也可用rmmod指令將一個未使用的模組從核心中刪除。

載入模組有兩種類別:
1. 靜態載入:模組在核心啟動時載入
2. 動態載入:在核心已經執行時載入

Note for C

printf
%p 被用來格式化位址 (16進位, e.g., 0x3E8FA0)
====================================================================
指標有時候會被稱為 reference(參考), *運算子可用來 dereference(解參考)指標.


struct, union, enum 這三者要一起看

typedef struct cell_phone{

...
...
...
} phone;
不需要像上面這種寫法,可以略過struct的名稱,直接定義別名(alias),如下面的寫法。
typedef struct {
...
...
...
} phone;
依照上述例子 phone 是別名
phone *myPhone;
//(*myPhone).xxx == myPhone->xxx
//上述兩式相等
struct結構中可以包含指向另一個struct的指標,但是struct本身不可以再包含完整的遞迴struct。因為C語言必須知道struct確切占據多少記憶體空間。


union的用法與struct相同,但是union只會針對它所定義的欄位之一配置記憶體空間,電腦將提供該union足以存放其最大欄位的空間。
typedef union {
    short count;
    float weight;
    float volume;
} quantity;
quantity q = {.weight=1.5};
上述初始化等同於,下面這種寫法
quantity q;
q.weight = 1.5;


enum讓你可以列舉出一序列的符號,像下面這樣:
enum color {RED, GREEN, PUCE};


bitfield可以讓我們儲存自訂數目的位元,並且應該被宣告為unsigned int。
例如:
typedef struct {
    unsigned int first_visit:1; //表示該欄位只占用一個位元(1bit)
    unsigned int come_again:1;
    unsigned int figner_lost:4;
    unsigned int shark_attack:1;
    unsigned int days_a_week:3; //表示該欄位占用三個位元(3bit)
} survey;


配置與釋放必須一對一
從heap配置動態記憶體 void *p = malloc(sizeof(int)*4);
釋放記憶體 free(p);

如何配置動態二維陣列?
如欲配置一[m][n]的二維陣列
有下列幾種作法
(ㄧ)
int **Array, *pData; 
int m,n,i; 
Array = (int**)malloc(m*sizeof(int *)); 
pData = (int*)malloc(m*n*sizeof(int)); 
for(i = 0; i < m; i++, pData += n)
Array[i] = pData;
只需做兩次malloc,free只要free Array和Array[0]就可以了
(二)
int i;
int **Array;
Array = (int **)malloc(m*sizeof(void *));
for (i = 0; i < m; i++)
Array = (int *)malloc(n*sizeof(int *));
這樣子的配置方式要做很多次的malloc,,並容易造成記憶體碎片化(memory fragment)
(三)
int i;
int **Array, *pData;
Array = (int **)malloc(m*sizeof(int *)+m*n*sizeof(int));
for (i = 0, pData = (int *)(Array+m); i < m; i++, pData += n)
Array[i]=pData;

這樣是最簡便的寫法 只要mallocㄧ次完成,free只要free Array即可

Ref: http://chiakie.pixnet.net/blog/post/3143518-%5Bc%5D-%E5%A6%82%E4%BD%95%E5%8B%95%E6%85%8B%E9%85%8D%E7%BD%AE%E4%BA%8C%E7%B6%AD%E9%99%A3%E5%88%97

GCC make 編譯 C 程式

gcc -c *.c
-c 告訴編譯器你想要為每個原始檔建造目的檔,但是沒有將之連結產生完整的可執行程式

gcc *.o -o a.out
將目的檔連結在一起,並且產生完整的可執行程式(a.out)

make所編譯的每個檔案被稱作 target
針對每個target,make必須被告知兩件事情:
1. dependencies (依存項目): target 將從哪些檔案產生
2. recipe (執行指令): 產生檔案所需要執行的一組指令

關於 target, dependencies and recipe的所有細節都必須被儲存在一個稱為 makefile or Makefile的檔案中。

launch.o: launch.c launch.h thruster.h
        gcc -c launch.c

綠色的部分為target
藍色的部分為dependencies
紅色的部分為recipe
紫色的部分為TAB,所有的recipe必須以TAB字元開頭

進階一點的話可以參考更自動化的工具 autoconf
Ref: https://www.gnu.org/software/autoconf/
Example: http://www.ibm.com/developerworks/cn/linux/l-makefile/

2014年6月24日 星期二

Python 標準輸入

#/usr/bin/env python 

import sys 

counter = 1 
while True: 
        line = sys.stdin.readline() 
        if not line: 
                break 
        print "%s:%s" % (counter,line) 
        counter += 1

2014年6月18日 星期三

unix 系統基本指令



[控制鍵]: 首先要了解在下命令時一些控制鍵的用法 :

  Ctrl-U 刪除整行命令行
  Ctrl-W 刪除命令行的最後一個字(Word)
  Ctrl-C 中斷程式或 shell script
  Ctrl-Z 暫停程式或 shell script
  Ctrl-S 暫停往下顯示
  Ctrl-Q 繼續往下顯示
  Ctrl-O 不要程式的輸出, 但不中斷程式
  Ctrl-D 終止檔案輸入(EOF), 或 Logout

與檔案目錄有關的特殊字元

  .  現在目錄 (一個句點)
  .. 上一層目錄 (兩個句點)
  ~ User 之主目錄 (老鼠尾巴)
  ?  檔名之單一字元 (問號)
  *  檔名之所有字元 (星號)

以下摘錄 unix 較常用之命令, 其中也包含了部份 csh 之 Built-in commnad :

ls 顯示目錄內容, 同 DOS 之 DIR
  ls -al  詳細顯示此目錄內的所有檔案 (包含以 . 開頭之隱藏檔)
  ls *.c  顯示此目錄內的所有結尾為 .c 的檔案 (unix 無所謂附檔名)

cd切換目錄
  cd  切換目錄至您的主目錄
  cd ..  切換目錄至上一層目錄
  cd /usr/bin  切換目錄至 /usr/bin

pwd 顯示現在目錄的路徑

2014年6月17日 星期二

處理 command-line options using getopt()

$./order_pizza -d now -t Anchovies Pineapple
Output:
Thick crust.
To be delivered now.
Ingredients:
Anchovies
Pineapple

2014年6月13日 星期五

記憶體與指標

int doses[] = {1, 3, 2, 1000}
int *t = doses;
//doses[3] == *(doses+3) == *(3+doses) == 3[doses]

//sizeof(doses) == 16

//sizeof(t) == 4(32bits) or 8(64bits)
//傳遞陣列變數給指標會發生退化(decay)

//不可做指標乘法但可以做指標加法


//使用fgets來取代scanf,因為fgets的function signature中,長度是必要項


//避免這樣的寫法 char *s = "Some string";
//改用這樣的寫法 const char *s = "Some string";
//因為字串 "Some string"本身存在於唯讀記憶體區段,好的寫法可以避免產生這種錯誤
//s[0] = 'S';

//declaration 宣告是一段程式碼,聲明某個東西(變數, 函式等)存在
//definition 一段程式碼

$(./bermuda | ./geo2json) < spooky.csv > output.json
//此命令利用管線(|)將行程(bermuda)的標準輸出連結到另一行程(geo2json)的標準輸入,並利用括弧將兩支獨立的程式當成單一程式,標準輸入的資料(spooky.csv)透過redirect standard input operator(<)來重導向至行程(bermuda),並且透過redirect standard output operator(>)來將行程(geo2json)之標準輸出導向檔案(output.json)。

FILE *in = fopen("i_dont_exist.txt", "r");
//Not Safety

FILE *in;
if (!(in = fopen("i_dont_exist.txt", "r"))){
  fprintf(stderr, "Can't open the file.\n");
  return 1;
}
//Safety

2014年4月28日 星期一

C++ Nested Classes 巢狀類別

在巢狀類別結構中,外部類別不能存取內部類別的私用成員,如果想要存取內部類別的私用成員的話,必須宣告外部類別為friend,例如:
class PointDemo {
    ...

private:

    // Nested Class
    class Point {
        friend class PointDemo;
        ....
    };
    ....
};

2014年4月25日 星期五

Syntax error: Bad for loop variable

PROBLEM DESCRIPTION

for ((i=1;i<=100;i=i+1))
do
echo "$i"
done

執行以後
顯示
test2.sh: 1: Syntax error: Bad for loop variable

SOLUTION

把dash關掉
sudo dpkg-reconfigure dash


2014年4月24日 星期四

DynamoDB vs MongoDB NoSQL


I recently migrated my MongoDB to DynamoDB, and write 3 blogs to share some experience and data about performance, cost.

Migrate from MongoDB to AWS DynamoDB + SimpleDB

NoSQL Database 101

用NoSQL解決資料庫不斷擴充的維護問題
NoSQL (Not Only SQL)資料庫是一個統稱的名詞,泛指哪些非關聯式資料庫的資料庫技術,包括了數十種不同類型的資料庫系統,因為這些資料庫大多沒有支援標準的SQL,例如知名的Google BigTable、Amazon S3的Dynamo資料庫,或是微軟Azure平臺儲存資料的方式,都屬於NoSQL資料庫的其中一種。

常見的NoSQL資料庫有4類:

  1. 圖學資料庫(Graph Database)
  2. 文件導向的資料庫(Document-Oriented Database)
  3. Key-Value Store分散式資料庫
  4. 記憶體快取為主的資料庫

2014年4月22日 星期二

About the L4Linux scheduler

Hi,

On Sun Sep 30, 2007 at 12:29:27 +0900, Lin wrote:
> I have some questions about the scheduler system on DROPS L4Linux.
> I would like your help or some hints.
> The version of my source is ...
>   DROPS SVN revision   : 205
>   L4Linux SVN revision : 61
>   Fiasco version       : 1.2
>   L4Linux version      : 2.6.22
> In L4Linux system (on L4Env), there are two schedulers (in Fiasco
> and in Linux server), you know.

Yes, multiple schedulers may exist on the system.
> Some papers say any Linux user process consists of L4 task and the L4
> shceduler schedules all L4 thread.
> It is ok, but I can't understand the work of the Linux scheduler.
> In fact, a new thread is created in L4 when a process (has one thread)
> is created in Linux, and the active thread is changed when the context
> switch occurs in Linux server (made sure by using Fiasco JDB).
> I want to make this relation clear.
> In other words, what does the Linux scheduler do at these time.

In genernal, the Linux scheduler doesn't do anything special, it just
lives in its Linux world and schedules Linux processes. The Linux
scheduler doesn't know about L4.
> 1. Task creating
> ~~~~~~~~~~~~~~~~
> When "fork()" (or such functions) is called, the function:
>   l4x_setup_next_exec (in "arch/l4/kernel/arch-i386/dispatch.c")
> may be called.
> This function seems push the argument function "ret_from_fork" to the
> stack of the new "task_struct" instance to execute it first when the
> task is scheduled.

Yes.

> Then, when "fork()" ends (when "do_fork()" returns), the new
> "task_struct" instance is created in Linux system.

do_fork and its helpers are allocating this new process, so when fork
returns the new process is already there.

> At this time, is the L4 thread (task ?) corresponds to that
> "task_struct" is not created yet ?
> (I assume it is created after the "task_struct" is scheduled.)

The corresponding L4 task is created when necessary, i.e. when this
task was actually scheduled and should run some user code.

> 2. Linux server's scheduling
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> In L4Linux task, there are 7 threads and IRQ threads:
>   (1)l4lx.rm       (2)l4lx.sem      (3)l4lx.main     (4)l4lx.tamer
>   (5)l4lx.cpu0     (6)l4lx.timer.i0 (7)l4lx.idler    ...
> "l4lx.main" creates "l4lx.cpu0" (Linux server) and waits this end.

> "l4lx.cpu0" does many initialization in the function "start_kernel()",
> and then it reaches at the function:
>   l4x_idle (in "arch/l4/kernel/dispatch.c").
> In this function, the Linux server creates the thread "l4lx.idler"
> and then enters the scheduling and IPC waiting loop.
> What does this function do ??
> (My expectation about it is written in 4.)

It's the idle thread. It is running when no other activity is in the
L4Linux system. It just sits there are waits for things to happen.

> And more, What is the thread "l4lx.idler" used for ??

It wakes up the idle thread when work is to be done.
> 3. Scheduled new Linux task
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~
> The function "switch_to()" (depends on L4 arch) in Linux kernel only
> saves and restores the registers ESI, ..., ESP, and EIP.
> So, when all new created "task_struct"s are scheduled by the Linux
> server, they runs from "ret_from_fork" as the Linux server thread.
> (Is it right ?)   ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^

ret_from_fork is the first function a newly created process is
executing.

> "ret_from_fork" reaches at the function:
>   l4x_user_dispatcher (in "arch/l4/kernel/dispatch.c").
> It calls "l4x_spawn_cpu_thread()" before its loop.
> I assume it creates the new L4 thread corresponds to the now scheduled
> "task_struct" in Linux server.

Yes.

> And, the loop in "l4x_user_dispatcher" seems to reply or wait page
> fault, exception and system call IPCs from any L4 thread runs as a
> Linux user task.
> What does this loop do in fact ??

It handles request from a user process, i.e. system calls, page faults,
exceptions etc. It receives the requests, handles them and replies
again.

> When the context switch occurs in Linux server for some reasons,
> the active L4 thread is also switched almost at the same time.
> (I see it by using "ps" on Linux and the thread list of JDB on L4.)
> I want to know the mechanism of this synchronization.
Only one user process is running at a time, i.e. when the user
dispatcher is waiting for an incoming message, a user process is
running. If the user dispatcher is not waiting, no user process is
running.
> 4. Summary
> ~~~~~~~~~~
> My main quiestions is ...
>   (1) What is "l4lx.idler" created for ? (in 2)
>   (2) What does the function "l4x_idle" do ? (in 2)

Hopefully answered.

>   (3) Do all Linux user tasks ("task_struct" instance) only execute
>       "l4x_user_dispatcher" (from "ret_from_fork") as the Linux
>       server ? (in 1 and 3)

Yes, all user processes run in the user-dispatcher loop.

>   (4) What does the function "l4x_user_dispatcher" do ?
>       How to switch contexts in Linux and in L4 almost at the same
>       time ? (in 3)

Context switching in L4 is done by the kernel (Fiasco). Also note that
the L4Linux server itself runs in an L4 thread and thus Fiasco is doing
context switches when switching from a user process (L4 thread) to the
L4Linux server (another L4 thread). This basically happens when the IPCs
are sent. The context switch in the other direction happens when the
L4Linux server replies the user process.
The context switches in the Linux server happen inside the schedule()
call, the L4 side is not affected by this, as it basically only means
that the Linux server switches to another stack.

> My expectation about Linux scheduling system is the following:
>   - When there is no need to reschedule Linux user processes, Linux
>     server is in IPC sleep and waiting the wakeup IPC in "l4x_idle".

Yes.

>   - If Linux server gets IPC for some reasons, it wakes up and check
>     the IPC sender. Then, if the sender is a thread corresponds to
>     certain Linux task, Linux server wakes up this Linux task and
>     reschedules by calling "schedule()".

I don't quite understand what you want to say. If the Linux server gets
an IPC it has to handle this request (Pagefault, syscall...). If the
Linux system wants to reschedule, schedule() is called so that another
context may be selected.

>   - The waked up task will be active as Linux server. This context
>     may execute only "l4x_user_dispatcher" which replies and wait IPCs
>     and handles page faults and exceptions based on information of the
>     received IPC.

Basically yes, but the kernel-side context of the user process will be
running.

>   - When the L4 thread of the Linux task exits, that Linux task in
>     Linux (task_struct instance) also is freed. If there is no
>     schedulable task in Linux at that time, the original context
>     (executes "l4x_idle") is re-scheduled.

There's always one process active in Linux (init). Idle is actually
process 0 so this would be 'running' then.


Adam
-- 
Adam                 [EMAIL PROTECTED]
  Lackorzynski         http://os.inf.tu-dresden.de/~adam/

_______________________________________________
l4-hackers mailing list
l4-hackers@os.inf.tu-dresden.de
http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers

======================================================

L4 Fiasco's scheduling in Multi-Core

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

> Suppose we have 2 cores (core 0 and core 1) and we have 2 tasks
> (task A and task B). And I assign all threads of task A to run in
> core 0 and all threads of task B to run in core 1. How L4 Fiasco's
> scheduler manages this? Will the tasks run together or they have to
> switch from one to another?
>> From what I understand, the tasks don't run together regardless
>> which core
> they are located, is it correct?

Fiasco's scheduler is only concerned with the threads you are running.
In your example, the threads of task A will be scheduled independently
from the threads of task B because they run on different cores. Each
core maintains a separate run queue. The scheduler schedules these
threads round-robin by their priority. If all your threads have the
same prio, CPU time will be distributed fairly among these threads.

Note that tasks in the L4 context are address spaces, i.e. what other
OSes would call processes. Do not confuse them with the term task as
it is used in real-time systems.

Kind regards,
Bjoern
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: Using GnuPG with Icedove - http://www.enigmail.net/

iEYEARECAAYFAlMpaooACgkQP5ijxgQLUNlpXACgk/bc/8BoYLZAFHrOP6L/DIjm
XVAAoIog+ebRIj9uaRmRWPLgDI7zQ/kh
=YNFG
-----END PGP SIGNATURE-----

_______________________________________________
l4-hackers mailing list
l4-hackers@os.inf.tu-dresden.de
http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers

2014年4月10日 星期四

C++ 繼承物件之 (virtual) 函數呼叫

下面程式輸出之結果為:
print from A
print from B
print from A

前兩行為 constructor 輸出,根據最後一行之輸出可以得出下列結論,當一個物件B被parent物件A 的指標指定時 (A* ptrA = &objB;),使用 (ptrA->y();) 會呼叫物件A的function (y();),若想呼叫物件B的function (y();),要在class A的定義中將 (void y();) 宣告成 (virtual void y();)。

所以,衍生物件呼叫哪一個function是由當下的變數所決定而不是只看宣告。
=================================
#include <iostream>

using namespace std;

class A
{
public:
A();
~A();
void y();
        //virtual void y();
void print();

private:

};

2014年4月7日 星期一

Using L4Linux on Fiasco.OC - How?


Hi Andreas,

On Mon Aug 09, 2010 at 15:37:42 +0200, Andreas Speier wrote:
> I just started porting some Projects running on L4Linux on the "old"
> Fiasco to Fiasco.OC with the current L4Linux version.
> Starting with the "hello" example of the documentation was no problem,
> but I could not find out how things have to be configured when using
> L4Linux.
> Which dependencies must be regarded to make it run properly?
> Is there any documentation I could use, or can anyone publish some
> example documentation and configuration to run L4Linux on Fiasco.OC?

The full snapshot (the big one) contains a simple L4Linux config without
any connection to anything else. There L4Linux is started as any other
program.

For example to get a L4Linux with a framebuffer you can look at the
example in conf/examples/x86-fb.cfg and exchange the start of
ex_fb_spectrum with vmlinuz.

To give host devices to L4Linux, make sure to enable the virtual PCI bus
option in L4Linux. Then add a new virtual io bus in the config (in the
start script and in the io config) and plug the devices you want there
(e.g.  dev => wrap(hw-root.match("PCI/CC_02")); to get all PCI network
cards). Give this io-bus to L4Linux in the config script via
'vbus = io_busses.l4linux' in the caps listing of L4Linux.



HTH,
Adam
-- 
Adam                 adam at os.inf.tu-dresden.de
  Lackorzynski         http://os.inf.tu-dresden.de/~adam/

http://os.inf.tu-dresden.de/pipermail/l4-hackers/2010/004456.html

2014年3月31日 星期一

simulation 與 emulation 的簡單分法

simulation
用軟體做的模擬,通常是指純軟體
==========================
emulation
用硬體做的模擬,主要是硬體加上些許軟體的配合

2014年3月28日 星期五

常用 Linux 指令

==================================
​grep -n -r 'Vcpu' ./​
-n 顯示行號
-r 遞迴搜尋
-I do not search binary files
==================================
find ./ -iname 'vcpu*'
-iname 不分大小寫
==================================
ls -lrt
-l use a long listing format
-r reverse order while sorting
-t sort by modification time, newest first
==================================
一般在指令的使用上常會用到重新導向運算元,linux下的重導運算元分為以下幾種:
< 把檔案內容重新導向為標準輸入
> 把標準輸出重新導向到檔案內容中(若檔案已存在,原先的內容會被覆蓋)
>> 把標準輸出重新導向到檔案內容中(若檔案已存在,新的內容會加在舊的之後)
2> 把標準錯誤訊息重新導向到檔案內容中(若檔案已存在,原先的內容會被覆蓋)
2>> 把標準錯誤訊息重新導向到檔案內容中(若檔案已存在,新的內容會加在舊的之後)
&> 把標準輸出和錯誤訊息重新導向到檔案內容中(若檔案已存在,原先的內容會被覆蓋)
==================================

2014年3月27日 星期四

Using std::find_if on a vector of object

std::vector<Req*> RWbuffer;

Req* rm_req;

struct Comp_Req
{
explicit Comp_Req(Req* i):n(i) {}
inline bool operator()(const Req* m) const { return m == n;}
private:
Req* n;
};

it = find_if(RWbuffer.begin(), RWbuffer.end(), Comp_Req(rm_req));

if (it != RWbuffer.end())
{
  /*
  Do something before Req* remove from RWbuffer
  */
  RWbuffer.erase(it);
}else
{
  cout << "Request not found! Cannot remove! " << endl;

}

http://stackoverflow.com/questions/6679096/using-find-if-on-a-vector-of-object

Complete Example of using a string as delimiter to parse (split) a string

/*
** Complete Example of using a string as delimiter to parse (split) a string
**
std::string s = "scott>=tiger>=mushroom";
std::string delimiter = ">=";

size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
std::cout << token << std::endl;
s.erase(0, pos + delimiter.length());
}
std::cout << s << std::endl;
*/

http://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c

2014年3月21日 星期五

Blogger Code block _ 文章顯示程式碼區塊

Blogger許多插件需要修改HTML加入一些程式碼(語法),在爬文搜尋blogger功能教學時,常會看到教學文通常會把插件的程式碼框起來,避免和文章內容混合,方便訪客複製語法添加到自己的部落格。

如何在Blogger文章中有顯示程式碼區塊的效果呢?我本身不懂程式語法,搜尋教學和試驗過程花了不少時間。剛開始整段程式碼跑到部落格最上方,改變插入位置修正這個問題,卻又不能正確顯示出區塊,反覆的搜尋&修改,終於順利增加程式碼區塊功能,以下說明如何增加也幫自己留下筆記。

在HTML中插入一段程式碼,CCS程式碼:
.post code {
display: block; /* fixes a strange ie margin bug */
font-family: Courier New;
font-size: 10pt;
overflow:auto;
background: #f0f0f0 url(http://klcintw.images.googlepages.com/Code_BG.gif) left top repeat-y;
border: 1px solid #ccc;
padding: 10px 10px 10px 21px;
max-height:250px;
line-height: 1.2em;
}


操作說明:
Blogger 後台 →「範本」→「編輯HTML」。(請先備份範本,觀看範本備份說明)


尋找/* Posts的位置,用瀏覽器尋找( F3) 能快速找到。


CCS程式碼插入/* Posts下方,儲存範本。


想顯示的程式碼需將 < 改成&lt;和 > 改成&gt;,沒有修改符號會被視為要執行的指令,指令執行後就無法順利顯示(備註:&lt;用全形輸入,修改時用半型)。

若是手動修改麻煩,HTML Encoder網頁提供轉換程式碼,可將<>兩個符號自動轉換,將程式碼貼上點擊「Encode」。


編輯文章時在程式碼前後各加上 <code> 和 </code> 就能顯示。


顯示效果如下:
程式碼

參考文章:
[筆記]在文章裡顯示優質的程式碼區-良人的大秘寶
在Blogger文章中插入程式碼-高登工作室

[C++] 如何在template 善用typename ?

在編譯其他人的Program 時發現的。(也多虧這些人有釋出這種奇奇怪怪的code,
我才發現g++ 編譯器在處理template時是怎麼運作的。)
example:
template<typename T>
class A{
public:
    T m_A;
    void funcTest()
    {
        map<T , int> mapTempTable; /* 這部分沒問題, OK! */
        map<T, int>::iterator it;  /* 編譯器會出錯! */
    }
};
第8行如果這樣子寫的話,g++ 編譯器會出錯!硬是要在前面加個typename 變成:
typename map<T, int>::iterator it;
才能夠解決!
這是為什麼呢? 因為:: scope operator 接在它後面的可以是成員變數、函數或是
物件類型。
如果不加上typename的話,編譯器可能會將iterator 誤認為成員變數。
(實際上iterator是一個物件類型)
所以要加上typename,讓編譯器知道這個東西是一個物件類型。
Ref:

2014年1月24日 星期五

Building Fiasco on x86

Preparing for Build

  1. Download l4re-snapshot-xxx.tar.xz from http://os.inf.tu-dresden.de/download/snapshots-oc/
  2. Open /etc/profile file, add the below line. It will set the PATH permanently.
    export PATH=/home/beam/workspace/l4re2013091917/bin:$PATH

Build Fiasco

  1. $ cd /unpacked_path/src/kernel/fiasco
  2. $ make BUILDDIR=mybuild
  3. $ cd mybuild
  4. $ make config
    In config menu, choose as the following items: (lscpu command helps u to print the information about OS)
    • Target configuration:
      • Architecture: IA-32
      • CPU: Core 2
    • Kernel options:
      • Enable multi processor support (NEW): 4
  5. $ make