이름

ioctl - 장치를 제어한다.

사용법

#include <sys/ioctl.h>

int ioctl(int d, int request, ...)

[세번째 인자는 전통적으로 char *argp 이며, 설명를 위해 그렇게 언급하겠다.]

설명

ioctl 함수는 특수 파일의 장치 인자를 조절한다. 특히, 문자 특수 파일(예로 터미널)의 많은 특징적인 동작은 ioctl의 요구에 의해 제어된다. d 인자는 반드시 열린 파일 기술자이어야 한다.

ioctl request는 인자가 입력되는 인자인지 출력되는 인자인지와 argp 인자의 바이트 단위의 크기를 나타낸다. ioctl request를 나타내기 사용되는 매크로와 상수는 <sys/ioctl.h>파일에 정의되어 있다.

반환값

성공시, 0이 리턴된다. 에러시, -1이 리턴되며, errno는 적당한 값으로 설정된다.

에러

EBADF
d는 유효한 기술자가 아니다.
EFAULT
argp 는 접근할 수 없는 메모리 영역을 참조한다.
ENOTTY
d 는 문자 특수 파일과 연관되지 있지 않다.
ENOTTY
명시한 request는 파일 기술자 d 에 해당하는 객체에 적용되지 않는다.
EINVAL
request또는 argp가 유효하지 않다.

호환

단일 표준이 없다. 인자, 반환값과 ioctl(2) 의미는 요청되는 장치 드라이버에 따라 달라진다. (이 시스템 콜은 유닉스 스트림 I/O 모델에 깨끗하게 맞지 않는 연산을 위한 대체 방법으로써 사용된다.)

알려져있는 많은 ioctl 호출 리스트를 보기 원한다면 ioctl_list(2) 를 참조해라. ioctl 함수는 Version 7 AT&T Unix에서 나타났다.

관련 항목

execve(2), fcntl(2), mt(4), sd(4), tty(4)
by sminchoi 2008. 8. 11. 17:09
쓰레드에서의 데이터 동기화 문제

예를 들어서 두개의 쓰레드가 2개의 변수를 업데이트하려고 하는데, 하나의 쓰레드는 2개의 변수를 0으로 다른 하나는 1로 변경을 시도한다고 하자. 만약 이러한 변경이 같은 시간(same time)에 일어난다면 하나는 0으로 변경이 되었지만 다른 하나는 1로 변경되는 문제가 발생할수도 있을것이다. 이러한 경우 충돌이 발생할 수 있을 것이다. 하나의 쓰레드가 변경하고자 하는 첫번째 변수를 0으로 바꾸었는데, 2번째 변수를 0으로 바꾸기 전에 다른 쓰레드가 변수를 모두 1로 바꾸어 버릴수 있기 때문이다. 그리고 나서 다시 첫번째 쓰레드가 두번째 변수를 0으로 바꾸게 되면, 첫번째 변수는 1이지만 두번째 변수는 0이 되는 데이타 불일치 상황이 발생하게 될것이다.

int a = 1; 
Thread A 에서 a를 읽어들인다. 
Thread B 에서 a를 읽어들인다. 
Thread A 에서 a = a+1를 한다. 
{ 
    a = a+1; 
    결과는 2; 
} 
Thread B 에서 a++를 한다. 
{ 
   a = a + 1; // 읽어들인 값이 1이기 때문에 
   역시 결과는 2가 된다. 
} 
 
두번의 a+1 과정을 거쳤음으로, a가 3이 되는걸 기대하겠지만 이러한 류의 동시접근 문제로 a는 2가 되어버리고 만다.
Mutex를 이용하면 된다.

