2015年9月14日 星期一

Telling gcc directly to link a library statically

gcc -lx264 動態連結
gcc -l:libx264.a 把 libx264 靜態連結到目標檔案中
神奇的 -l: 功能!(注意:多一個)

2015年9月4日 星期五

解決CI網頁圖片路徑問題

因為CodeIgniter會改寫網頁網址, 使得原本圖片的相對路徑會壞掉
例如:
http://{網址}/controller/function 頁面, 所有圖片的連結會變成
http://{網址}/controller/images/logo.png
導致找不到圖片

這時可用 HTML "BASE" tag, 來告訴 browser 圖片的相對路徑, 而非用瀏覽器目前的路徑

使用方式
在< head> 中加入: 區加入
< base href="< ?=base_url()?>" />

解決 CI 圖片路徑問題!

2012年12月7日 星期五

[演講筆記] APP創業經驗分享


Title: 賴俊毓, 創辦人兼執行長, 易享科技, "我的App創業經驗談- 四個月, 從0到180萬下載"
App: MixerBox
Feature: auto create play-list, auto sync, 分享朋友的play list
======================
  1. 創業是要 make an impact, 如果只是要賺錢,去大公司(google/facebook等)比較實際
  2. 創業時機:collage is the best time, 學校是最好的時機,開始工作後大不份人 不願意/無法 放棄現有的工作
  3. 思考方向:market-oriented, not engineering-oriented!!! 
    • 不要因為技術成份不高就放棄點子。先找到要解決的問題,再來看要用什麼技術去解決,方向要正確!

  4. Solve your own problems:從生活中找到不足的東西(你覺得麻煩的事情,就是有機會可以做的東西),MixerBox的構想就是從洗澡像聽音樂開始的
  5. Tell your idea to (almost) everyone:
    • 不用擔心點子被別人知道,有想法就可以分享,不然等做完才說,可能就沒有人理你了。
    • 如果你的點子很容易就被抄走了並模仿,那等推出時也會遇到一樣的問題
  6. Sell before build:
    • 藉由跟他人分享的方式,等於是先開始推銷,也可以知道別人是否認同或需要修改
    • 也可避免做出不合市場需求的東西
  7. Start small. Have an expansion roadmap:
    • 先從簡單(要先解決核心問題)的開始,再慢慢修正(增加功能完整度)
  8. Build Minimal Viable Product (MVP) before Full Product:
    • 先求有再求好!
    • 先做出最簡單最基本的功能,然後就推出,不然等你6個月做完完整產品,市場已經改變!
    • 也試試水溫,看看有沒有人想用,增加自己的彈性。
  9. Persevere through setbacks:堅持往前走,不要放棄
Q&A:
  1. 防衛效應:network effect當第一個公司建立起規模後,使用者資料都已經在你這邊了,就不容易被取代。例如: facebook vs google plus+
  2. 創投資金:必須先做出成效,才會有人來投資。(不同於以前)
  3. 獲利模式:
    • facebook模式,先衝高使用者,就可從中找到賺錢模式(例如fb找到可用ads,但風險高)
    • 整合現有商業模式(例如賣電影票app, 每張就可以賺錢)
  4. 如何與創投溝通
  5. 複製的創業模式(從A區複製到B區): C2C copy to china, 要看是否目標市場可以支持你的東西
  6. 開放API: 讓其他人幫忙開發系統, 其他人依靠你的平台, 他們會希望平台好, 對我們也有好處
  7. 但使用者多,還是會被吃掉, 例如: MSN->WhatsApp->Line->WeChat->...
    • 但做大後還是要持續創新,不然還是會被取代!
    • 唯一的永恆就是改變
==相關文章==

找到一個生活中想解決的問題
創業的點子,從解決自身在生活中遇到的問題開始。John 最初想解決的問題,是想要讓使用者方便的建立歌單,因為在這之前,建立歌單是痛苦的,尤其當歌單是分散在各個不同的裝置上:筆電、手機、平板…... 另外,使用者常常在 Facebook 上推薦歌曲,但時間一久,自己也忘了曾分享過哪些好歌。MixerBox 就是一個為了解決這樣問題的 app,這也是他們的機會,因此創造出 180 萬的使用者,並且這個數字還在成長。MixerBox 除了會擷取使用者在 Facebook 分享過的 YouTube 影片、連續撥放之外,還可以讓使用者很方便的跨裝置整合歌單、撥放並分享,達到社群的功能。
John 鼓勵觀眾想想生活中有什麼不方便的,因為這往往就是創業的機會。另外很重要的一點——不要保密,因為別人要偷你的點子機率其實很小,要成功的做出來,更講究的是團隊和執行力。一開始就對自己的點子閉口不提、閉門造車,結果就是做出來之後沒有人理你,因為要先說服人、讓使用者去下載很難,必須要在做出來之前就開始到處介紹、做行銷(John 稱這為「先賣空再實做」)。另外,John 建議,先從解決小問題做為切入點,有了特定的客群,再從這個功能去延伸、挖掘更多的使用者。

