노트북에 쓰던 160기가짜리 하드가 ssd를 달고 그냥 usb외장하드로만 쓰고 있다가

nas를 쓸까 하다 찾은것이 pogoplug란 녀석을 알게 되었다.

전에도 라즈베리파이나 아두이노같은 작은 공대생 장난감을 하나 구해 가지고 놀까 하다가 딱히 쓸데가 생각안나 그만두었는데 포고플러그가 더 저렴하고 뭔가 이것저것 안붙이고 그냥 nas로만 쓸 수도 있겠다는 생각이 들어 이걸 구하기로 맘 먹었다.

국내에서 판매하는건 pogoplug mobile 만 있는데 이놈은 usb만 꽂을 수 있다.

sata를 지원하는건 B01/P21(600MHz, 128m 같은 플랫폼인듯), Series 4(800MHz, 128m) 두가지..

스펙으로는 E02가 1.2GHz에 256mb으로 젤 좋긴 한데 sata가 없어 탈락

B01은 sata 슬롯이 내부에만 있고 이걸 바로 꽂아쓰지 못하고 선을 밖으로 빼야 하고 Series 4는 뚜껑열고 그냥 하드를 꽂으면 된다.

그래서 Series 4를 몇일 중고장터에서 기다리다 4만원에 하나 구했다.

아마존 같은데 보니 보통 30달러 정도

순정으로 몇일 써봤는데 집안에서.. 그러니까 같은 네트워크 안에 있으면 그럭저럭 쓸만한데

외부네트워크로 연결하면...... 10메가 복사하는데 2~3분 이건 못쓴다ㅎㅎ

정확하게 분석해본건 아니지만 내부네트워크에서는 samba같은 프로토콜을 쓰고 외부인 경우는 미국에 있는 pogoplug서버를 거쳐 커넥션이 연결되는 방식이라 느린 것으로 보인다. 

순정으로는 못쓸거 같고 원래 가지고 놀려고 산 장난감이니 남들 다하는 대로 archlinux 설치 후 웹서버, FTP, webdav로 네트워크 드라이브로 쓸 생각이다.

구성은

pogoplug series 4 1대

8기가 usb메모리 1개

160기가 2.5인치 하드디스크

usb메모리에 리눅스를 올릴 거고 하드디스크는 스토리지 전용으로 마운트할 계획

정리하는게 귀찮아서 여기에 더 올릴지는 모르겠지만 일단 여기서 마무리.



AND

필요해서 찾아보니 kldp에 김정균님이 만들어놓으신 스크립트가 있어 올려본다.

duration 시간을 넣어서 해당 초당 트래픽을 재도록 수정해봤다.

#!/bin/sh
#
# Scripted by JoungKyun Kim
# 2001.2.15 http://www.oops.org
# This Script follows GPL2 License
#
# 2003. 1. 15 Modified to trap CTRL-c by kyong
# 2003. 1. 23 Added SECONDS arg, Kbps unit, minutes conversion and
# some cleanups by kyong
# 2010.05. 24 Modified Duration loop

IF="$1"
CHECK=/proc/net/dev
KMULTI=1024
#KMULTI=1000

start() {
    [ -f $CHECK ] || { echo "\"$CHECK\" does not exist." ; exit ; }
    fgrep -qs $IF: $CHECK || { echo "DEVICE \"$IF\" does not exist." ; exit ; }

    set `cat $CHECK | grep $IF: | cut -f2- -d:`
    IN0=$1
    OUT0=$9
}
stop() {
    local MSEC=$SECONDS

    set `cat $CHECK | grep $IF: | cut -f2- -d:`
    IN1=$1
    OUT1=$9
    let "IN = ($IN1 - $IN0) / ($MSEC * $KMULTI)"
    let "OUT = ($OUT1 - $OUT0) / ($MSEC * $KMULTI)"

    if [ $MSEC -lt 60 ] ;
    then
    MTIME="$MSEC second(s)"
    else
        let "MMIN = $MSEC / 60"
        let "MSEC = $MSEC - ($MMIN * 60)"
        MTIME="$MMIN minute(s) $MSEC second(s)"
        fi
        if [ $KMULTI -eq 1024 ] ;
        then
        KUNIT="KiB/s"
        elif [ $KMULTI -eq 1000 ] ;
        then
        KUNIT="KB/s"
        else
            KUNIT="?"
            fi

            #echo
            #echo "During $MTIME"
            echo "Inbound  : $IN $KUNIT (`let "IN=$IN*8"; echo $IN` Kbps)"
            echo "Outbound : $OUT $KUNIT (`let "OUT=$OUT*8"; echo $OUT` Kbps)"
            echo
}
usage() {
    echo "Usage : `basename "$0"` DEVICE [Duration Sec]"
    echo "Ex. : `basename "$0"` eth0"
    echo " `basename "$0"` eth0 10"
}