pthread 라이브러리는 이러한 문제의 해결을 위해서 mutex 라는 것을 사용한다. mutex 는 IPC에서 데이타 접근 통제를 위해서 사용하는 세마포어와 매우 비슷한 일을한다. mutex 는 세마포어와 마찬가지로 잠금 을 사용하는데, mutex 는 lock 에 대해서 다음과 같은 3가지 사항에 대해서 보증한다.

  • Atomicity - mutex 잠금(lock)는 최소단위 연적(atomic operation) 으로 작동한다. 이말의 뜻은 하나의 쓰레드가 mutex 를 이용해서 잠금을 시도하는 도중에 다른 쓰레드가 mutex 잠금을 할수없도록 해준다는 뜻이다. 한번에 하나의 mutex 잠금을 하도록 보증해준다.
  • Singularity - 만약 스레드가 mutex 잠금을 했다면, 잠금을 한 쓰레드가 mutex 잠금을 해제 하기 전까지 다른 어떠한 쓰레드도 mutex 잠금을 할수 없도록 보증해준다.
  • Non-Busy Wait - 바쁜대기 상태에 놓이지 않는다는 뜻으로, 하나의 쓰레드가 mutex 잠금을 시도하는데 이미 다른 쓰레드가 mutex 잠금을 사용하고 있다면 이쓰레드는 다른 쓰레드가 락을 해제하기전까지 해당 지점에 머물러 있으며 이동안은 어떠한 CPU 자원도 소비하지 않는다 (이를테면 sleep).
mutex 는 위의 3가지 사항을 보증해 줌으로 우리는 쓰레드 공유되는 메모리를 충돌없이 사용할수 있게 된다. mutex 를 통해서 잠금을 얻는 것을 간단하게 나타내면 아래와 같다(pseude-code 형식으로 설명하겠다). 일단 첫번째 쓰레드는 다음과 같이 mutex 를 이용해서 변수 업데이트 작업을 하게 될것이다.
'X1' 에 대해서 뮤텍스 잠금을 한다.
첫번째 변수를 0으로 세팅한다.
두번째 변수를 0으로 세팅한다. 
'X1' 뮤택스의 잠금을 해제한다. 

그리고 나서 2번째 쓰레드가 뮤텍스를 이용한 변수 업데이트 작업을 하게 될것이다.

'X1' 에 대해서 뮤텍스 잠금을 한다.
첫번째 변수를 1으로 세팅한다.
두번째 변수를 1으로 세팅한다. 
'X1' 뮤택스의 잠금을 해제한다. 

2개의 쓰레드가 같은 mutex 'X1' 을 사용한다고 가정하면 이 코드는 어떠한상황 에서도 두개의 변수를 '0' 혹은 '1' 로 유지할것이라는걸 보증할수 있을것이다. mutex 를 이용해서 이러한 작업을 할때 프로그래머는 어떠한 상황에서 mutex 를 써야할지에 대해서 주의를 기울여야 한다.
만약 3번째 쓰레드가 mutex 를 사용하지 않은체 변수에 업데이트 작업을 하게 될경우 앞의 2개의 쓰레드가 mutex 를 사용한 이유가 사라지게 된다.

뮤텍스 생성과 초기화

뮤텍스를 생성하기 위해서 우리는 먼저, 뮤텍스정보를 저장하기 위한 타입인 pthread_mutex_t 를 선언해주고 이것을 초기화 해주어야 한다. 선언과 초기화의 가장간단한 방법은 PTHREAD_MUTEX_INITIALIZER 상수를 할당하는 것으로 아래와 같이 사용할수 있다.

pthread_mutex_t a_mutex = PTHREAD_MUTEX_INITIALIZER; 
 
뮤텍스 잠금, 잠금해제, 제거

뮤텍스 잠금을 위한 함수로는 pthread_mutex_lock() 함수를 제공한다. 이 함수는 해당 뮤텍스에 대해서 잠금을 시도하는데, 만약 잠그려는 뮤텍스가 다른 쓰레드에 의해서 이미 잠겨있다면, 잠금을 얻을수 있을때까지 - 이미 잠근 다른 쓰레드가 뮤텍스의 잠금을 해제할때까지 - 봉쇄(블럭)되게 된다. 다음은 이러한 뮤텍스 잠금을 얻기 위한 지원함수들이다.

