2013年11月13日 星期三

The udev and dbus in the root jail environment.

The root jail system lives in the base system that both UDev systems will receive the kernel notification from the netlink so you need to take care about race condition like upload firmware etc..., but the DBus system (system bus) will stay in isolation space because it used the unix socket to make communication but the system bus' unix socket must be take care. If you use mount bind to bind used folder form Base system to root jail system that the system_bus_socket can't be located at the same path.


2013年10月30日 星期三

DBus Notes

  • DBus 是一個 IPC System ,分為兩種型態 System Bus 與 Session Bus。

  • Session Bus 提供 applications 之間互相溝通, 在系統上 Session Bus 可以有多可, 一個 Session 就是一個 Group。


  • System Bus 整個系統只能有一個 System Bus,有些資料說到 System Bus 可以透過 kobject(netlink) 與 kernel 溝通。 但實際上從 dbus 的 source code(version 1.6.8 kubutu 13.04) 裡並無看到任何使用 netlink 部分。 我想 System Bus 主要是以 root 權限啟動在整個系統裡只有一個且是全域所以稱之為 System Bus, 與 kernel 溝通(控制硬體)的部分我想是透過 system layer 的 applications 如 udev, NetworkManager, UPower etc... , 並非直接透過 netlink。在其他文件中有提到 dbus 以實踐在 linux kernel 裡但這部分目前無相關資料。







2013年10月24日 星期四

Udev 與 devtmpfs 的關係

Driver Core: devtmpfs - kernel-maintained tmpfs-based /dev
Devtmpfs lets the kernel create a tmpfs instance called devtmpfs very early at kernel initialization, before any driver-core device is registered. Every device with a major/minor will provide a device node in devtmpfs.

Devtmpfs can be changed and altered by userspace at any time, and in any way needed - just like today's udev-mounted tmpfs. Unmodified udev versions will run just fine on top of it, and will recognize an already existing kernel-created device node and use it.
The default node permissions are root:root 0600. Proper permissions and user/group ownership, meaningful symlinks, all other policy still needs to be applied by userspace.

If a node is created by devtmps, devtmpfs will remove the device node when the device goes away.
If the device node was created by userspace, or the devtmpfs created node was replaced by userspace, it will no longer be removed by devtmpfs.
If it is requested to auto-mount it, it makes init=/bin/sh work without any further userspace support. /dev will be fully populated and dynamic, and always reflect the current device state of the kernel. With the commonly used dynamic device numbers, it solves the problem
where static devices nodes may point to the wrong devices.

It is intended to make the initial bootup logic simpler and more robust, by de-coupling the creation of the inital environment, to reliably run userspace processes, from a complex userspace bootstrap logic to provide a working /dev.


早期的作法應該是先建立一份 static /dev 提供系統 booting 時使用,當系統 booting 完成後再掛載 tmpfs 到 /dev 上.由 udevadm 重新 trigger kernel,再用 udev 動態建立相對應的 device node 在 /dev 裡


在 linux kernel 2.6.32 後使用 devtmpfs 之後. Udev 並不負責 create device node. create device node 的工作則是交由 Kernel 的 devtmpfs 負責. Udev 則是負責接收 kernel 送出的 uevent 依照相對的資訊如 device ID product ID,去載入相對應的 kernel module,device node的權限管理(參照上述藍色註記部分 device node 被 devtmpfs 建立出來的 default 屬性是 root:root 0660) 與建立相對應的 symlink file etc.

**注意舊版的 udev 會做 device node的建立,新版本的則不會只會做 symlink
http://www.freedesktop.org/software/systemd/
http://ftp.sunet.se/pub/Linux/kernel.org/linux/utils/kernel/hotplug/

2013年9月23日 星期一

裝飾者模式(Decorator Pattern)

