Wednesday, November 20, 2013

Install nox-classic on Ubuntu 12.04

It's seems that there are problems if just following the instruction in their wiki page. Try the instructions below if you have problems while installing nox.

Update apt-get download list

  • cd /etc/apt/sources.list.d/
  • sudo wget http://openflowswitch.org/downloads/debian/nox.list
  • sudo apt-get update
  • sudo apt-get install nox-dependencies


Download from Github

  • cd ~
  • apt-get install nox-dependencies libtbb-dev libboost-serialization-dev libboost-all-dev
  • git clone git://github.com/noxrepo/nox
  • cd nox
  • ./boot.sh
  • mkdir build
  • cd build

Configure

  • ../configure
  • make
  • sudo make install

Run

  • cd src
  • ./nox_core -i ptcp:6633
  • ./nox_core -v -i ptcp:6633 switch

Monday, November 18, 2013

Setup eCos Development Environment on Ubuntu 12.04 for STM32

Before You Begin


Install Required Tools & Dependencies

  • sudo apt-get install cvs libstdc++5 ia32-libs libglib2.0-dev


Download eCos then Setup

  • wget --passive-ftp ftp://ecos.sourceware.org/pub/ecos/ecos-install.tcl
  • sh ecos-install.tcl
    • choose a faster distribution site, like "[16] ftp://ftp.u-aizu.ac.jp/pub/gnu/cygnus/ecos", which may locate in Japan
    • choose a location to store the downloads, take default /home/<username>/ecos as example in this article
    • select "[1] arm-eabi", which is said in my course assignment instruction; however, I found we don't need this if we have arm-none-eabi (which we've installed already)
  • cd /home/<username>/ecos
  • cvs -z3 -d :pserver:anoncvs@ecos.sourceware.org:/cvs/ecos co -P ecos
  • in file "ecosenv.sh", modify "ECOS_REPOSITORY=/home/<username>/ecos/ecos-3.0/packages ; export ECOS_REPOSITORY" to "ECOS_REPOSITORY=/home/<username>/ecos/ecos/packages ; export ECOS_REPOSITORY"
  • . ecosenv.sh
    • this exports the system PATHs for ecos tools


Create HelloWorld Project

  • cd <somewhere you like to place you project>
  • mkdir ecos_project && cd ecos_project
  • ecosconfig new stm32f4discovery
  • configtool
    • change "eCos HAL->Cortex-M Architecture->Cortex-M3/-M4 STM32 Variant->STMicoelectronics STM32F4-Discovery board HAL->Startup Type" to ROM instead of JTAG
    • this starts an GUI interface, open the "ecos.ecc" file which locates in the folder "stm32f4discovery" just created
    • press "Build" -> "Generate Build Tree"
  • create an hello.c file, like:
#include <stdio.h>
int main(){
  printf("hello ecos!\r\n");
}

  • arm-none-eabi-gcc -o Hello.elf hello.c -Lecos_install/lib -I ecos_install/include -mcpu=cortex-m4 -mthumb -g -O2 -ffunction-sections -fdata-sections -Ttarget.ld -nostdlib
  • arm-none-eabi-objcopy -O binary -R .sram Hello.elf Hello.bin
    • finally, you got Hello.bin here, and burn it into stm32 by following the instruction in last article using QSTLink2 

Sunday, November 17, 2013

Fast way to Start VM and SSH into it on Mac

Though Mac OS is based on FreeBSD, but still lots of unix-based tools are not as good as those on Linux. And, it turns out people start to use "port", "brew", etc to get the tools they want. However, in my point of view, "port", "brew", etc are still not good as "apt-get" or "yum" since they are not well integrated.

So, I am using VirtualBox with Ubuntu guest. And, I write a simple script to:

  • Start the Ubuntu VM
  • SSH into the machine
  • Save the VM state when finishes SSH
I don't even need the GUI of Ubuntu. Also, the machine saves its state instead of turning off, so I don't have to wait long.


Tuesday, November 12, 2013

Operating System Study - Questions & Answers for Shumin

While I was discussing with Shumin, I found there are few things I don't really sure, so I wrote them down and try to find out the answers here. Since these are part of the discussion, they may be not that formal and precise.


Difference between Emulation & Virtualization

Virtualiztion: 模擬出整套系統真實的環境(包含模擬硬體),ex. VirtualBox。
  • Pros: 被模擬的環境比較真實,容易安裝或測試想跑的程式。
  • Cons: 消耗原本系統較大的資源(就像是你Mac會卡住)。