int pthread_mutex_lock(pthread_mutex_t *mutex); 
int pthread_mutex_trylock(pthread_mutex_t *mutex); 
int pthread_mutex_destory(pthread_mutex_t *mutex); 
 

pthread_mutex_trylock() 를 사용하면 잠금을 얻을수 없을경우 해당 코드에서 블럭되지 않고 바로 에러코드를 돌려준다. 즉 pthread_mutex_lock 의 비봉쇄 버젼이라고 생각하면 된다.

뮤텍스 잠금을 얻은후 해당 영역에서의 작업을 마친후 잠금을 해제하기 위해서 사용한다. 사용되는 함수는 pthread_mutex_unlock(3) 이며 함수원형은 다음과 같다.

int pthread_mutex_unlock(pthread_mutex_t *mutex); 
 
다음은 쓰레드간 공유되는 자원을 위해서 잠금을 어떻게 사용하는지를 보여주는 간단한 예제다.
예제: mutex_lock.c
#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 

int ncount;    // 쓰레드간 공유되는 자원
pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER; // 쓰레드 초기화

void* do_loop(void *data)
{
    int i;

    pthread_mutex_lock(&mutex); // 잠금을 생성한다.
    for (i = 0; i < 10; i++)
    {
        printf("loop1 : %d", ncount);
        ncount ++;
        sleep(1);
    }
    pthread_mutex_unlock(&mutex); // 잠금을 해제한다.
}

void* do_loop2(void *data)
{
    int i;

    // 잠금을 얻으려고 하지만 do_loop 에서 이미 잠금을 
    // 얻었음으로 잠금이 해제될때까지 기다린다.  
    pthread_mutex_lock(&mutex); // 잠금을 생성한다.
    for (i = 0; i < 10; i++)
    {
        printf("loop2 : %d", ncount);
        ncount ++;
        sleep(1);
    }
    pthread_mutex_unlock(&mutex); // 잠금을 해제한다.
}    

int main()
{
    int       thr_id;
    pthread_t p_thread[2];
    int status;
    int a = 1;

    ncount = 0;
    thr_id = pthread_create(&p_thread[0], NULL, do_loop, (void *)&a);
    sleep(1);
    thr_id = pthread_create(&p_thread[1], NULL, do_loop2, (void *)&a);

    pthread_join(p_thread[0], (void *) &status);
    pthread_join(p_thread[1], (void *) &status);

    status = pthread_mutex_destroy(&mutex);
    printf("code  =  %d", status);
    printf("programing is end");
    return 0;
}

위의 코드를 우선 mutex 잠금을 하지 않은체 컴파일후 실행해보자. 간단하게 pthread_mutext_lock 와 pthread_mutex_unlock 부만 주석처리하면 된다. 그러면 do_loop2 와 do_loop 가 일정한 간격을 두고 ncount 자원에 접근하는 것을 볼수 있을것이다. 그러나 우리는 do_loop 가 ncount 자원을 접근하고 있는동안 다른 쓰레드가 접근하지 않기를 원할때가 있을것이다. 이럴때 뮤텍스 잠금을 사용하면 된다.

위의 코드에서 뮤텍스 잠금 부분의 주석을 풀고 다시 컴파일해서 실행시켜보면, do_loop 쓰레드가 ncount 증가 작업을 모두 마칠때까지 do_loop2 쓰레드는 해당 영역에서 블럭됨을 알수 있을것이다. 이런식으로 하나의 쓰레드가 특정자원에 접근할때 다른 쓰레드가 접근하지 못하도록(한번에 하나의 쓰레드만 해당 자원에 접근할수 있도록) 제어할수 있다.

컴파일 방법은 gcc -o mutex_lock mutex_lock.c -lpthread 이다

더이상 뮤텍스를 사용할일이 없다면 pthread_mutex_destory 를 이용해서 뮤텍스 자원을 제거(free) 하도록 한다. 만일 뮤텍스자원을 사용하는 쓰레드가 하나라도 존재한다면 에러코드(EBUSY)를 리턴한다. 그러므로 모든 쓰레드의 뮤텍스에 대해서 pthread_mutex_unlock 을 이용해서 잠겨져야만 뮤텍스 제거가 성공할수 있다. 성공할경우 0을 넘겨준다.

