2012年4月29日

創業的目的



http://mrjamie.cc/2012/04/30/phil-libin/

這篇文章真的寫得太好了
也讓我之前的疑惑有了解答

雖然文章裡說台灣為了錢創業的現象還好
但我身邊的人很多想創業都是為了錢

舉例來說
有參加過直銷說明會的人應該都知道
他們一貫的說法就是
這裡不是直銷,是在經營一個自己的事業!!
賺不賺錢,純看你的努力!!
有人可以月入十幾萬!!你一定也可以!!
結果就因為那句月入十幾萬就當了別人的下線
還沒月入十萬就先花了十幾萬幫人衝業績

這是一個很畸形的例子
因為這根本不是一個創業的行為
這就只是讓你跳進慾望的坑洞裡
讓妳為了錢賣命
最後一無所獲
甚至只會怪自己不夠努力才沒有收穫


如果是為了錢,Please DON'T do it.
好好當員工,領月薪,學會理財
可能還會賺得更多。

2012年4月26日

【JavaScript】Closure in for loop



我們通常會遇到以下情況

假設有個簡單網頁,所包含的元件如下

<ul>
    <li>123</li>
    <li>456</li>
</ul>

我們要給每個 li 加上一個 onclick 事件

滑鼠點擊後會 alert 順序的編號

為了讓程式聰明點

我們通常會使用 getElementsByTagName

和 foor loop 來 add event

例如:


var list = document.getElementsByTagName("li");
for( var i=0; i<list.length; i++){
list[i].onclick = function(){
alert(i);
}
}

但是這樣會發現一個嚴重的問題

每個 li alert的數字都一樣是2

為什麼?

因為當滑鼠按下時,做的動作是: alert(i);

而當時的 i 早就跑完迴圈變成 2 了

所以應該要這樣寫:


var list = document.getElementsByTagName("li");
for( var i=0; i<list.length; i++){
list[i].onclick = (function(index){
return function(){
alert(index);
}
})(i);
}

把重要的那部分拿出來研究一下:


        (function(index){
return function(){
alert(index);
}
})(i)

最外面的 ()(i) 的意思是執行裡面的 anonymous function

而裡面的 anonymous function 又 return 一個 function

return 的 function 做的事情是 alert(index)

index 又是  anonymous function 的 parameter

就是一個不被外部干擾的 Local variable

所以可以保證 alert 是我們想要的數字


一個看似成功的"手機"平台:Android


隱約記得,在我大三那年
我們學長就在玩著一堆Bug的Android
我還拿著我的Sony Ericsson K810i
只有試玩過那時候破爛破爛的windows mobile
當時對智慧型手機的看法就是:爛

一直到了去年
Android 修掉了大部分的Bug
把使用者感覺的到的問題都修正了
一切看起來很美好
到了Android 4.0 更是對UI做了大幅度的改進
但是Android隱藏的怪物
卻始終在那

不過說是怪物
不如說Android就是靠這賺錢的
如果這篇文章在2010或2011初的時候寫
我還可以大肆批評Android架構如何爛如何差(但其實我並不善於批評XD)
而且可能只有我或少數人能認同
(其實去年我在跟我身邊朋友討論時,多數人都不相信我說的)
到了2012年,我終於敢寫這篇文章了

因為這世界上,不再只有我這樣想
先來引述幾篇文章

2012-02-07
七種跡象表明,Android將被強勢的iOS拽出疾速增長的軌道
http://www.36kr.com/p/81192.html

這篇文章可能是我所看到的第一篇,敢跳出來戰Android的文章
當時下面的回覆可是熱鬧非凡(不過改版後回復都不見了?)
我當然也有跳進去湊熱鬧XD
在今年2月的時候
仍然有大多數人看好Android,不斷吐槽寫這篇文章的人

不過在短短兩個月內!!
是的,就是今年四月
2012-04-22
實時研究表明:相比於Android,iOS設備用戶活躍度佔絕對主導地位
http://www.36kr.com/p/102211.html

這結果我並不意外
比較讓我意外的是下面的回覆
竟然大多數人都贊同這篇文章的研究結果!

自此之後,不利於Android文章越來越多