Emulation: 在原本系統中複製類似的環境,ex. WINE(可以讓你在linux/mac上面裝Windows程式的,很有名)。
  • Pros: 比較便宜、不耗成本的做法。
  • Cons: 不好用,被模擬的程式看到的環境比較差,容易壞、不易當測試環境。

What is "System Call"

  1. 先知道有個東西叫作API,是系統提供使用者的控制系統的方法,printf, read, write, open..都是。
  2. “The system-call interface intercepts function calls in the API and invokes the necessary system calls within the operating system.”
  3. “The intended system returns the status of the system call and any return values.”
Heron: 簡單來說就是system提供一些函式讓user可以call,之後怎麼handle就交給system(OS)去處理。

What is "static"

課本裡說”Thread-Local Storage”(TLS)類似於static,而不同處在於TLS在不同thread中是unique的。
static: "a static variable is a variable that has been allocated statically—whose lifetime or "extent" extends across the entire run of the program” (from Wikipedia) 表示static變數不是一般會動態分配的變數(heap memory)也不是函式呼叫時候的變數(call stack)。
而在C/C++語言中(http://en.wikipedia.org/wiki/Static_(keyword)) ,static變數表示:Lifetime為整份program執行期間、只能被內部(如同一class裡面)看見的變數。

Monday, November 11, 2013

Does the number of Cores = the number of kernel threads?

Question

"Does the number of Cores = the number of kernel threads?"

While we were studying for the midterm of Operating System, few people started to ask this question. It seems that the textbook, "Operating System Concepts (by Abraham Silberschatz, Peter B. Galvin, Greg Gagne)", doesn't explain this clearly enough. Therefore, I started to find out the answer on the internet. Here comes my study.


Answer

NO! The maximum number of the kernel threads can up to around 15,000 on a general machine. And, the number of the cores mostly are round 2~4. It means that "one core can run more than 2 kernel threads in the same time", which is called "Hyper-Threading".


Reference

Saturday, November 9, 2013

Using Shared Memory for Matrix Multiplication

Problem


This is one of the assignment in Operating System course. The deadline is passed already, and I would like to take notes here descripting how I implemented this assignment.

In this assignment, we are ask to calculate the multiplication(matrix C) of two input matrix A and B. A and B is simply defined in n dimension, the are same and looks like:

[ [ 0, 1, ....., n-1],
  [ n, n+1, ...,2n-1],
  [... ,   ......n*n] ]

which mean A[i][j] = B[i][j] = i*n + j.

We are asked to use shared memory for matrix C. And threads are forked in the original process, so that this multiplication can be processed by 2 or 4 processes in the same time, which will showed much faster if using 4 processes. The result we have to show is the sum of matrix C.

Tools


To create, attach, detach and release the shared memory, we can apply the following functions:

  • shmget(key, sizeof(unsigned int) * n * n, shmflg)
    • Getting a shared memory ID from the system, you will get the same ID if you are using the same input key, which can be any integer.
  • shmat(shmidC, NULL, 0))
    • By passing the shared memory ID, shmat returns the real address of the shared memory.
  • shmdt(C)
    • After we've done all the things related to the shared memory, we have to detach the shared memory (this should be called before exiting any child process).
  • shmctl(shmidC, IPC_RMID, 0)
    • Release the shared memory. While we're not using the shared memory anymore, it's time to release the memory, so that the operating system won't have to clean up manually.

Code


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/time.h>

/* Magic Number for Key */
#define MAGIC_NUMBER    1111

/* Global Array for A, B */
unsigned int A[800][800], B[800][800];
unsigned int *C;

/* Function Definitions */
unsigned long long processOne(int n);
unsigned long long processTwo(int n);
unsigned long long processFour(int n);
void initMemory();

/* Global Variables for shared memory ID */
int shmidC;

/* Self-write Functions for Attaching Shared Memories */
unsigned int *attachSharedMemoryC(int n);
void detachSharedMemory();
void detachAndReleaseSharedMemory();