2008/08/01 - [C/C++] - [스크랩] 쓰레드는 무엇이며, 왜 이용하는가 - 조인시 위키

'C/C++' 카테고리의 다른 글

this 포인터  (0) 2008.08.13
[스크랩] ioctl()  (0) 2008.08.11
[스크랩] 쓰레드는 무엇이며, 왜 이용하는가 - 조인시 위키  (0) 2008.08.01
[스크랩] volatile - c keyword  (0) 2007.05.15
gcc 옵션  (1) 2007.04.12
by sminchoi 2008. 8. 1. 14:18
쓰레드는 무엇이며, 왜 이용하는가

쓰레드는 세미(semi)프로세스, 혹은 Light Weight 프로세스라고 불리우며, 여러개의 클라이언트를 처리하는 서버/클라이언트 모델의 서버프로그래밍 작업을 위해서 주로 사용된다. 비슷한 일을 하는 fork(2) 에 비해서 빠른 프로세스 생성 능력과, 적은 메모리를 사용하는게 Light Weight 프로세스라고 불리우는 이유이다.

보통의 유닉스 프로세스는 main()함수에 의해서 시작되고 실행되는 single 쓰레드 로 이루어지며, 하나의 연속된 명령어들만을 처리한다. 반면 멀티쓰레드 프로그램은 여러개의 연속된 명령어들을 동시에 처리할수 있다.

스레드는 자기자신의 스택메모리영역을 가지고, 코드의 조각을 실행한다. (real) 프로세스 와는 달리 쓰레드는 다른 형제 쓰레드들과 메모리를 공유하게 된다.(보통 프로세스는 자기자신만의 메모리영역을 가진다). 이렇듯 전역 메모리를 공유하게 되므로 fork 방식에 비해서 좀더 작은 메모리를 소비하게 된다.

fork 에 비해서 thread 가 가지는 장점은 위에서 언급했듯이 "빠른 프로세스 생성" 능력과, 메모리 공유에 위한"적은 메모리의 사용"과 메모리 공유에 따른 쓰레드간의 좀더 쉬운 정보공유이다. fork(2) 시스템에서 부모와 자식같이 통신을 위해서는 IPC를 사용해야 하며 이는 꽤 어려운 작업이 될수도 있는데, 메모리를 공유함으로 IPC의 사용을 줄이면서도 쓰레드간 정보교환을 쉽게 할수있다.

fork 에 비해서 쓰레드가 더 빠른 수행능력을 보이는 이유는 fork 가 기본적으로 모든 메모리와 모든 기술자(파일기술자등)을 copy-on-write 방식으로 자식에게 복사하는데 비해서 쓰레드는 많은 부분을 공유하기 때문이다. copy-on-write 자체가 효율적이긴 하지만, 메모리 자원을 공유하는 것보다는 느릴 수 밖에 없다.

반면 단점도 가지고 있는데, 모든 쓰레드가 같은 메모리 공간을 공유하게 되므로, 하나의 쓰레드가 잘못된 메모리연산을 하게 되면, 모든 프로세스가 그 영향을 받게 된다는 것이다. fork 등을 통한 프로세스 생성방식에 있어서는 OS 가 가각의 프로세스를 보호해줌으로 한 프로세스의 문제는 해당 프로세스의 문제로 끝나게 된다. 그러나 쓰레드는 이러한 프로세스 보호를 기대할수 없다. 하나의 쓰레드에 문제가 생기면 전체 쓰레드에 문제가 생길가능성이 크다. 이런 이유로 멀티 쓰레드 프로그램은 좀더 주의를 기울여서 작성해야 한다. 또단 하나의 흐름을 가지는 단일 프로세스 프로그램과 달리, 여러개의 흐름으로 분리가 되기 때문에, 디버깅을 하기가 까다롭다는 문제도 가진다.