2008年以來Google通過Android只撈到5.5億美元,通過iPhone收入達數十億
http://www.36kr.com/p/95345.html
Android:什麼情況?
http://www.36kr.com/p/103038.html
單個應用上每用戶貢獻平均收入,Amazon 大於iTunes,並遠超Google Play
http://www.36kr.com/p/103380.html
212-04-27
左有蘋果的 iPhone,右有 Amazon 的 Kindle Fire,Google 的 Andr​​oid 將走向何方
http://techorange.com/2012/04/27/where-should-google-go-with-android/

到底是什麼原因造成現在的局面?

就我所觀察
比較嚴重的有兩點(但都跟Android架構無關XDD)
1. 版本分裂,導致開發者開發Android App時難度增加
我想最常聽見的就是,要為了每種不同解析度的螢幕優化
實在快累死人~~
不過這種情況在Android 4.0被稍稍改善
但由於4.0市占率不高,加上有消息稱5.0就快發布了
我想這問題還會持續好一陣子。

2. Android App太容易複製、傳播
這應該就是嚴重影響,Google Play 上使用者付費意願的主要原因
大家應該都知道SPB Mobile Shell,一個很華麗的桌面應用程式
Google Play上定價快500台幣
在Android 世界裡,算是賣得不錯
但很不幸的,只要在google搜尋欄位輸入"spb mobile shell 5.0 破解"
還真的就找到免費完整版了...
更不用說其他軟體了

不過有人會說 iPhone 越獄後不也一樣嗎?
根據個人使用經驗
我用過Hero, Desire(都是老牌的了XD),一隻iPhone 3GS
Android刷機是一定要的,iPhone越獄也是必然的
就我體驗的結果是
我的iPhone雖然越獄了
但Cydia的搜尋功能真是爛的可以...
而且除非我知道我要哪個軟體
要不然我也只能對著搜尋欄位發呆XD
而Android 我也不知道為什麼
總是可以下載到最新最好用的東西
軟體、遊戲什麼都不缺~~
真是窮人的好手機啊!!!!!!!!!!!讚!!!!
(不過我現在都用iPhone居多....)

當然還有很多安全性議題的文章,在此沒有列出
因為其實越獄後的iPhone只比root 過的 Android安全一點點(在此呼籲有越獄的朋友們,一定要把SSH關掉或改密碼!!!)
(但沒越獄的iPhone可能就比Android安全許多)
主要還是因為apk太容易被拆開再組合回去
這動作看似沒有意義,但最大的意義就在於拆開和組合中間的過程
拆開後可以修改內遷廣告的ID(讓收益變自己的)
也有可能加入隱藏的回傳資訊程式碼(原本就需要GPS和網路的App來說,裡面加進一小段回傳資訊的程式碼也是很難被發現的)
再包回apk,任意散播至各大論壇

說了這麼多
Android 真的無法再進步了嗎?
其實他還是在成長的XD
而且Linux kernel 擁有高移植性
所以對其他裝置來說,仍然有很大發展性(如:電視、智慧家庭....等等)

就手機而言目前除了Apple以外已經沒有其他選擇了
我以前也是個Apple hater,但實在受不了Android 只好跳槽當自己所討厭的人XDD
所以我仍然在期待年底的Windows Phone !!
原因? 下次再說吧....累了XDD


--------------
2012-04-27
再補一篇
Android平台上的盜版概況
http://www.inside.com.tw/2010/08/30/the-piracy-in-android

2012年4月8日

【DIY kernel】為context switch做準備, 實作Task



這部分程式已經提交到gitHub

故不將所有程式碼貼在網誌上瞜~~



task 共有四種狀態,分別是 ready, running, block(類似在休息, 記憶體不會被釋放), close

目前無法真正的將cpu使用權切換給其他task使用

只能修改各task的狀態

等下次將context switch實作之後才會有作用

這部分程式主要就是在這些狀態中切換

所以需要

list_t ready_list[MAX_PRIO];
list_t blocked_list;
list_t termination_list;

這三種list紀錄某種狀態下有哪些task

然後用

u32int task_table[MAX_TASK_NUM];

來放所有task, 有task設為1其餘為0 (所以這個os只能run MAX_TASK_NUM 個 task)

最後還有一個