/* Main */
int main() {

    // inits
    unsigned long long sum = 0;
    int n, sec, usec;
    struct timeval start, end;
    printf("Input the matrix dimension: ");
    scanf("%d", &n);

    initMemory(n);

    // 1-partition
    gettimeofday(&start, 0);
    sum = processOne(n);
    gettimeofday(&end, 0);
    sec = end.tv_sec - start.tv_sec;
    usec = end.tv_usec - start.tv_usec;
    printf("Multiplying matrices by 1 process: %f sec\n", sec + (usec/1000000.0));
    printf("Element Sum: %llu\n\n", sum);

    // 2-partition
    gettimeofday(&start, 0);
    sum = processTwo(n);
    gettimeofday(&end, 0);
    sec = end.tv_sec - start.tv_sec;
    usec = end.tv_usec - start.tv_usec;
    printf("Multiplying matrices by 2 processes: %f sec\n", sec + (usec/1000000.0));
    printf("Element Sum: %llu\n\n", sum);

    // 4-partition
    gettimeofday(&start, 0);
    sum = processFour(n);
    gettimeofday(&end, 0);
    sec = end.tv_sec - start.tv_sec;
    usec = end.tv_usec - start.tv_usec;
    printf("Multiplying matrices by 4 processes: %f sec\n", sec + (usec/1000000.0));
    printf("Element Sum: %llu\n\n", sum);

    //
    return 0;
}

void initMemory(int n){
    int i, j;
    for( i=0 ; i<n ; i++ ){
        for( j=0 ; j<n ; j++ ){
            A[i][j] = B[i][j] = i*n + j;
        }
    }
}

unsigned long long processOne(int n){
    int i, j, k;
    unsigned long long sum = 0;
    // calculate C
    for( i=0 ; i<n ; i++ ){
        for( j=0 ; j<n ; j++ ){
            unsigned int tc = 0;
            for( k=0 ; k<n ; k++ ){
                tc += (A[i][k] * B[k][j]);
            }
            sum += tc;
        }
    }
    return sum;
}

unsigned long long processTwo(int n){

    int i, j, k;
    C  = attachSharedMemoryC(n);

    // sum saves here
    unsigned long long sum = 0;

    // fork here
    pid_t pid;
    pid = fork();

    if(pid <0) {
        // if error, fork failed
        fprintf(stderr, "Fork Failed");
        exit(-1);
    }
    else if(pid == 0){
        // child, and calc the first part, i=0 ~ n/2
        for( i=0 ; i<n/2 ; i++ ){
            for( j=0 ; j<n ; j++ ){
                C[i*n + j] = 0;
                for( k=0 ; k<n ; k++ ){
                    C[i*n + j] += A[i][k] * B[k][j];
                }
            }
        }

        detachSharedMemory();
        exit(0);
    }
    else {
        // parent, i=n/2 ~ n
        for( i=n/2 ; i<n ; i++ ){
            for( j=0 ; j<n ; j++ ){
                C[i*n + j] =0;
                for( k=0 ; k<n ; k++ ){
                    C[i*n + j] += A[i][k] * B[k][j];
                }
            }
        }

        // if parent
        wait(NULL);

        // sum up here
        for( i=0 ; i<n*n ; i++ ) sum += C[i];
        detachAndReleaseSharedMemory();
    }

    return sum;
}

unsigned long long processFour(int n){

    int i, j, k;
    unsigned long long sum = 0;
    C  = attachSharedMemoryC(n);

    // fork here
    pid_t pid;
    pid = fork();

    if(pid <0) {
        // if error, fork failed
        fprintf(stderr, "Fork Failed");
        exit(-1);
    }
    else if(pid == 0){
        // fork here
        pid_t pid2;
        pid2 = fork();

        if(pid2 <0) {
            // if error, fork failed
            fprintf(stderr, "Fork Failed");
            exit(-1);
        }
        else if(pid2 == 0){
            // child, and calc the first part, i=0 ~ n/2
            for( i=0 ; i<n/2 ; i++ ){
                for( j=0 ; j<n/2 ; j++ ){
                    C[i*n + j] = 0;
                    for( k=0 ; k<n ; k++ ){
                        C[i*n + j] += A[i][k] * B[k][j];
                    }
                }
            }

            detachSharedMemory();
            exit(0);
        }
        else {
            // parent, i=n/2 ~ n
            for( i=n/2 ; i<n ; i++ ){
                for( j=0 ; j<n/2 ; j++ ){
                    C[i*n + j] = 0;
                    for( k=0 ; k<n ; k++ ){
                        C[i*n + j] += A[i][k] * B[k][j];
                    }
                }
            }

            wait(NULL);
        }
        detachSharedMemory();
        exit(0);
    }
    else {
        // fork here
        pid_t pid3;
        pid3 = fork();

        if(pid3 <0) {
            // if error, fork failed
            fprintf(stderr, "Fork Failed");
            exit(-1);
        }
        else if(pid3 == 0){
            // child, and calc the first part, i=0 ~ n/2
            for( i=0 ; i<n/2 ; i++ ){
                for( j=n/2 ; j<n ; j++ ){
                    C[i*n + j] = 0;
                    for( k=0 ; k<n ; k++ ){
                        C[i*n + j] += A[i][k] * B[k][j];
                    }
                }
            }
            detachSharedMemory();
            exit(0);
        }
        else {
            // parent, i=n/2 ~ n
            for( i=n/2 ; i<n ; i++ ){
                for( j=n/2 ; j<n ; j++ ){
                    C[i*n + j] = 0;
                    for( k=0 ; k<n ; k++ ){
                        C[i*n + j] += A[i][k] * B[k][j];
                    }
                }
            }

            // if parent
            wait(NULL);
            wait(NULL);

            // sum up here
            for( i=0 ; i<n*n ; i++ ) sum += C[i];
            detachAndReleaseSharedMemory();
        }
    }

    return sum;
}