아래는 쓰레드간에 서로 공유하는 자원들을 나열한 것이다.

  • 작업디렉토리
    • 파일지시자들
    • 대부분의 전역변수와 데이타들
  • UID 와 GID
  • signal
다음은 각각의 쓰레드가 고유하게 가지는 자원들을 나열한 것이다.
  • 에러번호(errno)
  • 쓰레드 우선순위
  • 스택
  • 쓰레드 ID
  • 레지스터 및 스택지시자
다음은 멀티쓰레드 프로세스가 어떻게 각종 자원을 공유하는지를 나타낸것이다.

http://www.joinc.co.kr/albums/album01/abg.gif

파일은 기본적으로 공유하며, 메모리 영역중에 상당부분을 공유한다는걸 볼수 있을것이다.

POSIX thread

흔히 Pthread 라고 불리우며, POSIX 에서 표준으로 제안한 thread 함수모음으로 thread 를 지원하기위한 C 표준 라이브러리 셋을 제공한다. 이후 모든 예제는 Pthread 를 통해서 구현하고 설명하게 될것이다.

쓰레드의 생성과 종료

멀티 쓰레드 프로그램이 처음 시작되었을때 그것은 main()함수를 실행하는 단일 프로세스 상태로 작동하게 될것이다. 이것은 그 자체로 하나의 완전한 쓰레드이다. 이 상태에서 우리는 pthread_create(3) 함수를 부름으로써 새로운 쓰레드를 생성할수 있다.

쓰레드를 이용한 프로그램은 기본적으로 아래와 같은 순서로 작동하게 된다.

     Master Thread 
           | 
           |             pthread_create() 에 의해서 worker 생성 
| +---+----+---+ worker 시작 | | | | | | | | 각각의 worker는 그들의 작업을 수행한다. | | | | +---+----+---+ worker 를 종료한다. | | pthread_join()에 의해서 worker 를 join 한다. | Master Thread

worker 은 쓰레드로 바꾸어 생각할수도 있다.

아래는 쓰레드 프로그램의 가장 간단한 예이다.

#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 

void* do_loop(void *data)
{
    int i;

    int me = *((int *)data);
    for (i = 0; i < 10; i++)
    {
        printf("%d - Got %d\n", me, i);
        sleep(1);
    }
}

int main()
{
    int       thr_id;
    pthread_t p_thread[3];
    int status;
    int a = 1;
    int b = 2;      
    int c = 3;      

    thr_id = pthread_create(&p_thread[0], NULL, do_loop, (void *)&a);
    thr_id = pthread_create(&p_thread[1], NULL, do_loop, (void *)&b);
    thr_id = pthread_create(&p_thread[2], NULL, do_loop, (void *)&c);

    pthread_join(p_thread[0], (void **) &status);
    pthread_join(p_thread[1], (void **) &status);
    pthread_join(p_thread[2], (void **) &status);

    printf("programing is end\n");
    return 0;
}

위의 프로그램을 컴파일 시키기 위해선 pthread 라이브러리를 링크시켜줘야 한다.

[yundream@localhost test]# gcc -o thread thread.c -lpthread 
 
최초에 main() 쓰레드가 시작되고 나서 pthread_create 를 이용해서 3개의 쓰레드를 생성 시켯다. 각각의 쓰레드는 do_loop 코드를 실행한다. 쓰레드가 모든 작업을 마쳤다면, pthread_join 을 이용해서 다른 쓰레드가 종료될때까지 기다리고, 모든 쓰레드가 종료되었다면, main()쓰레드가 종료되고 프로세스는 완전히 끝나게 된다.

쓰레드의 생성은 pthread_create()를 호출함으로써 이루어진다. 첫번째 아규먼트는 pthread_t 데이타 구조체에 대한 포인터를 돌려주는데, 쓰레드에 대한 지시값이 들어 있다. 각각의 쓰레드는 각각의 유일한 pthread_t 를 가지고 있어야만 한다. 위의 프로그램에서 우리는 각각의 쓰레드가 유일한 p_thread 를 가지도록 하기 위해서 생성할 쓰레드의 수만큼(3)을 배열로 만들었다. 2번째 아규먼트는 쓰레드가 만들어질때의 타입이다.