if [ $# = 0 -o $# -gt 2 ] ;
then
    usage ;
    exit
elif [ $# = 1 ] ;
then
    start ;
    trap 'stop;' SIGINT SIGQUIT
    echo "Ctrl-c to abort"
    sleep 365d
    exit 0
else
    while :
    do
        echo "$1 Interface [During $2 sec]"
        start ;
        unset SECONDS
        SECONDS=$2
        sleep $2
        stop ;
    done
fi

AND

파일명에 이상한 문자가 들어가거나 한 경우 rm으로 삭제가 안된다.

inode값으로 파일을 지우려면

find ./ -inum xxxx -exec rm -f {} \;

{} \; 안에 스페이스에 주목.. 빼먹으면 매개변수가 없다고 뭐라함..

AND

유닉스하고 맥은 \n을 개행문자로 쓰는데 윈도쪽은 \r\n을 개행문자로 쓴다.

윈도에서 작성한 텍스트를 가져가면 ^M 이 매 행마다 달려있다

삭제는 vi에서 :%s/^M//g 

^M은 Ctrl + v + m ..
AND

몇 일전 티맥스 코어에서 MS윈도우와 호환되는 국산 OS를 개발한다고 기자회견을 열었다.

관련기사
http://www.zdnet.co.kr/news/enterprise/os/0,39031185,39166973,00.htm
http://www.dt.co.kr/contents.html?article_no=2008032502010860744001


이러한 티맥스코어에 대한 의견이 분분한데 그에 대한 활발한 토론이
http://kldp.org/node/92098
에서 이루어 지고 있다.

주요 논쟁거리가 되는 것이 과연 MS윈도우와 100%호환 가능한 OS개발이 가능하느냐?
가능할지도 모른다 그러나 3년안에 완성하기는 불가능할 것이다.(OS쪽 개발인력이 100명 정도라는데..)
티베로(DMBS) 와 같은 행보를 걷는게 아니냐?
대부분의 분위기가 약간은 부정적인 의견이 많아 보인다.
데스크탑 뿐만 아니라 임베디드 및 서버용 OS도 같이 개발하고 있다고 하는데
임베디드, 서버용 OS는 그 사용 대상이 약간은 한정되어 있고 특화를 잘 시키면 가능성은 있어 보인다.
그런데 데스크탑은 사용 대상이 일반인이고 자주사용하는 프로그램 한두개만 호환이 되지 않아도
외면받을 것이다. 더군다나 win32 API중에는 자사제품에만 사용하는 비공개 API가 있는데
이러한 부분이 호환성과 문제에 최대 관건이라 생각된다.

어쨌든 우리나라에서 OS를 개발한다니 반가운 소식이다.
하지만 국산이란 이름의 타이틀로는 이제 더 이상 성공할 수 없는 시대다.
예전이야 애국심이다 뭐다 해서 국산 프로그램을 밀어주는 분위기었지만(지금도 정부기관 같은 곳은
의무적으로 어느정도 국산 프로그램을 사용해야한다는 규정이 있는 것으로 안다.)
이제는 단순히 애국심하나만으로 국산 프로그램을 사용하는 시대는 지났다.
과거 한글과 컴퓨터와 같은 상황이 벌어지지 않았으면 좋겠고(그 때 상황과 지금 상황을 비교하긴 조금 뭐하지만..) 용두사미가 되지 않았으면 좋겠다.
어쨌든 티맥스의 어찌보면 무모하면서도 기개있는 도전정신은 높이 평가 하고 싶다. 그리고 좋은 결과가 있길 바란다..
AND

OS분석(4) picoKernel

OS 2007. 12. 28. 14:01
3. IPC
IPC(Inter Process Communication)는 프로세스간 상호 통신을 말한다.
구현방법에서 크게 두가지 방법으로 나눌수 있는데 하나는 공유 메모리이고 두번째는 메시지 전달 방식이다.

공유메모리 방식은 송신측과 수신측이 일정한 메모리 공간을 공유하고 송신측이 이 공간에 데이터를 쓰면 수신측이 읽어 가는 형태이다.
공유 메모리 방식의 동기화를 위해서는 수신측은 송신측이 데이터를 기록하였는지 알아야 하고 송신측은 수신측이 데이터를 읽어갔는지 여부를 알아야 하며 이를 활용하는 프로그래머는 적절한 동기화 절차를 거쳐야 한다.
데이터를 바로 읽어가기 때문에 오버헤드가 크지 않기 때문에 큰 데이터를 전달할 때 유용하지만 동기화문제를 신경써야한다.

메시지 전달 방식은 운영체제가 커널 내부에서 메시지를 기록할 수 있는 공간을 두고 적절한 시스템 콜을 통해 메시지의 송수신을 운영체제에게 요구할 수 있도록 하는 방식이다. 즉 커널이 메시지를 받아 전달시켜주는 방식이다. 대표적인 예가 메일박스이다. 이 방식의 동기화의 경우 메시지를 위한 공간이 꽉 찼을 경우 송신측이 대기하여야 하고 반대로 비어있을 경우 수신측이 대기해야한다. 메시지를 커널로 복사하고 이 메시지를 다시 수신측에게 복사해야하므로 오버헤드가 큰 대신 동기화에 대한 문제를 크게 신경쓰지 않아도 되어서 메시지 양이 작은 경우 사용하면 유용하다.

picoKernel에는 프로세스간 통신을 위해 메일박스, 랑데부, 시그널이 구현되어 있다.

3.1 메일박스
메일박스는 메시지 전달방식으로 내부에 버퍼를 두고 송신측이 이 버퍼에 데이터를 전달하고 수신측이 이 버퍼에서 데이터를 받아가는 형식으로 되어 있다.
메일박스의 엔트리를 보면 해당 메일박스가 비어있는지 차있는지에 대한 세마포어와 순환 버퍼의 시작과 끝을 가르키는 인덱스, 메시지 버퍼(순환 버퍼)로 구성되어 있다. 또한 메일박스를 사용하기 위한 뮤택스와 사용하고 있는 메일박스의 엔트리 개수를 나타내는 변수가 있다.

메일박스의 생성은 mboxCreate이고 초기화시 메일박스 테이블에 대한 초기화, 해당 메일박스가 비어있는지 꽉차있는지를 확인하고 기다리는 세마포어의 초기화 후 메일박스의 id를 리턴한다.

mboxSend는 메시지를 전송하는 함수이다. 매개변수로 메일박스의 id와 메시지에 대한 포인터를 받는다.
메시지를 전달할 때 세마포어를 통해 메시지 버퍼가 비어있기를 대기한다. 메시지가 비어있게 되면 메시지를 버퍼 공간에 쓰기 위해 뮤택스로 락을 걸어두고 메시지를 저장후 버퍼공간의 헤드와 테일 인덱스를 업데이트 한다. 락을 해제한 후 수신측이 읽어도 된다고 세마포어를 통해 시그널을 보낸다.

mboxRecive는 메시지를 수신하는 함수이며 마찬가지로 매개변수를 id와 메시지를 받을 포인터를 받는다.
메시지가 저장되었다는 세마포어의 시그널을 기다렸다가 시그널이 오면 뮤택스로 락을 걸고 데이터를 읽어온다. 헤드 인덱스를 초기화 한 다음 뮤택스 락을 해제한 후 버퍼가 비었다는 세마포어의 시그널을 보내 다음 메시지가 버퍼에 저장될 수 있도록 한다.

3.2 랑데부
랑데부는 극단적으로 버퍼가 0인 통신이다. 말 자체로 송신측과 수신측이 만나서 데이터를 전달 받는 형식이다. 메일박스가 내부의 버퍼를 두고 통신을 하는데 반해 랑데부는 버퍼 없이 송신측이 수신측으로 바로 데이터를 전달한다.

메일박스와 비슷하게 rendCreate, rendSend, rendRecive로 구성되어 있다. 랑데부의 엔트리는 송신측과 수신측의 thread id, 대기와 완료를 알리는 세마포어, 메시지로 구성되어 있다.

랑데부를 생성하게 되면(rendCreate), 송신측과 수신측의 thread 번호를 등록하고 세마포어를 초기화한 후 랑데부 아이디를 리턴한다.

rendSend는 랑데부 id와 메시지를 매개변수로 받고 수신측이 대기상태가 될때까지 세마포어를 통해 기다린다. 수신측 대기상태의 세마포어 시그널을 보내면 메시지를 복사하고 완료했다는 세마포어 시그널을 보낸다.

rendRecive 역시 id와 메시지를 저장할 공간을 매개변수로 받아 포인터를 연결시킨다음 대기상태라는 세마포어 시그널을 송신측에 보내 데이터를 전달 받은 다음 완료했다는 세마포어 시그널을 보낸다.

3.3 시그널
시그널이 구현되기 위해서는 thread control block에 시그널 번호별로 해당 핸들러 함수를 등록해야하고 초기화시 0으로 세팅한다.

signalSet함수는 시그널 번호에 따른 핸들러 함수를 등록시키는 함수이고 signalSend는 시그널을 보내는 함수이다. signalSend함수를 호출해서 해당 핸들러가 성공적으로 호출되었으면 1로 설정되어있던 비트를 다시 초기화 시켜준다.

해당 스레드가 running상태가 아니라면 running가 된 후 즉 문맥교환이 이루어진 후에 시그널이 왔는지를 확인해야한다.


AND

OS분석(3) picoKernel

OS 2007. 12. 27. 16:41
2. 동기화
멀티태스킹으로 일을 처리하게 되면 둘 이상의 프로세스 혹은 스레드가 동시에 한 데이터에 접근하는 경우가 발생하는데 이럴 때 동기화 문제가 발생한다.
A와 B라는 두개의 스레드가 있고 alpha라는 공유변수가 있다고 가정할 때
두 스레드 A, B가 동시에 alpha라는 변수에 접근하여 데이터를 변경한다면 문제가 발생할 수 있다.
또한 두 스레드 A, B에서 변수 alpha에 접근하는 부분을 크리티컬 섹션 혹은 크리티컬 리젼이라고 부르며
이 섹션들 간에는 상호 배재 즉 상대방이 실행하고 있으면 다른 녀석들은 이에 접근할 수 없도록 조치해야한다.
picoKernel 에서는 이러한 상황을 해결하기 위한 동기화 방법에는 아래와 같은 방법이 있다.
뮤텍스(mutex)
세마포어(semaphore)
조건변수(condition variable)

2.1 뮤텍스
뮤텍스는 일종의 변수이고 해당 크리티컬 섹션에 대해 lock상태인지 아닌지에 대한 정보를 가지고 있다.
크리티컬 섹션에 진입할 때 해당 섹션이 lock상태이면 unlock이 될 때까지 기다리게 되는데
unlock이 될 때까지 계속 체크하는 비지 웨이팅방식이 아니라 해당 스레드 혹은 프로세스가 running상태에서
waiting상태로 넘어가게 된다. 다시 크리티컬 섹션에 진입할 때 unlock상태이면 자신이 진입했다는 표시로
lock을 걸어둔다. lock을 걸어둔 스레드 혹은 프로세스가 unlock을 할 때는 프로세스의 대기 목록에서 lock이 풀리기를 기다리는 프로세스들 중 하나를 깨워준다.

picoKernel에서는 뮤텍스로 사용할 변수를 선언하고 mutexCreate함수를 호출한다.
내부적으로 전체 뮤텍스의 엔트리를 가지고 관리하며 아직 할당하지 않은 뮤텍스의 id를 반환한다.
뮤텍스 엔트리의 구조체는 unlock을 기다리는 thread의 리스트를 가리키기 위한 thread엔트리 포인터(mHead, mTail)와 현재 lock을 걸어둔 thread의 엔트리 포인터(mOwner)를 가지고 있다.

mutexLock함수로 크리티컬 섹션에 진입할 때 내부적으로 mOwner가 null이 아니면 lock상태이고
null이면 unlock상태이다. null이 아니어서 lock상태라면 자신(thread)의 상태를 waiting상태로 바꾸고
해당 뮤텍스의 대기 리스트에 저장후 대기하고 있던 리스트안에 있는 thread를 실행하게 된다.

mutexUnlock함수는 대기중인 스레드 중에서 하나만 ready상태로 전환한다.
해당 뮤택스의 mOwner를 null로 바꾸고 내부에 해당 뮤텍스에 등록되어 있는 대기 리스트를 업데이트 한다.

2.2 세마포어
세마포어는 뮤택스보다는 조금 확장된 개념으로 볼 수 있는데 뮤택스가 해당 크리티컬 섹션에 진입할 수 있는 스레드나 프로세스의 개수가 하나라면 세마포어는 하나 이상으로 설정할 수 있다.
개념은 뮤택스와 비슷하다.
picoKernel에서는 세마포어 엔트리로 세마포어를 관리하는데 하나의 엔트리는 뮤택스와 마찬가지로 대기하고 있는 thread 엔트리 포인터(sHead, sTail)가 있고 세마포어 값으로 구성되어 있다.

세마포어를 사용하기 위해 초기에 semCreate 함수를 호출하는데 매개변수로 세마포어의 값을 입력받는다.
비어있는 세마포어 id를 리턴한다.

semWait함수는 해당 세마포어가 가진 값이 0보다 크면 해당 크리티컬 섹션에 진입이 가능하며 초기에 세마포어를 생성했던 값을 -1하게 된다. 여러 thread들이 semWait를 호출하게 되여 세마포어의 값이 0이 되면 더 이상 다른 스레드의 진입이 불가능하고 이 때 해당 스레드가 waiting상태로 넘어가게 된다.

semSignal함수는 반대로 크리티컬 섹션에서 나올 때 세마포어의 값을 1 증가시키며 대기하고 있던 스레드중에 하나를 깨우게 된다. 뮤택스와 마찬가지로 대기리스트를 업데이트한다.

2.3 조건변수
조건변수로 선언후 wait, signal로 사용하는데 해당 변수 예를 들어 a라는 조건 변수가 있을 때
a.wait()을 호출하면 다른 프로세스 혹은 다른 thread에서 a.signal()을 호출할 때까지 무조건 대기한다.

picoKernel에서는 condCreate함수로 초기화를 하고 조건변수의 id를 리턴한다.
조건변수의 엔트리는 해당 조건을 기다리고 있는 스레드의 개수와 동기화를 위한 세마포어로 구성되어 있다.

condWait함수는 id와 모니터로 사용하는 뮤텍스를 인자로 넘겨받아 조건변수 엔트리의 대기 스레드 개수를 +1 해주고 다른 스레드에서 Signal을 보낼때까지 기다릴 수 있도록 semWait하게 된다. 이 때 뮤택스로 조건변수와 semWait를 보호한다.

condSignal함수는 해당 조건변수의 대기 스레드 카운터가 0보다 크면 즉 비어있지 않으면 카운터값을 -1시키고 해당 세마포어를 semSignal하게 된다. 역시 이 부분도 뮤택스로 보호해주어야 한다.


AND

OS분석(2) picoKernel

OS 2007. 12. 17. 23:56
1.3 picoKernel의 thread 생성
picoKernel에서 함수는 thread로 등록할 수 있다.
thread의 생성은 threadCreate()함수로 처리한다.
thread의 관리는 thread entry structure로 처리한다.

아래는 thread하나의 entry structure이다.
----------------------------------------------------------------------
typedef struct threadEnt {
    struct threadEnt *tNext;        // point to next thread entry

    enum threadState tState;        // thread state
    int tPrio;              // thread priority

    int (*tStart)(int);         // start function address
    int tArg;               // argument of tStart()

    char *tStack;           // stack base address
    int tStackSize;         // stack size in bytes

    unsigned long tContext;     // address of context area

#ifdef KERNEL2 // .........
    // fields for signal operation
    void (*tSigTab[NUM_SIGNAL])(int);   // handler functions
    unsigned short tSignals;        // signal bits
#endif // KERNEL2 .........

#ifdef PROCESS
    struct procEnt *tProc;      // the process of this thread
    struct threadEnt *tSibling;     // threads of the same process
#endif

} threadEntT;
----------------------------------------------------------------------

threadCreate()는 3개의 매개변수를 받는데
첫번째 매개변수가 우선순위, 두번째 매개변수가 함수의 주소, 세번째 매개변수가
함수의 매개변수이다.
threadCreate()가 실행되면 threadEntT 를 하나 만들고 넘어온 thread의 정보를
threadEntT에 저장하고 context정보를 할당한다. context정보가 있어야
다른 thread가 동작하다가 context switch가 일어나도 상태를 유지할 수 있다.
tContext에 이 정보가 저장된다.

context정보는 스택에 저장되는데 처음 threadInit()함수에서 영역을 할당하고
threadCread함수에서 해당 context정보를 스택에 저장한다. 그리고 context의 위치정보를
tContext가 가지고 있다.
context정보를 담는 stack은 여러 thread의 context를 담고 있는 stack이다.
하나의 블록이 하나의 thread의 문맥정보를 가지고 있으며
각 thread는 이 위치를 알아야 문맥교환이 가능하다.

일련의 과정이 끝나면 thread가 스케줄러에 등록이 되면서
등록되어 있는 thread목록중에서 가장 우선순위가 높은 thread가 실행된다.
다른 thread가 동작하고 있다가도 새로운 thread가 등록되었을 때
새로 등록한 thread의 우선순위가 높다면 새로운 thread가 실행되게 된다.
(schedRunHighest())

threadExit()는 현재 동작하고 있는 thread를 종료하겠다는 의미이다.
현재 동작하고 있는 thread의 제어권을 다른 thread로 넘기고
thread의 리스트에서 자신의 목록을 제거하고
schedRunHighest()로 우선순위가 가장 높은 thread를 실행한다.

threadYield()는 동작하던 일을 멈추고 다른 thread에게 제어권을 양보하는 것이다.
제어권을 다른 thread에게 넘기고 자신의 정보를 스케줄러의 ready list에 등록한다.

대략 정리하자면
thread를 생성하려면 thread의 정보를 가진 구조체에 thread의 내용을 저장해야한다.
이 내용에는 자신의 함수 주소, 매개변수, 우선순위, context의 위치, thread의 상태
를 저장하고 스케줄러에 자신을 등록한다.

1.4 picoKernel scheduling
picoKernel에서는 thread의 리스트를 Running, Ready, Free 3개로 나타낸다.
3개의 포인터 모두 thread의 리스트를 가리키고 있다.
scheduling의 시작은 thread의 생성부터 시작된다.
thread를 생성하게 되면 상태를 ready상태로 두고 스케줄러의 Ready리스트에 등록하고
우선순위가 가장 높은 thread를 실행하게 한다.

schedInsertReady()함수가 thread를 생성할 때 ready 리스트에 등록하는 함수인데
링크드리스트로 되어 있는 ready 리스트에 우선순위 순서대로 등록된다.

schedRunHighest()함수는 현재 우선순위가 가장 높은 thread로 문맥교환하게 된다.
만약 현재 동작하고 있는 thread와 readlist에 있는 첫번째 thread의 우선순위가
같다면 문맥교환을 하지 않는다. 문맥교환을 하게 되면
현재 동작하고 있는 thread는 readlist로 이동하게 된다.
AND

OS분석(1) picoKernel

OS 2007. 12. 17. 23:54
OS를 공부하는데 있어서 OS가 동작하는 이론적인 문제도 중요하지만
실제로 OS가 어떻게 동작하는지 알아보는 일도 중요하다.
초보자 입장에서 현재 동작하고 있는 최신 리눅스 커널 소스를 보는 일은
이제 막 걸음마를 시작한 애가 장대 높이 뛰기 선수들이 쓰는 장대를 만지작
거리는 일과 다르지 않으리라 생각한다.
그래서 시작은 picoKernel과 linux 커널 0.1 버전을 분석해보는 일부터 시작하려 한다.

1. picoKernel
분석해보려는 picoKernel은 우리 교수님께서 만든 교육용 커널이다.
실제 소스의 길이도 2000정도 밖에 안되는 교수님 말을 빌리면 만만한 커널이다.
가벼워도 OS의 핵심적인 기능은 대부분 갖추고 있다.
물론 이것을 실제 운영체제로 사용하려면 각종 유틸들이나 파일시스템등 여러가지가
필요하지만 picoKernel 은 실제 OS 내부에서 사용하는 멀티태스킹, 스케줄링,
동기화에 필요한 뮤텍스, 세마포어, 공유메모리등이 구현되어 있다.
예전에 프로젝트 때문에 임베디드용 OS를 몇개 본적이 있었는데 그 구조가
picoKernel과 크게 다르지 않았다. 세부적인 내용은 조금씩 차이는 있지만
대략적인 구동방식이나 구조는 대동소이했다.
MicroC/OS나 ETRI에서 얼마전에 공개한 nanoQplus, 콜로라도 대학의 MANTIS 등과
같은 소형 임베디드 OS들은 모두 picoKernel과 같이 멀티태스킹과 동기화와 IPC를 위한
기능을 지원한다.

1.1 picoKernel 특징
picoKernel은 멀티태스킹이 가능한 OS이다. picoKernel자체가 하나의 프로세스이므로
프로세스내에서의 멀티태스킹은 thread방식이다.
picoKernel은 비선점형 스케줄링에 해당하는데 비선점형 자발적인 종료나 wait, 양보의 경우에만
다른 작업으로 제어권을 넘기게 되고 다른 인터럽트나 새로운 작업의 등록으로 인해
현재 작업중인 제어권이 바뀌지 않는 형태를 비선점형 스케줄링라고 한다.
picoKernel는 인터럽트의 처리를 제외하면 선점형 스케줄링으로 볼 수 도 있다.
picoKernel이 선점형 스케쥴링이 되려면 인터럽트에 대한 처리를 따로 처리해야하며
이때 발생하는 크리티컬 섹션 문제가 해결되어야만 선점형 스케쥴링이 될 수 있다.

여담..
프로젝트 할 때 AVR에 타이머 인터럽트를 통해서 선점형 스케쥴러 비스므리하게
강제적으로 시간이 지나면 스케줄링이 일어나게 했던 적이 있었는데.
OS와 통신모듈을 통합하고 나니까 통신모듈이 동작을 안하는 것이다.
통신모듈에 문제가 있는 줄 알고 몇주를 헤맸는데 결국 문제는 타이머 인터럽트로 인한
강제적인 스케줄링으로 인해 통신중에 문맥이 바뀌어버리는 것이다.
당연히 데이터가 날라가는 중에 스케줄링이 일어나면 데이터가 전송되다 만다..
타이머 인터럽트는 생각도 안하던 문제여서 통신 모듈상에 인터럽트 방지도 안해놨고
문맥교환시 데이터의 동기화역시 생각도 안하던 문제여서 결국 타이머 인터럽트에
걸려있던 강제 스케줄링을 삭제했던 기억이 있다.

1.2 picoKernel의 동작
picoKernel은 실제 OS라기보다는 교육목적으로 만들어졌기 때문에 리눅스나
Cygwin같은 환경에서 하나의 프로세스로 동작한다. 커널 하나가 하나의 프로세스로 동작하고
그 안에서 여러 thread를 생성해서 동작한다.

picoKernel은 기본적으로 nullMain과 userMain 2개의 thread로 동작한다.
nullMain은 말 그대로 비어있는 루틴이고 userMain은 사용자가 일을 처리할 때
사용하는 루틴이다. 두개의 thread가 등록이 되고 우선순위에 따라 동작한다.
thread생성시 userMain의 우선순위가 높기 때문에 userMain함수안에서
다른 thread를 생성하지 않는다면 userMain을 먼저 처리하고 끝나면
nullMain을 실행하고 종료한다.
nullMain을 보면 thread가 실행되면 바로 threadYield로 다른 thread로 제어권을 넘긴다.
userMain에서 thread를 생성하면 그 우선순위에 따라 thread를 실행하고
종료하게 된다.
AND

.vimrc 설정

OS/Linux 2007. 12. 7. 23:30
set cindent
set number
set shiftwidth=4
set smartindent
set ts=4

if has("syntax")
  syntax on           " Default to no syntax highlightning
endif

au FileType * set fo-=ro
set bg=dark
au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal g'\"" | endif

func! Man()
let sm = expand("<cword>")
exe "!man -S 2:3:4:5:6:7:8:9:tcl:n:l:p:o ".sm
endfunc

if $LANG[0] == 'k' && $LANG[1] == 'o'
set fileencoding=korea
endif

map <F1> :call Man()<CR><CR>

map <F3> :q!<CR>
map <F4> :wq<CR>

map <F5> :norm i//<CR>
map <F6> :norm xx<CR>

map <F9> v]}zf
map <F10> zo
map <F11> zc

AND