u8int prioExistFlag[MAX_PRIO];

這是為了取出priority最高的 ready_list 所建的table (array)。

task 的結構如下


struct task{
node_t node;

void *sp;
void *entry;
void *parameter;
void *stack_addr;
u16int stack_size;

u8int priority;

u32int init_tick;
u32int remaining_tick;

u32int task_id;
TASK_STATE state;
char name[NAME_MAXLENTH];

timer_t *timer;
};

比較特別的是 void *sp (stack point)這指向 task 的 stack

void *entry 這指向這task要做的事情的function

void *stack_addr 就是指向stack的開頭摟

總共要實作的function有這些


task_t *task_create( const char *name,
void (*entry)(void *parameter),
void *parameter,
u16int stackSize,
u8int priority,
u16int tick);
s8int task_start( task_t *task );
s8int task_delete( task_t *task );
void task_yield();
s8int task_sleep( u32int tick );
s8int task_suspend( task_t *task );
s8int task_resume( task_t *task );
void task_remove( task_t *task );
void task_addReady( task_t *task );
task_t *ready_task( u8int priority );
u8int get_top_prio();
u32int get_task_id();

static void task_timeout(void *parameter);

在task_create裡


task_t *task_create( const char *name,
void (*entry)(void *parameter),
void *parameter,
u16int stackSize,
u8int priority,
u16int tick){

task_t *task;
u32int *stackAddr;
u32int task_id;

task_id = get_task_id();
if( task_id < 0 ){
return NULL;
}

task = (task_t *)kmalloc(sizeof(task_t));
if(task == NULL)
return NULL;

stackAddr = (void *)kmalloc(stackSize);
if( stackAddr == NULL ){
kfree(task);
return NULL;
}

for( int temp=0; temp<NAME_MAXLENTH; temp++ ){
task->name[temp] = name[temp];
}

task->task_id = task_id;
task->entry = (void *)entry;
task->parameter = parameter;
task->stack_addr = stackAddr;
task->stack_size = stackSize;
task->node.next = NULL;
task->node.prev = NULL;

task->init_tick = tick;
task->remaining_tick = tick;
task->priority = priority;
task->sp = (void *)( (void *)stackAddr + stackSize -4 );

memset( (u8int *)task->stack_addr, '?', task->stack_size );
task->sp = (void *)init_stack(task->sp,
 task->entry,
 task->parameter);
task_table[task->task_id] = 1;

task->timer = timer_create(task->name,
  task_timeout,
  task,
  0,
  SET_ONESHOT);

return task;
}

首先會取得task_id

就是從task_table裡取出value是0的key

之後就是初始化的動作

其中的init_stack在下次context switch時再一併講解

其餘工具的演算法或流程也不難

從一個狀態切換到下個狀態主要是

從原本的list裡移除(critical region)再加入另一個狀態的list中

詳細程式碼請至gitHub下載或線上參考~~

https://github.com/herb123456/DIY_Kernel

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

後來想想,還是直接在這寫下 init_stack 吧XD

init_stack在 stack.c 裡實作

是每個 task 專屬的一塊記憶體

裡面放的東西長這樣:


之後context switch 時 會將程式狀態存在這塊stack裡

詳細流程會在下一篇在講~~

2012年4月7日

【DIY kernel】實作 timer



timer 要做的事情也不難

了解整個過程之後code就比較好理解

首先 timer create 之後就將 timer 加入 timer_list

之後在每100個clock發生的interrupt內檢查timer_list

是否有timeout的timer和不是periodic mode(週期模式)的timer

發生timeout就執行 timeout handler

不是periodic mode 就設為inactive

然後還有額外的控制函數

timer_stop, timer_delete, timer_control(可控制timer mode)

接下來的code只會在比較特別的地方做講解!

先定義 timer 的結構和狀態


#define NAME_MAXLEN 20

struct timer{

node_t node;

char name[NAME_MAXLEN];
u8int flag;
void (*timeout_func)(void *parameter);
void *parameter;
u32int init_tick;
u32int timeout_tick;
};
typedef struct timer timer_t;

#define ACTIVATED 1<<0
#define PERIODIC 1<<1
typedef enum{
SET_TIME = 0,
GET_TIME,
SET_ONESHOT,
SET_PERIODIC
} TIMER_CMD_TYPE;