(스케쥴링 우선순위 같은). 보통은 NULL 값을 사용한다. 쓰레드 타입에 대한 내용은 pthread_attr_init(3) 을 참조하기 바란다. 3번째 아규먼트가 바로 쓰레드가 실행할 코드이다. 4번째 아규먼트는 쓰레드에 넘겨주고 싶은 값을 명시해주면 된다. 여기에서는 각 쓰레드에 번호를 부여하기위한 int 값을 넘겼다.

각 쓰레드는 1부터 10까지 증가 시킨다음에 쓰레드를 종료하도록 되어 있다.

그동안 메인 쓰레드는 pthread_join 을 호출하여서 각각의 쓰레드가 종료할때까지 기다린다. 3개의 쓰레드가 모두 종료가 된다면 메인 쓰레드는 "programing is end" 메시지를 출력하고 프로그램을 완전히 종료하게 될것이다.

pthread_join 은 fork 의 wait(2) 와 비슷하다고 볼수 있다. fork 에서도 자식프로세스가 모두죽고 나서 부모프로세스가 죽어야 하듯이(예외를 만들수도 있지만), 쓰레드도 모든 생성된 쓰레드가 종료된 다음에 메인 쓰레드가 종료되어야 한다.

pthread_join 을 사용하게 되면 메인 쓰레드는 pthread_join 에 명시된 쓰레드가 종료할때까지 잠자면서(sleep)기다리게 된다. 이는 모든 쓰레드가 종료하기 전에 부모쓰레드가 종료하는 사태를 막기 위해서 사용된다. 하나의 쓰레드가 모든일을 종료하고, pthread_join 을 깨우게 되면, 쓰레드가 가지고 있던 자원들을 모두 되돌려주게 된다 (free). 만약 실행되고 있는 쓰레드를 즉시 중지하길 원한다면 pthread_cancel() 과 pthread_testcancel()을 사용하면 된다.

공용으로 사용되는 자원의 동기화

위에서 우리는 쓰레드를 사용할경우 상당히 많은 자원을 서로 공유하게 됨으로 얻는 여러가지 이점에 대해서 알아봤었다. 그러나 하나의 자원을 여러개의 쓰레드가 동시에 공유하게 됨으로 자원획득에 관한 문제가 발생할수 있다. 실지로 쓰레드를 사용하게 될경우 가장 주의해야 할점 중 하나가 바로 자원의 동시 접근에 대한 제어이다.

기본적으로 하나의 쓰레드가 하나의 자원에 접근하고 있을때, 다른 쓰레드는 그 자원에 대한 이전 쓰레드의 작업이 모두 끝나기전엔 접근하면 안될것이다.

이런한 공유되는 자원에 대한 접근제어는 IPC 설비의 세마포어와 매우 비슷한 점이 있다. 쓰레드에서는 이러한 공유되는 자원의 접근 제얼르 위해서 Mutexe 라는 것을 제공한다. Mutexe 는 다루어야할 내용이 꽤 많음으로 다음번 강좌에서 다루도록 하겠다.

2008/08/01 - [C/C++] - [스크랩] Mutex를 이용한 쓰레드 동기화 - 조인시 위키

'C/C++' 카테고리의 다른 글

this 포인터  (0) 2008.08.13
[스크랩] ioctl()  (0) 2008.08.11
[스크랩] Mutex를 이용한 쓰레드 동기화 - 조인시 위키  (0) 2008.08.01
[스크랩] volatile - c keyword  (0) 2007.05.15
gcc 옵션  (1) 2007.04.12
by sminchoi 2008. 8. 1. 14:07

티스토리를 좀 더 쉽게 사용해보려고 괜찮은 편집기를 알아보다가 BlogAPI를 알게 되었고
몇 가지 무료 편집기를 깔아서 사용해봤습니다.