void detachAndReleaseSharedMemory(){
    detachSharedMemory();
    if (shmctl(shmidC, IPC_RMID, 0) == -1) {
        fprintf(stderr, "shmctl(IPC_RMID) failed\n");
        exit(1);
    }
}

void detachSharedMemory(){
    if (shmdt(C) == -1) {
        fprintf(stderr, "shmdt failed\n");
        exit(EXIT_FAILURE);
    }
}

unsigned int *attachSharedMemoryC(int n){
    // setup shared memory
    key_t key = MAGIC_NUMBER;
    int shmflg = IPC_CREAT | 0666;

    if((shmidC = shmget(key, sizeof(unsigned int) * n * n, shmflg)) == -1) {
        perror("shmget: shmget failed");
        exit(1);
    }

    unsigned int *sC;
    if((sC = shmat(shmidC, NULL, 0)) == (unsigned int*)-1) {
        perror("shmat: attach error");
        exit(1);
    }

    return sC;
}

Friday, November 8, 2013

"Pitch It" is Released


App Site: http://pitchit.nctucs.net/
Apple Store: https://itunes.apple.com/us/app/pitch-it-perfect-pitch-challenge/id736721019?ls=1&mt=8

I've been working on this app, "Pitch It", for around one month. This interesting work is cooperated with Shumin, who has brought out lots of beautiful design and being a great partner.

"Pitch It" is a note guessing game. It plays a music note and ask to the user to tell if he/she can tell which note it is. People define a person who have "absolute pitch" or "perfect pitch" if he/she can answer more than 70% of the questions. With this app, the app can tell if you have "absolute pitch" or not.

On the other hand, this app is fast-implemented. I wanted to see how the Apple Store distribution works. That was a little complicated, and take a long for app reviewing by Apple. There, I write done time when the state is changed of this app on iTunes Connect.
  • Sat, Nov 2, 2013 at 12:38 AM: turned to Waiting For Upload
  • Sat, Nov 2, 2013 at 01:18 AM: turned to Waiting For Review
  • Fri, Nov 8, 2013 at 06:32 AM: turned to In Review
  • Fri, Nov 8, 2013 at 07:58 AM: turned to Processing for App Store
  • Fri, Nov 8, 2013 at 08:45 AM: turned to Ready for Sale
It means that takes 6 days for "Waiting For Review" state, and less than two hours for them to review and release.

Friday, November 1, 2013

解決Wordpress不能上傳多媒體檔案問題

Problem

若是這一台空的Linux機器安裝Wordpress,沒設定情況下會發現不能上傳相片,出現類似這樣的Error Message:"Unable to create directory wp-content/uploads"。
此問題來自上傳檔案這目標位置權限設定上並不能寫入,而網路上有許多做法是將 wp-content/uploads 改成777之類的,但這樣會變成任何人都可以讀寫,出現不合理的資訊安全問題。

Solution

這份網頁中提出很好的做法,即是將資料者擁有者換成www-data,然後只把讀寫的權限給擁有者。

(以環境為Ubuntu 12.04 with Apache為例)
mkdir <Web-root Directory>/wp-contents/uploads 
chgrp www-data <Web-root Directory>/wp-contents/uploads 
chmod 775 <Web-root Directory>/wp-contents/uploads

Reference