接下來就實作會用到的 function


void init_system_timer(){

init_list( &timer_list );

}



timer_t *timer_create( const char *name, void (*timeout)(void *parameter), void *parameter, u32int time, TIMER_CMD_TYPE flag ){

timer_t *timer = kmalloc( sizeof(timer_t) );
if( timer == NULL ){
kprintf("timer == NULL \n");
return NULL;
}else{
kprintf("timer != NULL \n");
}
timer_init(timer, name, timeout, parameter, time, flag);
return timer;
}

void timer_init( timer_t *timer, const char *name, void(*timeout)(void *parameter), void *parameter, u32int time, TIMER_CMD_TYPE flag ){
if( timer == NULL )
return;
switch(flag){
case SET_ONESHOT:
timer->flag &= ~PERIODIC;
break;
case SET_PERIODIC:
timer->flag |= PERIODIC;
break;
}
timer->flag &= ~ACTIVATED;
timer->timeout_func = timeout;
timer->parameter = parameter;
timer->timeout_tick = 0;
timer->init_tick = time;
}



timer_list 是個 list_t 型態的全域變數

list_t timer_list;


接著是實作 timer_start (將 timer 丟進 timer_list裡,並按照timeout大小排列)
和 timer_check (檢查timer_list是否有timeout的timer)


s8int timer_start( timer_t *timer ){

if( timer == NULL || timer->flag & ACTIVATED )

return ERROR;
timer_t *ptimer;
node_t *pnode, *last_node;
timer->timeout_tick = get_tick() + timer->init_tick;
disableInterrupt();
if( !is_Empty( &timer_list ) ){
pnode = first_node( &timer_list );
last_node = &timer_list.tail;
while( pnode != last_node || pnode == NULL ){
ptimer = (timer_t *)pnode;
if( ptimer->timeout_tick > timer->timeout_tick ){
append_list(pnode->prev, &timer->node);
break;
}else{
pnode = pnode->next;
}
}
if( pnode == last_node ){
insert_rear(&timer_list, &timer->node);
}
}else{
insert_rear(&timer_list, &timer->node);
}
enableInterrupt();
timer->flag |= ACTIVATED;
print_list(&timer_list);
return OK;
}

void timer_check(){
timer_t *ptimer;
node_t *pnode;
u32int current_tick = get_tick();
disableInterrupt();
if( !is_Empty(&timer_list) ){
pnode = first_node(&timer_list);
while( pnode != &timer_list.tail ){
ptimer = (timer_t *)pnode;
if( current_tick >= ptimer->timeout_tick ){
remove_node(&ptimer->node);
ptimer->timeout_func(ptimer->parameter);
if( (ptimer->flag & PERIODIC) && (ptimer->flag & ACTIVATED) ){
ptimer->flag &= ~ACTIVATED;
print_list(&timer_list);
timer_start(ptimer);
}else{
ptimer->flag &= ~ACTIVATED;
}
current_tick = get_tick();
pnode = pnode->next;
}else{
//kprintf("while break \n");
break;
}
}
}
enableInterrupt();
}


接下來是工具


s8int timer_stop( timer_t *timer ){

if( timer == NULL || !(timer->flag & ACTIVATED) )
return ERROR;
timer->flag &= ~ACTIVATED;
disableInterrupt();
remove_node(&timer->node);
enableInterrupt();
return OK;
}

s8int timer_delete( timer_t *timer ){
if( timer == NULL )
return ERROR;
disableInterrupt();
remove_node(&timer->node);
enableInterrupt();
kfree(timer);
return OK;
}

s8int timer_control( timer_t *timer, TIMER_CMD_TYPE cmd, u32int arg ){
if( timer == NULL )
return ERROR;
switch( cmd ){
case SET_TIME:
timer->init_tick = arg;
break;
case GET_TIME:
return timer->init_tick;
case SET_ONESHOT:
timer->flag &= ~PERIODIC;
break;
case SET_PERIODIC:
timer->flag |= PERIODIC;
break;
default:
return ERROR;
}
return OK;
}



我在gitHub上開了個 project
有興趣的人可以去看看