Flock, Qumana, Windows Live Writer, Zoundry Raven, Word2007, springnote 이 정도를 사용해봤는데
굳이 전체적인 느낌을 얘기하자면,
“와우 괜찮네~ 생각보다 잘 되는데~  하지만 결국은 티스토리 들어가서 한번 더 손봐줘야 되는거잖아…” 입니다 

image

현재 이 글을 포스팅 하는 툴도 Windows Live Writer 입니다.
그렇네요.. 티스토리와의 호환성 때문에 모든 편집기에 100% 만족하지는 못했지만 결국 남은 녀석은 Windows Live Writer 입니다.
(스크랩 용으론 Zoundry Raven도 가끔 사용하게 될 것 같습니다. 테이블도 안 깨지고 스크랩 용으론 좋아 보여서요)
(실상은 Windows Live Writer에서는 글을 긁어다가 붙이면 가끔 테이블이 사라지는 증상이 있어서요)

뭐, 이제 사용하기 시작한 시점이지만 굳이 Windows Live Writer의 장단점을 얘기해보자면

(1) ms office 를 쓰는 것이라고 착각이 들 정도로 익숙한 작업 환경 (습관이란게 무섭지만,, 참 익숙하게 느껴집니다)
(2) 강력한 화면 캡쳐 기능 : 걍 Alt + PrtSc 한 후에 Ctrl + V 하면 끝. 화면 캡쳐할 일이 많은 저로선 이거 하나만으로도 최고!
(3) 간단하지만 유용한 이미지 편집 기능 : Crop 과 Tilt를 포함하여 그림자 테두리, 액자 테두리 가능
    (crop & tilt는 버전에 따라 지원하기도 안 하기도 합니다. 현재 한글 버전에서는 지원이 안 되네요)
(4) 홈페이지 미리보기 제공 : 작성하고 있는 글이 홈페이지 상에서 어떻게 보일지 미리보기 기능이 있습니다
(5) 기타, 지도 등을 넣을 수 있는 잡 기능등을 제공합니다
(6) 티스토리의 more/less 가 안됩니다. Split Post를 제공하지만 티스토리상에선 정상적으로 지원이 되질 않네요
(7) 엔터 대신 Shift + 엔터를 쳐야 원하는 줄바꿈이 됩니다.

image

그 외엔 차근차근 써봐야 알겠지만 일반적인 용도로 사용하기엔 큰 부담이 없고 깔끔하며 안정적인것 같습니다. ㅎㅎ
마음 같앙서 eeepc 901 하나만 있으면 오프라인으로 작성해서 저장해놓고 랜 될 때 한꺼번에 포스팅해보고 그러면 좋겠습니다

by sminchoi 2008. 8. 1. 11:29
ARM으로 배우는 임베디드 시스템안효복 지음 한빛미디어 2006.05.31책소개 임베디드 실무서. 이 책에서는 저자의 오랜 개발과 강의 노하우를 통해서 이론과 실습에서 핵심을 명확히 짚어주고 있다. 임베디드 시스템의 개념과 하드웨어 및 소프트웨어 구성 요소를... 최저가 23,800원가격비교

by sminchoi 2008. 7. 31. 14:22
임베디드 리눅스 입문
저자
CHRISTOPHER HALLINAN 지음 강덕진 옮김
출판
정보문화사 펴냄 | 2008.07.10 발간
소개
임베디드 개발자 관점에서 정리한 임베디드 리눅스 입문서! 이 책은 효율적이고 가치 있는 리눅스 기반 임베디드 제품을 만들기 위해 필요한 지식을 담고 있다. 임베디드 개발자가 겪게 되는 기술적인 문...  더보기
가격
23,000원 → 최저가 15,870원가격비교

by sminchoi 2008. 7. 31. 14:21
임베디드 시스템 아키텍처테미 노가드 지음 | 임희연 옮김 아이티씨 2007.08.30책소개 임베디드 시스템 공학 전문서. 이 책은 임베디드 시스템의 개념과 모델, 하드웨어와 소프트웨어 소개, 디자인 및 개발 등의 내용을 담았다. 각 장 끝부분에는 연습문제를 수록해 본문의... 최저가 25,600원가격비교