裝飾者模式功能在於動態擴充,動態地將責任加諸於物件上。想要擴充功能,裝飾者提供有別於繼承的另一個選擇。

  • 繼承屬於擴充形式之一,但不見得是達到彈性設計的最佳方式。
  • 在我們的設計中,應該允許行為可以被擴充,而無須修改計有的程式碼。
  • 合成與委派可時常在執行時期,動態的加上新的行為。
  • 除了繼承,裝飾者模式也可以讓我們擴充行為。



Decorator 的含意
   f(x) = Decorator(obj)


#include <stdlib.h>
#include <stdio.h>

class CComponent
{
public:
        CComponent()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CComponent()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual int value(void) = 0;
};

class CConcreteComponent : public CComponent
{
private:
        int val;
public:
        CConcreteComponent()
        {
                val = 10;
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CConcreteComponent()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual int value(void)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                return val;
        }
};

class CDecorator : public CComponent
{
public:
        CDecorator()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CDecorator()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

       //  加上新的行為
        virtual void method(void) = 0;
};

class CConcreteDecoratorA : public CDecorator
{
private:
        CComponent *component;
public:
        CConcreteDecoratorA(CComponent *c) : component(c)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CConcreteDecoratorA()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                delete component;
        }

        virtual void method(void)
        {
        }

        // 將原生物件因裝飾後加入新的行為
        virtual int value(void)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                return 20 + component->value();
        }
};


class CConcreteDecoratorB : public CDecorator
{
private:
        CComponent *component;

public:
        CConcreteDecoratorB(CComponent *c) : component(c)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
        }

        virtual ~CConcreteDecoratorB()
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                delete component;
        }

        virtual void method(void)
        {
        }
       
       // 將原生物件因裝飾後加入新的行為
        virtual int value(void)
        {
                printf("%s\n", __PRETTY_FUNCTION__);
                return 30 + component->value();
        }
};

int main()
{
        CComponent *component = new CConcreteComponent();
        printf("\n");
        component = new CConcreteDecoratorA(component);
        printf("\n");
        component = new CConcreteDecoratorB(component);

        printf("===============================================\n");
        printf("%d\n", component->value());
        printf("===============================================\n");
        delete component;
}

執行結果
CComponent::CComponent()
CConcreteComponent::CConcreteComponent()

CComponent::CComponent()
CDecorator::CDecorator()
CConcreteDecoratorA::CConcreteDecoratorA(CComponent*)

CComponent::CComponent()
CDecorator::CDecorator()
CConcreteDecoratorB::CConcreteDecoratorB(CComponent*)
===============================================
virtual int CConcreteDecoratorB::value()
virtual int CConcreteDecoratorA::value()
virtual int CConcreteComponent::value()
60
===============================================
virtual CConcreteDecoratorB::~CConcreteDecoratorB()
virtual CConcreteDecoratorA::~CConcreteDecoratorA()
virtual CConcreteComponent::~CConcreteComponent()
virtual CComponent::~CComponent()
virtual CDecorator::~CDecorator()
virtual CComponent::~CComponent()
virtual CDecorator::~CDecorator()
virtual CComponent::~CComponent()

在此要思考裝飾者的結構式裡用 delete 是否恰當,原程式是在 Java 上時做,但  C++ 不具備有 garbage collection 的功能。若不再解構式中釋放則會產生 memory leak 的問題。但在另一個 case 裡則會引發錯誤。

使用時機須在思考

int main()
{
        CComponent *component;
        CConcreteComponent concreteComponent;
        printf("\n");
        component = new CConcreteDecoratorA(&concreteComponent);
        printf("\n");
        component = new CConcreteDecoratorB(component);

        printf("===============================================\n");
        printf("%d\n", component->value());
        printf("===============================================\n");
        delete component;
}

CComponent::CComponent()
CConcreteComponent::CConcreteComponent()

CComponent::CComponent()
CDecorator::CDecorator()
CConcreteDecoratorA::CConcreteDecoratorA(CComponent*)