商業模式
目前 app 常見的商業模式分為兩種,一是先衝高使用者的數量,像是 Facebook、Google ;另外是針對小眾客群,但從一開始就要收費、有營收的模式。MixerBox 目前是採用前者的模式,先專注把使用者數量衝高、攻下市占率,再來想後續的收費方式。
John 提到 MixerBox 的防衛點是網路效應,因為其實使用的技術並不困難,而擁有大量使用者、社群建立後,使用者的移轉成本高,自然會為 MixerBox 創造了進入者障礙。

為什麼要 Startup?
John 認為,要創業,賺錢固然重要,但決對不能只是要賺錢,若是為了賺錢不如去大公司工作,風險更小。John 過去花時間在矽谷交流了好一陣子,在他創業的路途中,經歷過許多低潮期,像是不知道使用者的想法、他們會想要怎樣的功能?如何找資金?而如何撐過去等等。
John 提到在大公司能做的有限,大部分都是從事延伸性、分工精細的工作,很難有可以做重大改變的機會。創業就不同了,你可以透過自己的力量,改變世界,並且每個時刻都要思考如何精進產品,John 表示雖然很累人,但創業家樂在其中。

大學是最好的時機!
John 本身是在業界工作過,直到 29 歲才興起創業的念頭,但這時候,John 的同學、朋友大多事業有成、有家庭要顧,安於現狀,要找創業夥伴其實不容易,而且機會成本大,因為有家庭、風險又高。學生則不同,很容易可以找到理念相似的朋友一起,最後頂多的是損失時間,機會成本並不大。

以市場,而非技術為導向(Market-oriented, not engineering-oriented)
從小學習寫程式、資工背景出身的 John 以自身經驗,提到理工背景出身的學生常犯的錯,是「萬般皆下品,唯有技術高」的思維。他認為,創業的點子必須先從市場角度思考,想你想要替使用者解決的問題為何,再來想你需要用到什麼樣的技術,而不是為了用某項厲害的技術,再去想你要做什麼服務。

堅持往前走!(Persevere through setbacks)
由 John 和另外三位夥伴組成的易享科技,其實前前後後試過十幾個產品,其中甚至包括塑化劑偵測 app,在新聞很熱的那陣子,還真的反應不錯,但後來等新聞退燒後,產品也乏人問津。直到這次 MixerBox 推出,一週內就達台灣 app 下載量的第一名,對團隊而言是很大的鼓舞。John 鼓勵更多想創業、正在創業中的朋友,堅持往前走。

2012年9月11日 星期二

Add virtual address mapping to current process's page table

Object:
Using hardware MMU to speedup the translation of gva to hpa for QEMU system mode.

Note: pgd , pud, pmd are the table entry, not the table

Reference:

Sample kernel code:

//#include <asm/tlb.h>
#include <linux/mm.h>
#include <linux/mm_types.h>
#include <linux/sched.h>

#include <asm/pgalloc.h>
//#include <asm/pgtable_types.h>  //for struct page
#include <asm/tlbflush.h>