by sminchoi 2008. 7. 31. 14:20
아웃룩 2007 에서 가끔 애용하는 팁을 알려드리자면,

아웃룩 창에서 Ctrl + Alt + F11 을 누르면
"확장입력기" 라는 녀석이 튀어 나옵니다.
(필기 인식 이라고 되어 있는 놈인데...)

그렇다면 이 녀석을 어떤 용도로 사용하는냐? 하면
그렇습니다..  눈치빠른 분들은 벌써 눈치채셨겠지만...

한자 사전으로 사용하고 있습니다 -_-;;;

입력창에 마우스로 원하는 한자를 그려넣으면
오른쪽 창에 비슷한 글자들이 자동으로 뜹니다.

결국, 한자의 음을 모르는 경우에
옥편에서 획수로 찾는 것보다 훨씬 빠르게 찾기가 가능합니다 ㅋㅋㅋ

참고로, Ctrl + Alt + F10을 누르면
키보드 모양의 녀석이 나와서 입력기로 사용이 가능합니다만.,,
글쎄요... 이녀석은 활용도가 많이 떨어지네요 ㅎㅎ
by sminchoi 2008. 7. 29. 21:08

(단지 CPLD에서만의 문제는 아니지만)
일반적으로 신호의 level에 의해서 다른 signal을 구동하는 방법이 있지만
가끔은 edge로 동작해야 하는 경우가 있어서

이런 경우에는 보통 입력 신호의 system clk에 의해서 delay된 signal을 이용해서
입력 신호와 delayed 신호를 동시에 참조해서 해당되는 signal을 구동시켰었다.

그런데, system clk이 꽤 느린 경우이고,
구동해야할 signal은 많은 delay를 허용하지 않는 경우라면
여러가지로 고민하게 된다...

이런 경우에 입력 신호를 not gatering 해서
그 출력과 입력 신호를 잘 묶어서 생각해보면
not gate의 출력 신호는 입력에 비해 5~6ns 정도의 gate delay를 가지므로
결과적으로 5~6ns 정도의 1-pulse를 생성해낼수 있을텐데...

이 5ns 정도의 1-pulse를 async reset/set 등으로 사용한다면
system clk에 의한 방법보단 timing적으론 괜찮지 않을까 싶은데

그렇다곤 해도 5ns...라...
과연 system 안정성 면에선 어떨지 모르겠네...

한번 테스트해볼 필요는 있을 듯
분명 특별한 케이스에 필요한 날이 있을테니

'VHDL' 카테고리의 다른 글

Quartus에서 Power-on시의 Register 초기값 설정하기  (0) 2008.07.29
by sminchoi 2008. 7. 29. 12:42

일반적인 경우,
VHLD에서 Register의 값은 system reset 신호에 의해 async로 초기화를 해주게 된다.

그런데 어떤 특이한 케이스에서
Power-on 시에 (system reset으로 제어할수가 없어서) 초기값을 설정해야 할 필요가 있었다.

사용하는 M3000 시리즈의 EPM3128의 manual을 참조하면
모든 register는 Power-Up 시점에 clear 된다고 나와 있고
"Power-Up Level logic option" 을 사용해서 그 값을 선택할 수 있다고 되어 있다.
(Quartus에서만 가능하다고 되어 있음)

그런데 막상 아무리 저 값을 setting 해봐도 정상적으로 동작하는 것 같지는 않았다
아무래도 Quartus version과 해당 Device 등등과 관련되어 있는 듯

시간날 때 다시 한 번 확인해보고 정리할 필요는 있을 것 같음.


'VHDL' 카테고리의 다른 글

CPLD에서 특정 signal의 edge에서의 동작  (1) 2008.07.29
by sminchoi 2008. 7. 29. 11:54
| 1 2 3 4 5 6 |