CComponent::CComponent()
CDecorator::CDecorator()
CConcreteDecoratorB::CConcreteDecoratorB(CComponent*)
===============================================
virtual int CConcreteDecoratorB::value()
virtual int CConcreteDecoratorA::value()
virtual int CConcreteComponent::value()
60
===============================================
(執行 delete)
virtual CConcreteDecoratorB::~CConcreteDecoratorB()
virtual CConcreteDecoratorA::~CConcreteDecoratorA()
virtual CConcreteComponent::~CConcreteComponent()
virtual CComponent::~CComponent()
*** Error in `./decorator': double free or corruption (out): 0xbfa397c8 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x767e2)[0xb74ee7e2]
/lib/i386-linux-gnu/libc.so.6(+0x77530)[0xb74ef530]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0xb7691b4f]
./decorator[0x8048980]
./decorator[0x8048aec]
./decorator[0x8048b3f]
./decorator[0x8048c10]
./decorator[0x8048c63]
./decorator[0x80487f6]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0xb7491935]
./decorator[0x8048651]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:01 393246     /home/archer/src/HeadFirstDesignPatterns/chap03/decorator
0804a000-0804b000 r--p 00001000 08:01 393246     /home/archer/src/HeadFirstDesignPatterns/chap03/decorator
0804b000-0804c000 rw-p 00002000 08:01 393246     /home/archer/src/HeadFirstDesignPatterns/chap03/decorator
0819b000-081bc000 rw-p 00000000 00:00 0          [heap]
b7433000-b7435000 rw-p 00000000 00:00 0 
b7435000-b7476000 r-xp 00000000 08:01 656247     /lib/i386-linux-gnu/libm-2.17.so
b7476000-b7477000 r--p 00040000 08:01 656247     /lib/i386-linux-gnu/libm-2.17.so
b7477000-b7478000 rw-p 00041000 08:01 656247     /lib/i386-linux-gnu/libm-2.17.so
b7478000-b7625000 r-xp 00000000 08:01 656199     /lib/i386-linux-gnu/libc-2.17.so
b7625000-b7627000 r--p 001ad000 08:01 656199     /lib/i386-linux-gnu/libc-2.17.so
b7627000-b7628000 rw-p 001af000 08:01 656199     /lib/i386-linux-gnu/libc-2.17.so
b7628000-b762c000 rw-p 00000000 00:00 0 
b762c000-b7647000 r-xp 00000000 08:01 656224     /lib/i386-linux-gnu/libgcc_s.so.1
b7647000-b7648000 r--p 0001a000 08:01 656224     /lib/i386-linux-gnu/libgcc_s.so.1
b7648000-b7649000 rw-p 0001b000 08:01 656224     /lib/i386-linux-gnu/libgcc_s.so.1
b7649000-b7725000 r-xp 00000000 08:01 1969970    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b7725000-b7726000 ---p 000dc000 08:01 1969970    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b7726000-b772a000 r--p 000dc000 08:01 1969970    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b772a000-b772b000 rw-p 000e0000 08:01 1969970    /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b772b000-b7732000 rw-p 00000000 00:00 0 
b7747000-b774b000 rw-p 00000000 00:00 0 
b774b000-b774c000 r-xp 00000000 00:00 0          [vdso]
b774c000-b776c000 r-xp 00000000 08:01 656173     /lib/i386-linux-gnu/ld-2.17.so
b776c000-b776d000 r--p 0001f000 08:01 656173     /lib/i386-linux-gnu/ld-2.17.so
b776d000-b776e000 rw-p 00020000 08:01 656173     /lib/i386-linux-gnu/ld-2.17.so
bfa1a000-bfa3b000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)


修改過適合 C++ 的作法

#include <string>
#include <iostream>

using namespace std;

class CComponent
{
public:
        CComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual int value(void) = 0;
        virtual string getInfo(void) = 0;
};

class CConcreteComponent : public CComponent
{
private:
        int val;
public:
        CConcreteComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
                val = 10;
        }

        virtual ~CConcreteComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;

        }

        virtual int value(void)
        {
                return val;
        }

        virtual string getInfo(void)
        {
                return "CConcreteComponent";
        }
};

class CDecorator : public CComponent
{
public:
        CDecorator()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CDecorator()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        // new mothod
        virtual void newMethod(void) = 0;
};

class CConcreteDecoratorA : public CDecorator
{
private:
        CComponent *m_component;
public:
        CConcreteDecoratorA(CComponent *c) : m_component(c)
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CConcreteDecoratorA()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual void newMethod(void)
        {
        }

        // the same mothod but new behavior
        virtual int value(void)
        {
                return 20 + m_component->value();
        }

        virtual string getInfo(void)
        {
                return m_component->getInfo() + " ,CConcreteDecoratorA";
        }
};

class CConcreteDecoratorB : public CDecorator
{
private:
        CComponent *m_component;

public:
        CConcreteDecoratorB(CComponent *c) : m_component(c)
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CConcreteDecoratorB()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual void newMethod(void)
        {
        }

        // the same mothod but new behavior
        virtual int value(void)
        {
                return 30 + m_component->value();
        }

        virtual string getInfo(void)
        {
                return m_component->getInfo() + " ,CConcreteDecoratorA";
        }
};

int main()
{
        CConcreteComponent m;
        cout << endl;

        CConcreteDecoratorA a(&m);

        cout << endl;
        CConcreteDecoratorB b(&a);

        cout << "=============================================" << endl;
        cout << "Info : " << m.getInfo() << endl;
        cout << "Value: " <<m.value() << endl;
        cout << "=============================================" << endl;
        cout << "Info : " << a.getInfo() << endl;
        cout << "Value: " << a.value() << endl;
        cout << "=============================================" << endl;
        cout << "Info : " << b.getInfo() << endl;
        cout << "Value: " << b.value() << endl;
        cout << "=============================================" << endl;
}

修正了動態配置所產生的 memory leak 的問題,但在使用上似乎不能向上例如此彈性。


用 shared_ptr 解決動態配置問題 (only supported by c++11)    
  
#include <string>
#include <iostream>
#include <memory>

using namespace std;

class CComponent
{
public:
        CComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual int value(void) = 0;
        virtual string getInfo(void) = 0;
};

class CConcreteComponent : public CComponent
{
private:
        int val;
public:
        CConcreteComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
                val = 10;
        }

        virtual ~CConcreteComponent()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual int value(void)
        {
                return val;
        }

        virtual string getInfo(void)
        {
                return "CConcreteComponent";
        }
};

class CDecorator : public CComponent
{
public:
        CDecorator()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual ~CDecorator()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        // new mothod
        virtual void newMethod(void) = 0;
};

class CConcreteDecoratorA : public CDecorator
{
private:
        shared_ptr<CComponent> m_component;
public:
        CConcreteDecoratorA(shared_ptr<CComponent> c) : m_component(c)
        {
                cout << __PRETTY_FUNCTION__ << endl;
                cout << "use count:" << c.use_count() << endl;
        }

        virtual ~CConcreteDecoratorA()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual void newMethod(void)
        {
        }

        // the same mothod but new behavior
        virtual int value(void)
        {
                return 20 + m_component->value();
        }

        virtual string getInfo(void)
        {
                return m_component->getInfo() + " ,CConcreteDecoratorA";
        }
};

class CConcreteDecoratorB : public CDecorator
{
private:
        shared_ptr<CComponent> m_component;

public:
        CConcreteDecoratorB(shared_ptr<CComponent> c) : m_component(c)
        {
                cout << __PRETTY_FUNCTION__ << endl;
                cout << "use count:" << c.use_count() << endl;
        }

        virtual ~CConcreteDecoratorB()
        {
                cout << __PRETTY_FUNCTION__ << endl;
        }

        virtual void newMethod(void)
        {
        }

        // the same mothod but new behavior
        virtual int value(void)
        {
                return 30 + m_component->value();
        }

        virtual string getInfo(void)
        {
                return m_component->getInfo() + " ,CConcreteDecoratorA";
        }
};

int main()
{
        shared_ptr<CComponent> m(new CConcreteComponent());
        cout << "m's use count:" << m.use_count() << endl;
        cout << endl;

        shared_ptr<CComponent> a(new CConcreteDecoratorA(m));
        cout << "a's use count:" << a.use_count() << endl;
        cout << endl;

        shared_ptr<CComponent> b(new CConcreteDecoratorB(m));
        cout << "b's use count:" << b.use_count() << endl;

        cout << "=============================================" << endl;
        cout << "Info : " << m->getInfo() << endl;
        cout << "Value: " << m->value() << endl;
        cout << "=============================================" << endl;
        cout << "Info : " << a->getInfo() << endl;
        cout << "Value: " << a->value() << endl;
        cout << "=============================================" << endl;
        cout << "Info : " << b->getInfo() << endl;
        cout << "Value: " << b->value() << endl;
        cout << "=============================================" << endl;
}
                     

2013年9月15日 星期日

XBMC used strategy pattern to implement player to playback file.

XBMC 使用 Strategy pattern 實作 player,各 player 實作 IPlayer 介面,提供控制方法由 CApplication 控制

在執行時期由 CPlayerCoreFactory::Get().CreatePlayer(eNewCore, *this)
動態決定要掛載的 player 實體


bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
{
     :
     :
  if (!m_pPlayer)
  {
    m_eCurrentPlayer = eNewCore;
    m_pPlayer = CPlayerCoreFactory::Get().CreatePlayer(eNewCore, *this);
  }
:
     :
}

if __name__ == "__main__"

在 python 裡 __name__ 可用來識別當下所執行 module 名稱
讓我們來看以下幾個範例

# file: test1.py
print "the module name is:", __name__


#file: test2.py
print "the module name is:", __name__


#file: test3.py
import test1
import test2
print "the module name is:", __name__

分別執行 test1.py test2.py test3.py 可到如下結果


#>: python test1.py
the module name is: __main__

#>: python test2.py
the module name is: __main__

#>: python test3.py
the module name is: test1
the module name is: test2
the module name is: __main__

我們可以知道,在當下執行的檔案 __name__ 會是 "__main__",若被 import 到其他檔案中被執行到則 __name__ 會是該 module 的名稱,可由執行 test3.py 驗證.

由於 python 是直譯是語言,interpreter 再載入各 module 時同時也會直行該 module 所包含的程式碼.若要避免不必要地誤動作可在各 module 內加入 if __name__ == "__main__",避免程式碼被執行.

我們可將上述檔案改變如下,並觀察執行結果,則可發現在執行 test3.py 的時候可避開 test1.py
與  test2.py 載入時不必要的執行.

# file: test1.py
if __name__ == "__main__":
    print "the module name is:", __name__


#file: test2.py
if __name__ == "__main__":
    print "the module name is:", __name__


#file: test3.py
import test1
import test2

if __name__ == "__main__":
    print "the module name is:", __name__

#>: python test1.py:
the module name is: __main__

#>: python test2.py
the module name is: __main__

#>: python test3.py
the module name is: __main__

2013年9月14日 星期六

Mplayer backend example





#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <string>


using namespace std;

int main()
{
        int   pipefd[2] = {0};

        if(pipe(pipefd) != 0) {
                printf("pipe open failed\n");
        }

        if(fork() != 0) {
                string command;
                close(pipefd[0]);

                while(1) {
                        cout << "command:";
                        cin >> command;
                        command += "\n";

                        write(pipefd[1], command.c_str(), command.length());

                }
        } else {
                dup2(pipefd[0], fileno(stdin));

                execl("/usr/bin/mplayer", "mplayer",
                      "-slave", "-fs", "-osdlevel", "0", "-really-quiet",
                      "-input", "nodefault-bindings", "-noconfig", "all",
                      "/home/archer/Videos/300_Trailer2_8mbps_1080p29.98_5.1.wmv", NULL);
        }

        return 0;
}

2013年9月13日 星期五

Observer Model example for C++


  • Observer Model
    • The Observer dose not actively to get the data from the Subject else the Subject will
      notify the Observer when there are something changed.
    • 觀察者模式定義了物件之間一對多的關係
    • 主題(Subject) 更新觀察者的方式 ,是透過一個共用介面。
    • 觀察者與可觀察者之間採用鬆綁的方式結合(loose-coupling),因為可觀察者不知道觀察者的細節,只知道觀察者有實踐特定的觀察者介面。




#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <list>

using namespace std;

class CObserver
{
public:
        virtual void update(int data) = 0;
};

class CSubject
{
public:
        virtual void registerObserver(CObserver *obs) = 0;
        virtual void deleteObserver(CObserver *obs) = 0;
        virtual void notify(void) = 0;
};

class CInformationStation : public CSubject
{
private:
        list<CObserver *> m_observerList;
public:
        virtual void registerObserver(CObserver *obs);
        virtual void deleteObserver(CObserver *obs);
        virtual void notify(void);
};

void CInformationStation::registerObserver(CObserver *obs)
{
        list<CObserver *>::iterator it;
        bool found = false;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                if(*it == obs){
                        found = true;
                        break;
                }
        }

        if(!found)
                m_observerList.push_back(obs);
}

void CInformationStation::deleteObserver(CObserver *obs)
{
        list<CObserver *>::iterator it;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                if(*it == obs) {
                        m_observerList.erase(it);
                        break;
                }
        }
}

void CInformationStation::notify(void)
{
        list<CObserver *>::iterator it;

        for(it = m_observerList.begin(); it != m_observerList.end(); it++) {
                srand((int)time(0));
                sleep(1);
                (*it)->update( rand() % 1000);
        }
}

class CStatistic : public CObserver
{
private:
        int m_data;
public:
        CStatistic() : m_data(0) {}

        virtual void update(int data)
        {
                m_data = data;
        }

        void display(void)
        {
                printf("[%s] m_data:%d\n", __PRETTY_FUNCTION__, m_data);
        }
};

int main()
{
        CInformationStation station;
        CStatistic statistic1, statistic2, statistic3;

        station.registerObserver(&statistic1);
        station.registerObserver(&statistic2);
        station.registerObserver(&statistic3);

        station.notify();

        statistic1.display();
        statistic2.display();
        statistic3.display();

        return 0;
}

2013年9月12日 星期四

Call by reference of const object argument passing.

當 function 或 member 透過 call by reference 傳遞參數時有個有趣的現象,如下範例

#include <stdlib.h>
#include <stdio.h>
#include <string>

using namespace std;

class CFoo
{
public:
    CFoo(strring &str)
    {
        printf("[%s]: str:%p\n", __PRETTY_FUNCTION__, &str);
    }

    CFoo(int &i)
    {
        printf("[%s]: i:%p\n", __PRETTY_FUNCTION__, &i);
    }
    CFoo(CFoo &foo)
    {
        printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
    }
    ~CFoo()
    {
       printf("[%s]\n", __PRETTY_FUNCTION__);
    }
};

void func1(const CFoo &foo)
{
    printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
}

//void func2(CFoo &foo)
//{
//    printf("[%s]: foo:%p\n", __PRETTY_FUNCTION__, &foo);
//}

int main()
{
    CFoo foo;
    string str = "str";
    int i = 10;

    printf("&foo:%p\n", &foo);
    func1(foo);

    printf("&str:%p\n", &str);
    func1(str);

    printf("&i:%p\n", & i);
    func1(i);

    return 0;
}

當 g++ 面對不同型態的參數呼叫 func1() 時 , 除了 func1(foo) 之外, 都會暫時產生一個 CFoo 的object 並依照其 CFoo 所定義的 constructor 完成 func1 參數裡的物件建構.但只限 const object.

如果將 func1() 替換成 func2(),則除了 func2(foo) 可順利編譯成功, 其他方式的呼叫皆會在 compiling time 時出現錯誤.因為 compiler 並不會為其他呼叫方式產生臨時的 instance, 所以將會有型別不符的錯誤.

void func1(const CFoo &foo)void func2(CFoo &foo) 除了 const 修飾詞所表示的不可修改之外,在參數傳遞的建構方式也有所不同.



2013年9月9日 星期一

Designed Patterns


  • 模式不是程式碼,而是針對特定系統的解決方案,是解決程式中設計的問題。
  • 模式不是被發明,而是被發現。
  • 我門通常把系統中,會變動的部分抽出來封裝。
  • 利用繼承設計次類別的行為,是在編譯時期靜態決定的,而且所以次類別都會繼承到相同的行為。
  • 利用合成的作法擴充物件的行為,就可以在執行時期動態地進行擴充。

(Head First Design Patterns) Strategy Patten


  • 多用合成 ,少用繼承 (More composition less inheritance)
    • 使用合成建立系統具有很大的彈性,不僅可以將演算法封裝成類別,更可以在執行期動態改變行為,只要合成的行為物件,符合特定的介面標準即可。
E.X:

#include <stdlib.h>
#include <stdio.h>

// particular interface
class IFlyBehavior
{
public:
        virtual void fly(void) = 0;
};

// The interface implementance 
class CFlyWithWings : public IFlyBehavior
{
public:
        virtual void fly(void)
        {
                printf("I'm flying\n");
        }
};

// The interface implementance 
class CFlyNoWay : public IFlyBehavior
{
public:
        virtual void fly(void)
        {
                printf("I can't fly\n");
        }
};

// particular interface
class IQuackBehavior
{
public:
        virtual void quack(void) = 0;
};

// The interface implementance 
class CQuack : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("Quick\n");
        }
};

// The interface implementance 
class CMuteQuack : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("<<silence>>\n");
        }
};

class Squeak : public IQuackBehavior
{
public:
        virtual void quack(void)
        {
                printf("Squeak\n");
        }
};

class CDuck
{
protected:
        IFlyBehavior *m_flyBehavior;             // more fixable
        IQuackBehavior *m_quackBehavior;  // more fixable
public:
        CDuck(){}
        virtual ~CDuck(){}
        virtual void display() = 0;

        virtual void performQuack(void)
        {
                m_quackBehavior->quack();
        }

        virtual void performFly(void)
        {
                m_flyBehavior->fly();
        }

        virtual void swim()
        {
                printf("All duck float, even decoys!");
        }
};

class CMallardDuck : public CDuck
{
public:
        CMallardDuck()
        {
                m_flyBehavior = new CFlyWithWings(); // can be replacement at runtime
                m_quackBehavior = new CQuack();        
        }
        virtual ~CMallardDuck()
        {
                delete m_flyBehavior;
                delete m_quackBehavior;
        }

        virtual void display(void)
        {
        }
};

int main()
{
        CDuck &mallard =  *(new CMallardDuck());

        mallard.performQuack();
        mallard.performFly();

        return 0;
}

2013年8月27日 星期二

MAC PHY MII GMII RGMII


OSI Network Stack




ETHERNET 的接口實質是 MAC 通過 MII 匯流排控制 PHY 的過程。


MAC
  • MAC是Media Access Control 的縮寫,即媒體訪問控制子層協議。該協議位於OSI七層協議中數據鏈路層的下半部分,主要負責控制與連接物理層的物理介質。在發送數據的時候,MAC協議可以事先判斷是否可以發送數據,如果可以發送將給數據加上一些控制信息,最終將數據以及控制信息以規定的格式發送到物理層;在接收數據的時候,MAC協議首先判斷輸入的信息並是否發生傳輸錯誤,如果沒有錯誤,則去掉控制信息發送至LLC層。以太網MAC由IEEE-802.3以太網標準定義。 
MII  GMII  RGMII

  • 基本上,這三個的作用是一樣的,同樣都是連結MAC層和PHY層的介面。區別在於編碼、速度、使用的腳位數、I/O clock的頻率不同。


  • MII : 這是IEEE 802.3u制定出來,應用在Fast Ethernet上,連接 Data Link Layer 中的MAC層和Physical Layer 中的PHY層(這樣的說法有點瑕疵,因為Data Link Layer有分為MAC層和LLC層,但Physical Layer沒有分其它的層別,統稱為PHY層)的溝通介面。全名為(Media Independent Interface)。


  • MII即媒體獨立接口, 「媒體獨立」表明在不對MAC硬件重新設計或替換的情況下,任何類型的PHY設備都可以正常工作。包括分別用於發送器和接收器的兩條 MII使用8B/10B之編碼,所以它運作在125Mbps的時候,可以傳送包含檔頭的100Mbps的資料。(想成有八條水管,同時有125Mbps的資料流進來,通過了一個閘道,要流到十條水管裡去,這十條水管的平均流速就是125Mbps*8/10=100Mbps。)


  •  IC對PHY做讀寫的時候用一組訊號:MDC(Management Data Control)與MDIO(Management Data Input/Output)。


          輸出和輸入各有四個bit的匯流排:Tx[0:3]、Rx[0:3] (輸出是指IC到PHY、輸入是指PHY到IC)

          MII對於Data sampling reference用的兩組clock,頻率為25MHZ,這兩個訊號為Tx_CLK和Rx_CLK。(Ethernet頻率為2.5MHz)

          通知對方準備輸入資料的輸出和輸入的啟動訊號為:Tx_EN、Rx_EN

          輸出、輸入訊號的錯誤通知訊號為:Tx_ER、Rx_ER

          得到有效輸入資料的通知訊號為:Rx_DV

          網路上出現擁塞的Colision訊號為:Col

          作為carrier回覆用的訊號為:CRS (請參考CSMA/CD)

          MII實作的電路電壓可用+5V或是+3.3V


  • GMII:Gigabit Media Independent Interface,可支援到1Gbps,不同於MII,輸出和輸入各有8個bit。

          Tx:GTXCLK、TxCLK、TxD[0:7]、TxEN、TxER

          Rx:RxCLK、RxD[0:7]、RxDV、RxER、COL、CRS

          MDC、MDIO


  • RGMII:Reduced Gigabit Media Independent Interface,顧名思義就是GMII的縮小版(因為減少了PIN腳位數)啦。

          和GMII一樣可以支援10/100/1000Mbps,只有定義12個訊號,比GMII還少一半:RxC、RxD[0:3]、Rx_CTL、TxC、TxD[0:3]、Tx_CTL

  •  IC控制訊號一樣是透過MDC、MDIO


PHY

  • PHY是物理接口收發器,它實現物理層。包括MII/GMII(介質獨立接口)子層、PCS(物理編碼子層)、PMA(物理介質附加)子層、PMD(物理介質相關)子層、MDI子層。

Reference:
http://blog.csdn.net/dark_goldz/article/details/4691773
http://blog.csdn.net/sahusoft/article/details/6908753

2013年7月27日 星期六

Gstreamer gst-launch multithreaded example (with tee element)

Pipeline example:



Command example:




Command example:
gst-launch videotestsrc ! ffmpegcolorspace ! tee name=t ! queue ! autovideosink t. ! queue ! autovideosink
Parse the command:
1) First part:
videotestsrc ! ffmpegcolorspace ! tee name=t !
2) Splited to:
queue ! autovideosink and t. ! queue ! autovideosink

tee name=t which mean is to create a new source pad which name is 't'.

Another example:
gst-launch-0.10 filesrc location=sample.mp4 ! qtdemux name=demuxer demuxer. ! queue ! faad ! audioconvert ! audioresample ! autoaudiosink demuxer. ! queue ! ffdec_h264 ! ffmpegcolorspace ! autovideosink





Reference:
http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+10%3A+GStreamer+tools
http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+7%3A+Multithreading+and+Pad+Availability