//vaddr_h: vaddr above 4G
long sys_cr3(unsigned long vaddr_h)
{
    unsigned long eax;
    unsigned long vaddr=0x10000000 | (vaddr_h & 0xfff);
    pgd_t *pgd;
    pud_t *pud;
    pmd_t *pmd, pmd_n;
    pte_t *pte, *pte_h;
    struct page *page;
    pgprot_t pgprot;// = __pgprot(0x67);
    //pgprot.pgprot=0x67;
    //set_pte_vaddr(vaddr, ptep);
    //pte_alloc();
    
    //get origen page above 4G
    pgd = pgd_offset(current->mm, vaddr_h);
    pud = pud_offset(pgd, vaddr_h);
    pmd = pmd_offset(pud, vaddr_h);
    pgprot = __pgprot(pmd_val(*pmd) & 0xfff);
    pte_h = pte_offset_map(pmd, vaddr_h);
    
    //mapping vaddr_h above 4G to vaddr below 4G
    //alloc page entry
    pgd = pgd_offset(current->mm, vaddr);
    if(pgd_none(*pgd)) {
        printk("pgd entry not found, alloc new pud and set pgd entry\n");
        /* FIXME */
        //pud = pud_alloc(current->mm, current->mm->pgd, vaddr);
        //set_pud(pgd, *pud);
        pgd = pgd_alloc(current->mm);
    }
    pud = pud_offset(pgd, vaddr);
    if(pud_none(*pud)) {
        printk("pud entry not found, alloc new pmd and set pud entry\n");
        /* FIXME */
        pud = pud_alloc(current->mm, pgd, vaddr);
    }
    pmd = pmd_offset(pud, vaddr);
    if(pmd_none(*pmd)) {
        printk("pmd entry not found, alloc new pte and set pmd entry\n");
        //pmd = pmd_alloc(current->mm, pud, vaddr);
        page = pte_alloc_one(current->mm, vaddr);
        pmd_n = mk_pmd(page, pgprot);
        set_pmd(pmd, pmd_n);
    }
    /*
    pte = pte_offset_map(pmd, vaddr);
    if(!pte) {
        printk("pte_alloc\n");
        //page table entry is not availble, alloc one page table
        //Note: pte is page table pointer, not page table entry
        ptep = pte_alloc_map(current->mm, current->mm->mmap, pmd, vaddr);
        if(!ptep)
            printk("pte_alloc_map fail\n");
    }
    */
    
    //pte = page table entry
    pte = pte_offset_map(pmd, vaddr);
    
    //printk("vaddr_h: pmd_index:%lu, pte_index:%lu\n", 
    //        pmd_index(vaddr_h), pte_index(vaddr_h));
    
    //set new pte as origin pte_h
    set_pte(pte, *pte_h);
    
    //printk("__pa(%lx)=%lx, __pa(12345678)=%lx\n", 
    //        vaddr_h, __pa(vaddr_h), __pa(0x12345678));
    //update_mmu_cache(current->mm->mmap, vaddr, pte);
    //flush_tlb_mm(current->mm);



    __asm__ __volatile__ (
#ifdef CONFIG_X86_64
        "mov %%cr3, %%rax"
#else
        "mov %%cr3, %%eax"
#endif
        : "=a" (eax)
        : /* no input */
        :
        );

    return eax;
    //flush_tlb_page(current->mm->mmap, 0x12345);
}

2012年8月17日 星期五

Adding a new system call in Linux kernel 3.3

How to add a new Linux kernel API in 3.3 version? -- for 64 bits OS
  • Upzip it with command ‘tar xvfj XXX” to a folder For example : /root/kernel tar xvfj linux-3.3.1.tar.bz2 
  • Edit file “/root/kernel/linux-3.3.1/arch/x86/syscalls/syscall_64.tbl” Add new line
    312 64 husky1 sys_husky1 
  • Eidt file “/root/kernel/linux-3.3.1/include/linux/syscalls.h” Add new function declaration
    asmlinkage long sys_husky1(int fd);
    before the line “#endif” 
  • Add a new c file under “/root/kernel/linux-3.3.1/arch/x86/kernel”
    long sys_husky1(int fd) { ... }
  • Edit “/root/kernel/linux-3.3.1/arch/x86/kernel/Makefile” Add a new line “obj-y += husky.o” 
  • goto /root/kernel/linux-3.3.1 folder and run command “make –j8” 
User space code for calling the new system call:
int ret = syscall(312);
Due to standard kernel header doesn't know our new system call,
we need to use system call number here.

Ref: http://stackoverflow.com/questions/9977968/adding-a-new-system-call-in-linux-kernel-3-3

2012年7月4日 星期三

讓Apache得知透過nginx reverse-server的訪客真實IP

由於大家都只對revere proxy連線,實際存取apache的就只有reverse proxy而已,若是不透過reverse proxy,apache的log可以清楚的紀錄每一個連線的ip,但是透過了reverse proxy之後,所有瀏覽紀錄會變成只剩下一個,所有的瀏覽紀錄都來自127.0.0.1,這樣的情況是不被允許的,雖然說reverse proxy也可以留下紀錄,但是遇到有問題要比對時就相當麻煩了,所以還是希望apache可以記錄到原始的ip。


安裝: emerge mod_rpaf
設定:
RPAFenable On
RPAFproxy_ips 127.0.0.1 2.2.2.2(reverse proxy ip)
RPAFsethostname On
#RPAFheader X-Forwarded-For (This is default)


Reference:
Show IP in Apache logs from nginx reverse proxy
Passing IPs to apache with nginx proxy
Related Posts Plugin for WordPress, Blogger...