find (절대경로) -name "*" -exec perl -pi -e 's/찾을 문자열/바꿀 문자열/g' {} \; 
% find ./ -name "*" -exec perl -pi -e 's/s6m/s6tmpl/g' {} \;
Can't do inplace edit: ./ is not a regular file. 

메세지는 안 좋게 뜨지만 다  변경되어 있음

'dev > Linux' 카테고리의 다른 글

알아두면 유용한 워드 단축키  (0) 2015.05.01
tar 명령어 모음  (0) 2014.08.01
linux 시스템 정보  (0) 2012.05.14
[Linux] sub directory 별로 압축할 때  (0) 2012.02.17
비슷한 기능의 Linux/DOS 명령어<펌글>  (0) 2012.01.10

알아두면 유용한 워드 단축키

  • AhnLab
  • 2015-04-21

복사하기(Ctrl + C), 저장하기(Alt + S), 오려두기(Ctrl + X), 실행취소(Ctrl + Z) 등 단축키 몇 개 정도 외워두는 것이 기본인 요즘. 윈도 단축키도 유용하지만 워드에서 문서 작업을 할 때 사용하는 단축키는 문서 편집을 보다 편리하게 할 수 있다. 여기에 몇 개의 단축키를 더 알아둔다면 그 매력에 푹 빠질지도 모른다. 문서 작성 시 요긴하게 사용할 수 있는 워드 단축키 몇 가지를 소개한다. 

 


새 문서 작업 할 때 : Ctrl + N
워드로 문서 작업 중 새로운 문서 작업을 하거나 새로운 창을 띄워야 할 때가 있다. 이 때 마우스를 사용하면 여러 번의 클릭이 필요하지만 단축키는 한 번이면 된다. Ctrl + N을 눌러주면 곧바로 새 문서가 열린다. N을 ‘New’라고 생각하면 금방 외울 수 있을 것이다.

 

문서를 불러 올 때 : Ctrl + O
이미 저장돼 있는 문서를 불러올 때 Ctrl + O를 누르면 마우스 클릭보다 훨씬 빠르다. 파일을 클릭하고 열기를 누르기까지의 과정이 단축키 하나면 한번으로 줄어든다. 

 

텍스트 정렬하기 
문서를 작업하기 전에 문서의 전체적인 틀을 맞추고 텍스트를 정렬하기도 한다. 문서 전체를 양쪽 맞춤 하려면 Ctrl + J, 제목을 가운데로 맞추려면 Ctrl + E, 텍스트를 왼쪽으로 맞추려면 Ctrl + L, 오른쪽으로 맞추려면 Ctrl + R을 사용하자.
 
글꼴 변경 : Ctrl + Shift + F, 글자 크기 조절 : Ctrl + Shift + P
문서 작업에서 글꼴 변경은 필수. 바꾸려는 글자 부분에 블록을 Shift와 우측의 방향키를 누르고 단축키 Ctrl + Shift + F를 누르면 빠르다. 단축키를 누르면 글자의 크기를 변경할 수 있는 글꼴 상자 창이 한 눈에 들어온다. 한 번에 글꼴, 크기까지 바꾸려면 왼쪽의 탭(Tab)으로 이동을 빠르게 할 수 있다(Ctrl + Shift + P를 눌러도 글꼴 상자 창이 나타난다). 여기에 글꼴 기울이기는 Ctrl + I, 굵기 조절은 Ctrl + B, 밑줄까지 넣고 싶다면 Ctrl + U를 누른다.

 

​​
 

 

글꼴 크기를 자유자재로 조정하기
: 늘일 때 Ctrl + Shift + >, 또는 Ctrl + ], 줄일 때 Ctrl + Shift + <, 또는 Ctrl + [
단축키를 쓰다 보면 글자의 크기나 글꼴을 조절할 때 은근 재미도 쏠쏠하다. 글자의 크기를 늘리려면 Ctrl + Shift + > 또는 Ctrl + ] , 줄이려면 반대로 Ctrl + Shift + < 또는 Ctrl + [를 사용하자. 사용자가 원하는 크기로 조절해주면 된다.

 

영문 대/소문자 바꾸기 : Shift + F3
영문으로 문서 편집 시 간혹 대소문자를 입력할 때 스트레스를 받는다. 그럴 땐 Shift + F3이 유용하다. 앞의 첫 글자만 대문자로 바꾸려면 Shift + F3 한번, 모두 바꾸려면 Shift + F3을 두 번, 소문자로 바꾸려면 Shift + F3을 한번 더 누르면 된다. 대문자를 입력할 때마다 귀찮게 Caps Lock을 켰다, 껐다 할 필요 없고, 대문자를 칠 때마다 왼손으로 힘주어 Shift를 누를 필요가 없어 편리하다. 아예 모두 대문자로 바꾸려면 Ctrl + Shift + A를 한번 누른다. 반대로 소문자에서 모두 대문자로 바꾸려면 Ctrl + Shift + A를 누르면 된다.
 
문서 분할하기 : Ctrl + Alt + S
업무에 따라, 문서 특성에 따라 자주 사용하는 사람이 있을 수도 있고 그렇지 않을 수도 있다. 문서를 분할해서 작성하려는 사람에게 유용한 단축키다. Ctrl + Alt + S를 누르면 마우스로 어딘가에 있을 메뉴를 찾아 헤매지 않아도 된다. 단축키 한 번이면 된다. 워드로 문서 작업을 하다가 메모가 필요할 때 메모장이나 따로 새 창을 열지 않아도 된다. 

 

하이퍼링크 삽입하기 : Ctrl + K
문서 작업 중 웹사이트의 주소를 넣을 일이 있다면 Ctrl + K를 쓰자. 마우스로 메뉴를 찾아야 하는 시간과 번거로움이 해결된다.  
 
선택하여 붙여넣기 :  Ctrl + Alt + V
Ctrl + V가 붙여넣기의 단축키라는 것을 모르는 사람은 별로 없을 것이다. 여기에 Alt를 추가로 누르면 사용자의 기호에 맞게 붙여넣기를 할 수 있다. Ctrl + Alt + V를 누르면 현재 작업 중인 문서의 형식에 얽매이지 않아 편리하다. 

 


 

 

문서를 닫을 때 :  Ctrl + W, 문서 종료 시 : Alt + F4
문서 작업을 완료했거나, 중요 문서 작업 중 자리를 비울 경우에는 일일이 마우스로 문서를 닫을 필요 없이 Ctrl + W를 눌러주자. 문서 창을 닫을 때는 반드시 Ctrl + S를 눌러 저장하자. 무심코 닫았다가는 공들여 작업한 문서를 다시 작업해야 하는 수고가 따른다.  워드 문서 작업을 마치고 종료할 때는 Alt + F4를 사용하자. 마우스로 손을 왔다 갔다 하기 전에 이 키만 누르면 퇴근할 때는 더 유용할 것이다.
 
단축키 중에는 한글과컴퓨터의 한글  Microsoft 워드(메모장), Microsoft 파워포인트에서 공통으로 사용할 수 있는 것도 있다. 잘라내기(Ctrl + X), 복사하기(Ctrl + V), 저장하기(한글과컴퓨터의 한글은 Alt + S, Ctrl + S) 모두 사용)), 실행취소(Ctrl + Z), 문서 종료(Alt + F4)는 유용하게 사용할 수 있다. @

  • AhnLab 로고

이 정보에 대한 저작권은 AhnLab에 있으며 무단 사용 및 도용을 금합니다.

단, 개인이 비상업적인 목적으로 일부 내용을 사용하는 것은 허용하고 있으나, 이 경우 반드시 출처가 AhnLab임을 밝혀야 합니다.
기업이 이 정보를 사용할 때에는 반드시 AhnLab 의 허가를 받아야 하며, 허가 없이 정보를 이용할 경우 저작권 침해로 간주되어 법적인 제재를 받을 수 있습니다. 자세한 내용은 컨텐츠 이용약관을 참고하시기 바랍니다.

정보 이용 문의 : contents@ahnlab.com

'dev > Linux' 카테고리의 다른 글

파일 내 문자 치환  (0) 2016.07.05
tar 명령어 모음  (0) 2014.08.01
linux 시스템 정보  (0) 2012.05.14
[Linux] sub directory 별로 압축할 때  (0) 2012.02.17
비슷한 기능의 Linux/DOS 명령어<펌글>  (0) 2012.01.10

목차

  1. tar 소개
  2. 미리 알아두면 좋을 것들
    1. 옵션주는 방법
    2.  -f와 -v옵션이 많이 쓰이는가?
    3. 가장 많이 사용되는 작업
  3. 기본 명령어 활용예
    1. 아카이브 풀기
    2. 아카이브 만들기
    3. 아카이브 내용보기
    4. 퍼미션을 유지하며 아카이브 만들기
    5. tar+gzip 압축하기
    6. tar+bzip2 압축하기
    7. gzip으로 압축된 tar 풀기
    8. bzip2로 압축된 tar 풀기
    9. 허가권(Permission) 유지하며 풀기
  4. 백업에 활용하기
    1. 아카이브에 새 파일 추가하기
    2. 아카이브에 파일 업데이트하기
    3. 아카이브에 파일 삭제하기
    4. 아카이브에서 특정 디렉토리 또는 파일만 풀기
    5. 옛버전 파일 풀기
    6. 아카이브에서 파일 비교하기
  5. 기타

모든 하위 디렉토리에 특정 소스만 묶고 싶을 때는?

TAR 명령어의 모든것

1 tar 소개

주요기능은?

아카이브를 만들거나 푼다.

아카이브란?

아카이브는 여러 파일을 한 파일로 묶은 것을 말한다. tar는 아카이브를 압축하지 않는다. 단지 하나의 파일로 묶을 뿐이다. 아카이브의 압축은 gzip이나 bzip2등을 이용한다.

아카이브를 만드는 목적

파일의 백업이나 배포에 편리하게 이용된다.

확장자

아카이브의 확장자는 .tar 이다. 일반적으로 tar로 묶인 아카이브를 gzip으로 압축하여 확장자가 .tar.gz 압축 아카이브를 많이 이용한다.

유래

원래, tar 아카이브는 마그네틱 테이프에 파일을 저장하기 위해 만들어졌다. 그래서 tar는 tape archiver에서 유래한다.

2 미리 알아두면 좋을 것들

2.1 옵션주는 방법

긴 형식 옵션

tar --create --verbose --file=afiles.tar apple angst aspic

짭은 형식 옵션

tar -c -v -f afiles.tar apple angst aspic

또는 붙여서

tar -cvf afiles.tar apple angst aspic

tar 는 반드시 옵션이 필요 해서 옵션에 - 를 붙이지 않아도 된다.

tar cvf afiles.tar apple angst aspic

2.2 왜 -f와 -v옵션이 많이 쓰이는가?

-f --file=

-f 는 아카이브 파일의 이름을 지정해 주는 옵션이다. -f 가 없으면 아카이브의 이름이 없는 샘이다. 따라서, -f 로 아카이브의 이름을 꼭 명시해야 한다. tar는 아카이브 이름이 없으면 디폴트 이름을 취한다. 원래 tar의 목적대로 (디폴트로 엑션) 테입드라이브로 아카이브를 저장하려 들지도 모른다. 요즘은, 컴퓨터에 마그네틱 테입 드라이브가 없으므로 에러가 발생할 것이다.

-v --verbose

-v 옵션이 있으면 아카이브에 추가되거나 풀리고 있는 파일의 이름을 화면에 보여준다. 진행사항을 알 수 있기 때문에 사용하는게 좋다.

"ls -l" 과 같은 형식으로 파일을 보려면 v를 두번 써준다.

tar -cvvf afiles.tar 파일들(디렉토리들)

2.3 가장 많이 사용되는 작업

--create -c 새로운 아카이브를 생성한다.

--list -t 아카이브의 내용(묶인 파일이름)을 보여준다.

--extract -x 아카이브에 묶인 파일이나 디렉토리를 풀어준다.

·  아카이브의 파일 리스트 보기

3 명령어 활용예

3.1 아카이브 풀기

 tar -xvf afiles.tar

afiles.tar 라는 아카이브 파일에 묶인 파일과 디렉토리를 현재 디렉토리에 풀어준다.

3.2 아카이브 만들기

 tar -cvf afiles.tar 묶을파일과디렉토리들

afiles.tar 라는 이름으로 파일과 디렉토리를 묶어준다.

3.3 아카이브 내용보기

 tar -tvf afiles.tar 묶을파일과디렉토리들

afiles.tar 라는 이름으로 묶인 파일과 디렉토리를 보여 준다.

3.4 퍼미션을 유지하며 아카이브 만들기

 tar -cvfp archive.tar 묶을파일과디렉토리들

afiles.tar 라는 이름으로 퍼미션을 유지하며 파일과 디렉토리를 묶어준다.

3.5 tar+gzip 압축하기

tar -czvf afiles.tar.gz 묶을파일과디렉토리들

afiles.tar.gz 라는 이름으로 파일과 디렉토리를 묶어준다.

tar -czvfp afiles.tar.gz 묶을파일과디렉토리들

afiles.tar.gz 라는 이름으로 퍼미션을 유지하며 파일과 디렉토리를 묶어준다.

3.6 tar+bzip2 압축하기

tar -cjvf afiles.tar.bz 묶을파일과디렉토리들

afiles.tar.bz 라는 이름으로 파일과 디렉토리를 묶어준다.

tar -cvjfp afiles.tar.gz 묶을파일과디렉토리들

afiles.tar.gz 라는 이름으로 퍼미션을 유지하며 파일과 디렉토리를 묶어준다.

3.7 gzip으로 압축된 tar 풀기

 tar -xvzf afiles.tar.gz

afiles.tar.gz 라는 tar 로 묶인뒤 gzip 으로 압축된 파일을 먼저 압축을 푼뒤에 묶인 파일까지 풀어준다.

3.8 bzip2로 압축된 tar 풀기

 tar -xvjf afiles.tar.bz

afiles.tar.bz 라는 tar 로 묶인뒤 bzip2로 압축된 파일을 먼저 압축을 푼뒤에 묶인 파일까지 풀어준다.

3.9 허가권(Permission) 유지하며 풀기

 tar -xpf afiles.tar

파일을 묶을 당시의 각 파일의 허가권을 유지하며 풀어준다.

4 백업에 활용하기

4.1 아카이브에 새 파일 추가하기

 tar --append --file=collection.tar rock

또는

 tar -rvf collection.tar rock

collection.tar 라는 기존 아카이브 파일에 rock라는 파일을 추가한다. 옵션은 --append (-r) 이다.

똑같은 이름의 파일이 아카이브에 추가되면 기존의 오래된 파일은 지워지지 않고 아카이브에 남아 있는다.

따라서 같은 이름의 파일을 여러번 추가하면 (append) 추가된 시간별로 여러 버전의 파일이 존재한다. 그러나, 아카이브를 풀때는 가장 최신 파일이 풀린다.

4.2 아카이브에 파일 업데이트하기

 tar -uvf collection.tar blues folk rock classical

collection.tar 라는 기존 아카이브에 blues folk rock classical등 4 개의 파일을 업데이트 한다. 업데이트는 날자와 시간을 기준으로 실행한다. 아카이브에 있는 파일과 업데이트할 파일이 수정된 날자가 같으면 아카이브에 추가하지 않는다.

만약 아카이브에 있는 파일보다 최근에 수정이 되었으면 아카아브에 추가한다. 기존의 오래된 파일은 지워지지 않고 남아 있는다.

따라서, 업데이트를 여러번 하면, 같은 이름의 파일이 수정된 시간별로 여러가지 버전이 존재할 수 있다. 그러나, 아카이브를 풀때는 가장 최신 파일이 풀린다.

아카이브를 풀때 옵션은 --update(-r)이다.

4.3 아카이브에 파일 삭제하기

 tar --delete --file=collection.tar blues

collection.tar 라는 기존 아카이브에서 blues라는 파일을 삭제한다. 주의할 것은 모든 blues파일을 삭제한다는 것이다. 모든 디렉토리내의 blues파일과 여러 버전의 blues가 모두 삭제된다. 다른 옵션과 달리 삭제 옵션인 --delete는 짧은 형식의 옵션이 없다.

3.4 아카이브에서 특정 디렉토리 또는 파일만 풀기

명시된 파일 풀기: collection.tar 라는 아카이브에서 blues라는 파일만 현재 디렉토리에 푼다.

tar --extract --file=collection.tar blues

디렉토리까지 명시: music.tar 에서 practice/folk와 practice/jazz파일만 푼다.

tar -xvf music.tar practice/folk practice/jazz

 

*** 실제 활용 예 ***

tar xzvfp /backup/20050107/20050107.tar.gz /home/ home/yc1500

tar [옵션] [아카이브파일명] [압축을풀어놓을 대상디렉터리] [압축파일내의 특정파일(폴더)]

p 옵션: 허가권 유지 옵션

 

4.5 옛버전 파일 풀기

 tar --extract --file archive.tar --occurrence=2 myfile 

archive.tar 라는 아카이브에서 2번째 버전의 myfile을 푼다.

 tar --extract --file archive.tar --occurrence 

archive.tar 라는 아카이브에서 첫번째 버전의 모든 파일을 푼다.

4.6 아카이브 파일과 실제 파일 비교하기

 tar -d -f archive.tar *.c

archive.tar라는 아카이브에 모든 c파일들과 현재 디렉토리의 c파일을 비교한다. 수정 날자와 내용을 비교하고 내용이나 날자가 다르면 화면에 보여준다.

5 기타

5.1 모든 하위 디렉토리의 특정 소스만 묶고 싶을 때는?

쉘 컴멘드와 조합하여 특정 소스를 찾아서 아카이브에 추가 할 수 있다.

먼저 아카이브를 하나 만든다.

 tar -cvf test.tar prog1.c

for 문과 find 명령을 이용해서 하위 디렉토리의 묶고 싶은 파일을 찾고, tar의 -r 옵션으로 test.tar에 하나씩 추가한다.

 for i in $(find . -name '*.c'); do tar -rvf test.tar $i; done

find 의 다양한 검색능력을 100%활용할 수 있다. 

* 출처 : http://rjh1147.tistory.com/6

'dev > Linux' 카테고리의 다른 글

파일 내 문자 치환  (0) 2016.07.05
알아두면 유용한 워드 단축키  (0) 2015.05.01
linux 시스템 정보  (0) 2012.05.14
[Linux] sub directory 별로 압축할 때  (0) 2012.02.17
비슷한 기능의 Linux/DOS 명령어<펌글>  (0) 2012.01.10

1. callback 

  • 라이브러리 에서 우리가 만든 함수를 호출하는 경우...
  • 이렇게 역방향으로 호출되는 함수를 Callback 함수라고 한다.
  • 예를 들어 라이브러리에 생일축하 노래불러주는 함수가 있다고 해보자.
  • 사랑하는 땡땡땡~ 이부분은 우리의 목소리를 넣고 싶다.
  • 그러면, 땡땡땡에 무엇을 넣어야할지를 라이브러리에 알려주기 위해,
  • 만드는 함수가 Callback 함수이다.
  • 우리는 callback 함수를 만들고 , 이 힘수의 포인터를 라이브러리에 알려주면,
  • 라이브러리는 땡땡땡이 나오는 순간, Callback 함수를 호출하여 생일축하 노래를 완성한다.,
  • 그 예로 표준함수중, 데이터를 정렬하는 기능을 수행하는 qsort()가 있다.
  • 퀵소트 함수인데.
  • 데이터타입은 개발자가 정할 수 있다.
  • 그래서 데이터를 비교하는 기능은 개발자가 Callback 함수로 만들어 라이브러리에 제공하도록 하였다.
  • 정렬시 어떤 데이터가 앞으로, 어떤 데이터가 뒤로 갈지를 라이브러리에서 결정하는 것이 아니라, 개발자가 정한다.
  • 이렇게 하면 기본 데이터 타입 뿐 아니라 , 개발자가 정의 한 구조체에 대해서도 정렬을 할 수 있고, 오름 차순인지, 내림차순정렬인지 등을 개발자 마음대로 변경할 수 있어 유연성이 엄청나게 증가한다.


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

#define  NUM 10

int ascending(const void*a , const void*b)
{
    if (*(int*) a > *(int*) b)
        return 1;      
    else if (*(int*) a < *(int*) b)
        return -1;           
    else           
        return 0;                 
}

int descending(const void*a , const void*b)
{
    if (*(int*) a < *(int*) b)
        return 1;       
    else if (*(int*) a > *(int*) b)
        return -1;           
    else           
        return 0;                 
}

void output(int *data, int size)
{
    for (int i=0; i<size; i++) 
        printf("%d ", data[i]);
    puts(""); 
}

void main()
{
    int data[NUM]= { 10,20,30,40,9023,1231,2345,343,123,532 };
    qsort(data, NUM, sizeof(int) , ascending);
    output(data, NUM);
    qsort(data, NUM, sizeof(int) , descending);
    output(data, NUM);       
}


#include <stdio.h>
void test_func(void (*func)(int aa,int bb), int a, int b)
{
    printf("I am Test Function\n");

    //callback function call
    func(a, b);
}

void call_back_func_1(int a, int b)
{
    printf("I am CallBack Function1 -- a=%d,b=%d\n", a,b);
}

void call_back_func_2(int a,int b)
{
    printf("I am CallBack Function2 -- a=%d,b=%d\n", a,b);
}

int main(int argc, char **argv)
{
        int answer1;
        int answer2;

        if (argc != 3) {
                printf("err argc = %d\n",argc);
                return -1;
        }
    answer1 = atoi(*(argv + 1));
    answer2 = atoi(*(argv + 2));
        switch (answer1)
        {
        case 1:
                 test_func(call_back_func_1, answer1,answer2);
                 break;
        case 2:
                 test_func(call_back_func_2, answer1,answer2);
                 break;
        }
        return 0;
}


'dev > C' 카테고리의 다른 글

가변 인자 함수(va_list, va_start, va_arg, va_end)  (0) 2013.02.19
시간 측정을 위한 gettimeofday 사용예제  (0) 2012.12.19
[C언어] assert()  (0) 2010.11.09
문자열 처리 함수  (0) 2010.11.05

IMSI (International Mobile Station Identity) 국제 이동국 식별 번호

 GSM 서비스 가입 시에 이동 단말기에 할당되는 고유 15자리 식별 번호. 이 번호는 이동 국가 코드, 이동 네트워크 코드, 이동 가입자 식별 번호 및 국가 이동 가입자 식별 번호로 구성된다. IMSI는 다음과 같은 구조를 지닌다.



MCC (Mobile Conuntry Code) 

MNC (Mobile Network Code) 

MSIN (Mobile Subscriber Identifier Number)


  MCC+MNC는 이동전화 가입자의 Home Network를 전세계 어떠한 망에서든지 유일하게 식별한다. 다시말해, IMSI는 Visited Network(로밍 서비스를 제공하는 타 Network)가 최대 처음 6자리를 분석해서 Home Network를 조회할 수 있는 구조로 되어 있다.  MSIN은 MCC와 MNC가 주어진 경우, 이동전화 단말기를 유일하게 식별한다. 


TMSI (Temporary Mobile Subscriber Identity), 임시 이동 가입자 식별 번호 

이동 통신 시스템에서 이동국을 식별하는 임시 식별 번호. 임시 식별 번호는 홈 위치 레지스터(HLR)의 인증 센터(AC/Auc)에 의해 부여되며, 이동국과 이동 전화 교환국(MSC) 사이에서 보안상 국제 이동국 식별 번호(IMSI: International Mobile Station Identity) 대신 사용된다. 이는 Air 인터페이스 상에 IMSI 노출을 최소화하기 위하여 최초 위치 등록시 IMSI 대신에 TMSI를 가입자별로 핟당한다. 

가입자 식별을 보호하기 위해 인증과 암호화를 거쳐 이동국에 전송되며, 이동국 통신권 내에서 유효하고 통신권 외에서는 추가적으로 위치 영역 식별(LAI: Location Area Identification)이 필요하다. 


MIN (Mobile Identification Number), 이동국 식별 번호 

이동국(이동 전화 단말기)에 할당된 10자리 전화번호를 디지털로 표시하는 34비트의 숫자. 단말기의 지정 번호(일명 전화번호)로서 MIN 1과 MIN 2가 있다. MIN 1은 단말기에 할당된 7개 디짓의 전화번호로 24개 비트로 구성되며, MIN 2는 3개 디짓의 지역 번호로 10개의 비트로 구성된다. 011-YYY-XXXX에서 MIN 1은 YYY-XXXX이고 MIN 2는 011이다. 

[참고] MIN은 원래 북미의 이동전화 단말기를 식별하기 위한 것이었다. 10자리의 MIN은 국제 로밍을 제공하기 위해 필요한 추가정보를 포함할 수 없다는 점 때문에 IMSI 체계가 필요하게 되었다. IMSI 는 GSM 표준에서 사용된다. 


(ITU-T) MSISDN (Mobile Station International ISDN Number), 이동국 국제 ISDN 번호 

WCDMA IMT-2000에서는 가입자에게 두 가지 번호를 부여한다. USIM 카드에 IMSI와 단말기에 MSISDN이라는 것이 부여되는데, 이번에 정부에서 010X로 부여한 것이 바로 MSISDN이고 이 MSISDN에는 실제로는 국가코드(우리나라 = 82)가 들어가 있는 상태이다. 따라서 가입자는 상대방이 어디에 있는지 전혀 예상하지 않고서도 별도의 다이얼링 없이 전화를 걸어 상대방이 다른 국가에 있다는 것을 알 수 있다. 

하나의 IMSI에 4개의 MSISDN을 가질 수 있다. GSM 네트웍에서의 전화번호란 MSISDN(Mobile Station Integrated System Digital Network)을 뜻하며 국가코드(Country Code), 네트웍코드(NetworkCode) 그리고 디렉토리번호(Directory Number)로 구성되어 있다. 

반면에 IS-41C 네트웍에서의 전화번호란 휴대폰의 MIN(Mobile Identification Number)를 뜻하며 지역번호(Area Code)와 전화번호(Phone Number)로 구성되어 있고 (NPA) Nxx-xxxx 형태를 갖고 있다. MDN (Mobile Directory Number)와 동일한 것으로, 가입자 전화번호를 의미한다. 


IMEI (International Mobile Equipment Identity), 국제 이동 단말기 식별 번호 

GSM 표준에서 제조업체에 의해서 단말의 하드웨어 제작시 할당되는 최대 15자리 하드웨어 번호를 말하며, 이 번호는 형식 승인 코드, 최종 조합 코드 및 일련 번호를 포함하여 15자리로 구성된다. 이를 통해 GSM 이동 단말기가 서로를 고유하게 식별할 수 있다. 

-- while list : 정상적인 사용이 가능한 단말들의 분류 

-- black list : 호를 금지시켜야 하는 단말들의 분류 

-- gray list : 호를 금지하지는 않지만, 추적이 필요한 단말들의 분류 


PIN (Personal Identification Number), 개인 식별 번호 

특정 기능이나 정보의 접근을 위해 모든 GSM 기반 전화기에서 사용되는 코드로, PIN은 가입과 동시에 제공한다.

'dev > 통신' 카테고리의 다른 글

SIP 응답 코드  (0) 2013.04.03
IMSI(International Mobile Subscriber Identity)  (0) 2012.09.06

1xx = 정보용 응답

100 시도 중

180 전화 벨 울림

181 통화 전달 중

182 대기 중

183 세션 진행


2xx = 성공 응답

200 확인

202 수락: 참조용으로 사용


3xx = 경로 변경 응답

300 복수 선택

301 영구 이동

302 임시 이동

305 프록시 사용

380 대체 서비스


4xx = 요청 실패

400 잘못된 요청

401 권한 없음: 등록기관만 사용 가능. 프록시는 프록시 인증 407을 사용해야 합니다.

402 요금 청구됨(향후 사용을 위해 예약)

403 금지

404 찾을 수 없음: 사용자를 찾을 수 없음

405 메소드가 허용되지 않음

406 수락할 수 없음

407 프록시 인증 필요

408 요청 시간 종료: 시간 내에 사용자를 찾을 수 없음

410 없음: 사용자가 일시 존재하였으나 더 이상 사용할 수 없음.

413 요청 엔티티가 너무 큼

414 요구-URI가 너무 김

415 지원되지 않은 매체 유형

416 지원되지 않는 URI 체계

420 잘못된 확장자: 잘못된 SIP 프로토콜 확장자가 사용됨, 서버가 인식하지 못함

421 확장자 필요

423 간격이 너무 짧음

480 일시적인 사용 불능

481 통화/트랜젝션이 존재하지 않음

482 루프가 검출됨

483 홉이 너무 많음

484 불완전한 주소

485 모호함

486 사용 중

487 요청이 종료됨

488 여기서 수락할 수 없음

491 요청 보류 중

493 복호화할 수 없음: S/MIME본문 부분의 암호를 풀 수 없음


5xx = 서버 오류

500 서버 내부 오류

501 구현되지 않음: SIP 요청 메소드가 구현되지 않음

502 잘못된 게이트웨이

503 서비스를 사용할 수 없음

504 서버 시간 종료

505 지원되지 않은 버전: 서버가 이 버전의 SIP 프로토콜을 지원하지 않음

513 메시지가 너무 큼


6xx = 전체 실패

600 모두 사용 중

603 거부

604 어디에도 존재하지 않음

606 수락할 수 없음

가변 인자 함수 : 함수의 전달값(파라미터)(인수) 의 개수가 변경될수있는 함수.

ex) printf, scanf


예제

#include <stdio.h>
#include <stdarg.h>

void va_fct(int nFix, ...); //가변 인자 함수 선언

int main(void)
{
    va_fct(3, 1, 2, 3);
    return 0;
}

void va_fct (int nFix, ...);
{
    int i;
    va_list    list; //list 포인터

    va_start (list, nFix); //list 포인터 초기화

    for (i=0 ; i<nFix ; i++) {
        printf ("%d ", va_arg(list, int));
    }
    printf("\n");

    va_end(list); //list reset
}

 1 2 3


  •  va_list : 전달된 인수들은 스택에 저장되고 함수는 스택에서 인수를 꺼내쓴다.  va_list 타입은 char*형으로 정의되어 있고 가변인수를 읽기 위한 포인터 변수다.
  • va_start(list, 마지막고정인수) :  list 포인터 변수가 첫번째 가변인수를 가리키도록 초기화한다. 마지막 고정인수의 번지에 길이를 더해서 가변인수가 시작되는 번지를 계산한다.
  • va_arg(list, 인수타입) : 가변인수를 실제로 읽는 명령어, list 위치에서 인수타입에 맞는 값을 읽고 리턴하여 list를  다음 가변인수의 위치로 옮겨준다. va_arg는 매크로 함수이기 때문에 타입명이 내부적으로 sizeof 연산자와 캐스트연산자로 전달되어 인수로 받을 수 있다.
  • va_end(list) 가변인수를 다 읽은후 reset.


가변 인자 함수의 조건

  • 반드시 하나이상의 고정인수를 가져야한다. 가변인수를 읽기위해 포인터 list를 초기화하기위해 마지막 고정 인수의 번지를 알아야하기때문이다. 고정인수가 없으면 vs_start매크로가 동작하지않는다.
  • 함수 내부에서 자신에게 전달된 가변인수의 개수를 알수있어야한다. 인수의 개수에는 제한이없고 컴파일러가 인수의 개수를 점검하지않으므로 함수가 인수의 개수를 파악할수있게 정보를 제공해야한다.
  • 함수 내부에서 각각의 가변인수타입을 알 수 있어야한다. va_arg매크로가 list번지에서 가변 인수를 읽을때 얼만큼 어떤 타입으로 해석할지를 알아야하기때문이다. 하나의 고정인수를 통해서 모든 가변인수의 타입을 알수있게하는 방식이 가장 좋다.


'dev > C' 카테고리의 다른 글

callback  (0) 2013.05.29
시간 측정을 위한 gettimeofday 사용예제  (0) 2012.12.19
[C언어] assert()  (0) 2010.11.09
문자열 처리 함수  (0) 2010.11.05

MySql을 실제로 사용 중 mysql_num_rows() 을 통해 값을 가져와서

그 크기 만큼 vector size나 메모리 alloc을 해야 하는 경우가 있었다.

그런데 실제 쿼리로는 되는데  mysql_num_rows() 는 0으로 나오는 현상이 간혹 생겨서 검색해보니

아래와 같은 내용이 있었다.

 

1. mysql_num_rows는 용도가 insert문 이나 update문 delete문을 사용한 후 적용된 rows갯수를 구하는 것입니다. select문에서 사용하신것이 아닌가 생각이 됩니다.

 

2. mysql은 실제 적용된 로우의 개수를 리턴한다고 합니다. 그래서, 해당 로우가 있는데도 0으로 나오는 경우가 발생하기도 하구요. mysql 접속할때 CLIENT_FOUND_ROWS 옵션 주고 해보시면 원하는 결과가 나올것 같습니다

 

관련 링크 : 

http://database.sarang.net/?inc=read&aid=25543&criteria=mysql&subcrit=&id=&limit=20&keyword=procedure&page=3

 

select 문에서 두루 사용되고 mysql_store_result()문 후에 사용했었던 터라

-mysql_num_rows()은 mysql_store_result()후에 사용하는 것으로 나와있다.- 

2.번이 해결책이 될 듯 싶었으나.........

 

같은 현상이 일어나는 듯....

 

select 가 문제가 아니라, 기전 insert에서 auto commit 옵션을 off 후, insert & commit 진행, auto commit on 변경 후

아직까진 문제가 없다.

 

auto commit인 경우 아무래도 insert data가 좀 많아서 실제 쿼리 돌려보면 되는데, api로  select 하게 되면 api 단에서 문제가 있는 것이 아닐까 하는 생각을 해본다.

 

 

 

#include <sys/time.h>
#include <unistd.h>
struct timeval
{
    long tv_sec;       // 초
    long tv_usec;      // 마이크로초
}
int gettimeofday(struct timeval *tv, struct timezone *tz);


long gettimeofday_d(void)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec*1e6) + tv.tv_usec;
}


long getTimeGap(struct timeval *s_t, struct timeval *e_t)
{
    struct timeval rt;
    long et = 0L;

    rt.tv_sec = e_t->tv_sec - s_t->tv_sec;
    rt.tv_usec = e_t->tv_usec - s_t->tv_usec;

    if(rt.tv_usec < 0)
    {
        rt.tv_sec--;
        rt.tv_usec += 1000000L;
    }
    et = (rt.tv_sec*1000000L) + rt.tv_usec;
    return et;
}


'dev > C' 카테고리의 다른 글

callback  (0) 2013.05.29
가변 인자 함수(va_list, va_start, va_arg, va_end)  (0) 2013.02.19
[C언어] assert()  (0) 2010.11.09
문자열 처리 함수  (0) 2010.11.05

IMSI는 가입자 식별번호 즉, 전화번호를 의미한다.
IMSI는 WCDMA, LTE 망에서 사용을 하며, 총 15자의 digit으로 구성되어 있다.

구조는 "MCC + MNC + 전화번호"이다.
MCC(Mobile Country Code, http://en.wikipedia.org/wiki/Mobile_country_code)
MNC(Mobile Network Code, http://en.wikipedia.org/wiki/Mobile_Network_Code)

대한민국의 MCC는 '450'이며 SKT의 MNC는 '05', KT의 MNC는 '04', '08'이고 LGU+는 '06'이다.

즉, 전화번호가 010-1234-1234인 경우에 각 이통사의 IMSI는 다음과 같다.

 SKT IMSI

 450051012341234
 KT IMSI  450041012341234 | 450081012341234

 LGU+ IMSI

 450061012341234



아래는 IMSI가 실제 UICC에 저장될때의 형식이다.


1st byte는 Length of IMSI로써 0x08로 고정값을 가진다.
2nd ~ 9th byte에 IMSI값이 저장이 되는데 그냥 저장되는 것은 아니고 다음과 같은 변환 규칙을 따라 저장이 된다.
변환전 IMSI: 450091012341234
변환후 IMSI: 4905900121432143
즉, '4' 다음에 '9'가 고정으로 들어가고 이후는 nibble 단위로 자리를 switching한다.

최종적으로 EF IMSI에 저장되는 IMSI의 physical value는 084905900121432143가 된다.


PS. IMSI와 동일한 개념으로 CSIM에서는 IMSI_M이라는 것이 존재한다.


펌글

'dev > 통신' 카테고리의 다른 글

이동통신 각종 식별번호 개념잡기(IMSI, MSISDN, MIN 등)  (0) 2013.04.11
SIP 응답 코드  (0) 2013.04.03

Linux 시스템에 대한 정보

/proc 디렉토리 아래 파일을 출력해 봄으로써 간단한 정보를 알수있습니다.

* 몇가지 소개를 합니다. /proc/cpuinfo : cpu 정보 

/proc/pci : pci 정보 

/proc/interrupts : 사용중인 irq 정보 

/proc/dma : 사용중인 dma 채널

/proc/ioports : 사용중인 i/o 포트 정보 

/proc/filesystems : 현재 사용가능한 화일 시스템 

/proc/meminfo : 현재 사용중인 메로리 

/proc/partitions : 현재 사용중인 파티션 

/proc/swaps : 현재 사용중인 스왑 파티션 정보 

/proc/version : 현재 사용중인 커널 버전 

/proc/devices : 현재 사용중인 드라이버

/proc/cmdline : 현재 사용중인 부트 이미지

'dev > Linux' 카테고리의 다른 글

파일 내 문자 치환  (0) 2016.07.05
알아두면 유용한 워드 단축키  (0) 2015.05.01
tar 명령어 모음  (0) 2014.08.01
[Linux] sub directory 별로 압축할 때  (0) 2012.02.17
비슷한 기능의 Linux/DOS 명령어<펌글>  (0) 2012.01.10
#include <stdio.h>
tar cvf test.tar ./test   묶기
tar xvf test.tar            풀기
tar cvfz test.tar ./test    zip압축
tar xvfz test.tar             zip압축 풀기
tar tvf test.tar               목록보기
tar xvf test.tar | grep aaa      test.tar내의 aaa만 풀기

--exclude 특정 디렉토리, 파일 제외


'dev > etc' 카테고리의 다른 글

우분투 타이틀바 옮기기  (0) 2012.02.03
정규표현식의 기본 문법  (0) 2010.11.09
안철수 님의 말(펌)  (0) 2010.11.09
glib  (0) 2010.11.09
[VirtualBox] Linux에서 게스트 확장 설치  (0) 2010.11.09
Linux 에서 특정 위치의 directory 내에서 sub directory 가 많고 각 sub directory 별로 압축 할 때

exe)

 find `ls` -type d -maxdepth 1 -exec tar -cvjf "{}.tar.bz2" "{}" \;


'dev > Linux' 카테고리의 다른 글

파일 내 문자 치환  (0) 2016.07.05
알아두면 유용한 워드 단축키  (0) 2015.05.01
tar 명령어 모음  (0) 2014.08.01
linux 시스템 정보  (0) 2012.05.14
비슷한 기능의 Linux/DOS 명령어<펌글>  (0) 2012.01.10

'dev > etc' 카테고리의 다른 글

TAR  (0) 2012.03.01
정규표현식의 기본 문법  (0) 2010.11.09
안철수 님의 말(펌)  (0) 2010.11.09
glib  (0) 2010.11.09
[VirtualBox] Linux에서 게스트 확장 설치  (0) 2010.11.09

예전에 wiki에 있던 글


OpenMP 소개: 공유 메모리 멀티 프로세서를 위한 포터블한 병렬 프로그램 API

  • 썬 스튜디오 컴파일러 (C/C++/포트란 95) 는 OpenMP 병렬화를 네이티브하게 지원합니다. OpenMP는 공유 메모리 모델에서 병렬 프로그램의 새로운 표준 모델로 발전하고 있습니다. 이 것은 컴파일러 지시자, 런타임 루틴, 그리고 프로그래머들이 코드를 쉽게 병렬화 하기 위한 환경 변수들을 제공하고 있습니다. 이 글에서는 OpenMP 에 대한 간략한 소개와 썬 스튜디오 컴파일러에서의 OpenMP 지원에 대해 설명합니다. 이 글은 OpenMP 와 포트란, C 혹은 C++ 에서 병렬프로그래밍을 처음 접하는 개발자들을 위해 쓰여 졌습니다.

OpenMP란 무엇인가?

  • OpenMP는 공유 메모리 환경에서 프로그램을 병렬화 하는 표준 입니다. OpenMP 는 컴파일러 지시자, 런타임 루틴 그리고 포트란, C, C++ 프로그램에서 공유 메모리 병렬화를 지정할때 프로그래머가 사용할 수 있는 환경 변수등을 제공합니다.
  • OpenMP 컴파일러 지시자는 프로그램내에서 사용되며 OpenMP를 인식하는 컴파일러가 멀티 쓰레드를 이용해서 병렬로 실행되는 실행파일을 생성하도록 지시 합니다. 소스 코드의 많은 수정이 필요 없습니다(최고의 퍼포먼스를 얻기 위해 튜닝을 할때를 빼고). OpenMP 컴파일러 지시자는 여러분이 다양한 아키텍쳐와 시스템 상에서 프로그램을 병렬화 하기 위한 우아하고, 일관적이고 포터블한 인터페이스를 사용 가능하도록 합니다. OpenMP는 광범위하게 채용되는 표준으로써 Sun, IBM, Intel, SGI 등이 지원하고 있습니다. (하단의 참고자료 링크를 이용해서 최신의 OpenMP 표준 문서를 확인하시기 바랍니다.)
  • OpenMP 는 쓰레드를 생성하고 관리해 줌으로써 병렬 프로그래밍을 좀더 발전된 레벨로 끌어 올려 줍니다. 여러분이 해야할일은 단순히 적절한 컴파일러 지시자를 소스 프로그램에 삽입시키고 OpenMP 를 지원하는 컴파일러를 이용해서 프로그램을 컴파일 하고 적절한 컴파일러 옵션을 사용 하는 것입니다 (썬 스튜디오는 -xopenmp 컴파일러 옵션을 사용). 컴파일러는 컴파일러 지시자를 해석하고 코드를 병렬화 시킵니다. OpenMP 를 지원하지 않는 컴파일러는 OpenMP 구문을 조용히 무시해 버립니다.
  • 이 글은 OpenMP를 C 와 C++ 프로그램에서 사용하는 예제를 제공하지만 동일한 프로그램이 포트란95 에도 존재 합니다. OpenMP 유저 가이드에서 좀 더 상세한 정보를 알아보시기 바랍니다.

OpenMP 컴파일러 지시자

  • OpenMP 표준은 컴파일러 지시자의 셋을 정의 합니다. 지시자는 컴파일러에게 코드의 블럭을 어떻게 처리할 것인지를 알려 줍니다. 가장 많이 쓰이는 기본 지시자는 #pragma omp parallel 로 병렬화 구역 임을 나타 냅니다.

  • OpenMP 는 병렬 실행시에 fork-join 모델을 사용 합니다. OpenMP 프로그램은 초기 쓰레드라고 하는 싱글 쓰레드로 시작 합니다. 쓰레드가 병렬 구조를 만나면 그 자신과 0개 혹은 그 이상의 추가 쓰레드로 구성된 쓰레드 팀을 만든 다음 그 자신이 새로운 팀의 마스터가 됩니다. 새로운 팀의 모든 멤버(마스터를 포함)는 병렬 구조상에서 코드를 실행 합니다. 병렬 구조의 끝에는 암묵적인 장벽이 존재 합니다. 오직 마스터 쓰레드만이 병렬 구문 이후의 유저 코드를 계속해서 실행할 수 있습니다.

  • 병렬 지역을 실행하는 팀의 쓰레드 갯수는 몇가지 방법으로 조정할 수 있습니다. 한가지 방법은 환경 변수 OMP_NUM_THREADS 를 이용하는 것입니다. 또다른 방법은 런타임 루틴 omp_set_num_threads() 를 호출 하는 것입니다. 또 다른 방법은 num_threads 절을 parallel 컴파일러 지시자와 같이 사용하는 것입니다.
  • OpenMP 는 두가지 기본 두가지의 작업-공유 구조를 지원해서 병렬 지역 내의 작업이 팀 내의 쓰레드 간에 나뉘어 질 수 있도록 지정할 수 있습니다. 이러한 작업-공유 구조는 루프와 섹션 입니다. 루프를 위해 #pragma omp 이 사용 되고 #pragma omp sections 가 섹션 을 위해 사용 됩니다 -- 병렬로 수행될 수 있는 코드의 블럭들.

  • #pragma omp barrier 는 팀의 모든 쓰레드가 장벽 이후의 코드를 계속 수행 하기 전에 다른 다른 쓰레드를 기다리도록 합니다. 이것은 병렬 지역의 끝에 암묵적인 장벽이라고 합니다. #pragma omp master 은 컴파일러에게 이후의 블럭은 오직 마스터 쓰레드에 의해서만 실행되도록 합니다. #pragma omp single 은 팀의 오직 하나의 쓰레드만이 해당 코드의 블럭을 실행시키도록 지시 합니다; 이 쓰레드는 꼭 마스터 쓰레드가 되어야 할 필요는 없습니다.여러분은 #pragma omp critical 지시자를 이용해서 오직 한번에 하나의 쓰레드만에 의해서 코드 블럭이 실행되도록 보호할 수 있습니다. 물론 이러한 지시자는 오직 parallel 지시자 안에서만 의미가 있습니다 (병렬 지역).

OpenMP 런타임 루틴

  • OpenMP 는 프로그램 상의 쓰레드에 대한 정보를 얻을 수 있는 몇가지 런타임 루틴을 제공 합니다. 것은 omp_get_num_threads(), omp_set_num_threads(), omp_get_max_threads(), omp_in_parallel(), 와 다른 루틴들을 포함합니다. 추가적 적으로 OpenMP 는 몇가지 lock 루틴을 제공해서 쓰레드 동기화에 사용할 수 있도록 해 줍니다.

OpenMP 환경 변수들

  • OpenMP 는 OpenMP 프로그램의 동작을 조정할 수 있는 몇가지 환경 변수들을 제공합니다.
  • 가장 중요한 환경 변수는 OMP_NUM_THREADS 로 병렬 지역을 실행할때 사용되는 팀내의 쓰레드 갯수를 조정합니다 (팀의 마스터 쓰레드도 포함). 널리 사용되는 또 다른 환경 변수는 OMP_DYNAMIC 입니다. 이 환경 변수를 FALSE 로 설정함으로써 구현적으로 실행시에 동적인 쓰레드 갯수 조정을 비활성화 시킬 수 있습니다. 일반적인 규칙은 시스템상의 코어 보다 적은 숫자의 쓰레드 숫자를 지정하는 것입니다.

  • 표준 OpenMP 환경 변수에 덧붙여서 썬 스튜디오 컴파일러는 썬-특수한 환경 변수의 셋을 추가 시켜서 런타임 환경을 좀 더 조정할 수 있도록 해 줍니다. 이러한 것들은 OpenMP 유저 가이드에 설명되어 있습니다.

Exemple1

  • 간단한 행렬 곱하기 프로그램을 이용해서 OpenMP가 어떻게 프로그램을 병렬화 시키는지 알아 봅시다. 다음의 코드 부분은 2개의 행렬을 곱하는 것입니다. 이것은 매우 간단한 예제로써 진짜로 훌륭한 행렬 곱셈 루틴을 원한다면 캐시 효과를 고려하거나 좀 더 낳은 알고리즘을 사용해야 합니다. (Strassen 혹은 Coppersmith 와 Winograd 의 알고리즘 등).


.

for (ii = 0; ii < nrows; ii++) {  
  for (jj = 0; jj < ncols; jj++) {  
    for (kk = 0; kk < nrows; kk++) {  
      array[ii][jj] = array[ii][kk] * array[kk][jj];  
    }  
  } 
}
.

  • 위의 루프로 감싸진 각 레벨에서 각 루프 반복은 독립적으로 수행될 수 있습니다. 그러므로 위의 코드 세그먼트의 병렬화는 매우 직관적입니다:#pragma omp parallel for 지시자를 제일 외곽쪽의 루프 전에 (ii 루프) 추가시킵니다. 지시자를 제일 외곽쪽 루프에 삽입하는 것이 이득입니다. 왜냐하면 이것이 최고의 퍼포먼스 이득을 가져다 주기 때문입니다. 병렬화된 루프에서 변수 array, ncols 와 nrows 는 쓰레드간에 공유 되고 ii, jj, 와 kk 는 각 쓰레드에 독립적입니다. 이제 이전의 코드는 다음과 같이 변경됩니다:

.
#pragma omp parallel for shared(array, ncols, nrows) private(ii, jj, kk) 
for (ii = 0; ii < nrows; ii++) { 
  for (jj = 0; jj < ncols; jj++) {  
    for (kk = 0; kk < nrows; kk++) {  
      array[ii][jj] = array[ii][kk] * array[kk][jj];  
    }  
  } 
}
.
.

또다른 예제로 0 <= x < n. 구간에서 f(x) 의 합을 구하는 다음의 코드 부분을 보시기 바랍니다.

.
for (ii = 0; ii < n; ii++) { 
  sum = sum + some_complex_long_fuction(a[ii]); 
}
.
.

위의 코드를 병렬화 하기 위해서 첫번째 단계는 다음과 같습니다.

#pragma omp parallel for shared(sum, a, n) private(ii, value)
for (ii = 0; ii < n; ii++) { 
  value = some_complex_long_fuction(a[ii]);
#pragma omp critical  sum = sum + value; 
}
.
.

혹은 좀더 낳은 방법으로 reduction 절을 이용할 수 있습니다

.
#pragma omp parallel for shared(a, n) private(ii) reduction(+: sum) 
for (ii = 0; ii < n; ii++) {  
  sum = sum + some_complex_long_fuction(a[ii]); 
}
.
.

Exemple2

root@wl ~ # cat openmp.c
#include <stdio.h>
#include <omp.h>

int main(int argc, char *argv[]) {
  int mt = 1, iam = 0, np = 1, omp = 0;

  #pragma omp parallel default(shared) private(mt, iam, np, omp)
  {
    #if defined (_OPENMP)
      mt = omp_get_max_threads();
      np = omp_get_num_threads();
      iam = omp_get_thread_num();
      omp = 1;
    #endif
    if (omp) {
      printf("최대쓰레드 개수: %d, 사용한 쓰레드개수: %d, 이 메시지를 출력한 쓰레드 번호: %d\n", mt, np, iam);
    } else {
      printf("OpenMP 사용하지 않음.\n");
    }
  }
  return 0;
}
root@wl ~ # export OMP_NUM_THREADS=4
root@wl ~ # cc -O3 -o openmp -xopenmp=parallel openmp.c
root@wl ~ # ./openmp
최대쓰레드 개수: 2, 사용한 쓰레드개수: 2, 이 메시지를 출력한 쓰레드 번호: 0
최대쓰레드 개수: 2, 사용한 쓰레드개수: 2, 이 메시지를 출력한 쓰레드 번호: 1
root@wl ~ # 

OpenMP 환경변수

  • 범용 OpenMP 환경 변수
    • OMP_NUM_THREADS: OpenMP에서 사용할 쓰래드의 개수. 기본값은 1이며, 보통 코어의 개수를 지정해준다.
    • OMP_DYNAMIC: FALSE로 설정하면 시스템의 코어개수에 상관 없이 OMP_NUM_THREADS에 설정된 개수를 사용한다.
  • 4개의 코어를 가지지 않은 시스템에서 강제로 4개의 쓰레드를사용하게 하려면 다음과 같이 하면 된다. 싱글 코어를 가지고 있는 경우 아래와 같이 하면 강제로 4개의 쓰레드를 사용하게 된다. (당연히 성능은 떨어진다)

root@wl ~ # export OMP_NUM_THREADS=4
root@wl ~ # export OMP_DYNAMIC=FALSE
root@wl ~ # ./matrix
  • 솔라리스 전용 OpenMP 환경 변수
    • SUNW_MP_PROCBIND: 각각의 쓰레드를 어느 가상 프로세서에 바인딩 할 것인지 결정한다. 번호는 가상 프로세서의 순서이다. [psrinfo | grep "on-line"]을 이용했을때 나오는 순서를 적어준다. (프로세서 아이디를 말하는게 아니다)

root@wl ~ $ /usr/sbin/psrinfo | grep "on-line"
0       on-line   since 10/07/09 21:00:00
1       on-line   since 10/07/09 21:00:00
10      on-line   since 10/07/09 21:00:00
11      on-line   since 10/07/09 21:00:00
20      on-line   since 10/07/09 21:00:00
21      on-line   since 10/07/09 21:00:00
root@wl ~ $ export SUNW_MP_PROCBIND=false
root@wl ~ $ export SUNW_MP_PROCBIND=0
root@wl ~ $ export SUNW_MP_PROCBIND="0 2 3 4 5"
root@wl ~ $ export SUNW_MP_PROCBIND="0-6"
  • STACKSIZE: 각각의 쓰레드의 스택 크기를 지정한다. 단위는 킬로바이트이다.

예) 스택사이즈를 16MiB로 지정: export STACKSIZE=16384

  • 간단한 OpenMP 예제

root@wl ~ # cat matrix.c
#include <stdio.h>
#include <omp.h>
#include <mtmalloc.h>
const int nrows =      10;
const int ncols = 1000000;

int main(int argc, char *argv[]) {
  int* array[nrows];

  printf("메모리 할당 및 초기화중...\n");
  #pragma omp parallel for
    for (int i = 0; i < nrows; i++) {
      array[i] = (int*) malloc(sizeof(int) * ncols);
    }

  printf("행렬 계산중...\n");
  #pragma omp parallel for
    for (int i = 0; i < nrows; i++) {
      printf("쓰레드 번호 %d이 %d열 계산중\n", omp_get_thread_num(), i);
      for (int j = 0; j < ncols; j++) {
        for (int k = 0; k < nrows; k++) {
          array[i][j] = array[i][k] * array[k][j];
        }
      }
    }
}
root@wl ~ # export OMP_NUM_THREADS=2
root@wl ~ # cc -O3 -mt -lmtmalloc -xopenmp=parallel -o matrix matrix.c
root@wl ~ # ./matrix
메모리 할당 및 초기화중...
행렬 계산중...
쓰레드 번호 0이 0열 계산중
쓰레드 번호 1이 5열 계산중
쓰레드 번호 0이 1열 계산중
쓰레드 번호 1이 6열 계산중
쓰레드 번호 0이 2열 계산중
쓰레드 번호 1이 7열 계산중
쓰레드 번호 0이 3열 계산중
쓰레드 번호 1이 8열 계산중
쓰레드 번호 0이 4열 계산중
쓰레드 번호 1이 9열 계산중
root@wl ~ #

시작하기

  • 프로그램을 병렬화 시키는 방법은 여러가지가 있습니다. 첫째로 여러분이 병렬화가 필요한지 결정합니다. 몇몇 알고리즘은 병렬화에 적당하지 못합니다. 만약 새로운 프로젝트를 시작한다면 여러분은 병렬화가 가능한 알고리즘을 선택할 수 있습니다. 코드가 올바른지 (직렬환경에서) 확인하는 것이 병렬화를 시도 하기 전에 가장 중요 합니다. 직렬화된 실행시간을 반드시 측정해서 병렬화가 유용한지에 대해서도 판단하시기 바랍니다.
  • 직렬로 실행되는 버전을 최적화 옵션을 이용해서 컴파일합니다. 컴파일러는 보통 여러분이 할 수 있는 것 보다 더 많은 최적화작업을 수행할 수 있습니다.
  • 프로그램을 병렬화할 준비가 되었다면 썬 스튜디오의 수 많은 기능과 툴들이 여러분의 목적을 이루도록 도와줄 것입니다. 간단하게 이러한 기능들에 대해 설명합니다.

자동 병렬화

  • 컴파일러의 자동 병렬화 옵션을 사용해 봅니다 (-xautopar). 병렬화를 컴파일러에게 넘김으로써 여러분이 노력할 필요 없이 컴파일러가 알아서 프로그램을 병렬화 해줍니다. 자동병렬화는 또한 OpenMP 지시자를 이용해서 병렬화 할수 있는 코드의 부분들을 인식할 수 있도록 도와주고 반대로 병렬화를 하지말아야 할 코드의 부분(예를 들어 내부 루프 의존 같은)도 알려 줍니다. 여러분은 컴파일러가 알려주는 정보를 -g 플래그를 이용해서 프로그램을 컴파일 해서 썬 스튜디오의 er_src(1) 를 이용함으로써 확인할 수 있습니다.

 % cc -g -xautopar -c source.c % er_src source.o

자동범위지정

  • OpenMP 프로그램시에 일반적인 타입의 오류는 범위 지정의 오류 입니다. 즉 변수의 범위가 잘못 지정되어서, 예를 들어 private(shared) 로 지정되어야 할 변수가 shared (private) 로 지정되는 것 입니다. 자동범위 지정 기능은 썬 스튜디오 컴파일러가 변수의 범위를 자동으로 결정해 줍니다. 두가지 OpenMP 의 확장 기능이 지원됩니다: auto 절과 default(auto) 절. OpenMP 의 유저 가이드에서 자세한 내용을 확인하시기 바랍니다.

dbx 디버거

  • 썬 스튜디오 디버거 dbx 는 쓰레드 디버깅이 가능한 디버거로 여러분의 OpenMP 프로그램을 디버깅하는데 도움을 줍니다. OpenMP 프로그램을 디버깅 하려면 첫째로 -xopenmp=noopt -g 컴파일러 옵션을 이용해서 어떠한 최적화도 적용하지 않은채 컴파일하고 dbx 를 결과 실행파일을 이용해서 실행합니다. dbx 를 이용해서 여러분은 병렬 지역에 브레이크 포인트를 설정할 수 있고 병렬 지역을 순차적으로 실행시킬 수 있고 쓰레드에 private 한 변수를 검사 할 수 있고 기타 여러가지 작업을 할 수 있습니다.

퍼포먼스 분석기

  • 썬 스튜디오 퍼포먼스 분석기를 통해 프로그램의 병목현상을 잡아낼 수 있습니다. 이 툴은 사용자가 대부분의 시간이 소요되는 핫 루틴을 프로그램상에서 잡아낼 수 있습니다. 또한 작업 및 대기 시간, 함수의 속성, 소스 라인, 그리고 명령어등 OpenMP 프로그램의 병목현상을 잡아 낼 수 있도록 도와 줍니다.

=== OpenMP 와 MPI 혼용하기 ==

  • MPI (Message Passing Interface) 는 병렬 프로그램의 또 다른 모델입니다. OpenMP 와는 다르게 MPI 는 여러개의 프로세스를 실행시키고 TCP/IP 를 통해 통신 합니다. 이러한 프로세스들은 동일한 주소 공간을 공유하지 않기 때문에 원격 머신에서 실행 될 수 있습니다(혹은 클러스 환경). OpenMP 와 MPI 중 어느것이 더 낳다고 말하기는 어렵습니다. 두가지 모두 장단점이 존재 합니다. 더 흥미로운 점은 OpenMP 가 MPI 와 함께 사용될 수 있다는 것입니다. 일반적으로 MPI 를 사용해서 작업을 여러 머신으로 정련되지 않은 채로 분산시킨 다음 OpenMP 를 이용해서 각 싱글 머신의 병렬화 레벨을 좀더 향상 시키는 방법을 사용 합니다.

요약하자면 썬 스튜디오 컴파일러와 툴은 OpenMP 를 네이티브하게 지원하고프로그램을 병렬화 할 수 있는 수 많은 유용한 기능을 제공 합니다. 자세한 정보는 아래의 참고자료 섹션을 참고 바랍니다.

Resources

  • OpenMP specifications for C/C++ and Fortran 95. Includes examples and commentary. compunity.org The OpenMP User Community.

  • Techniques for Optimizing Applications by Rajit Garg and Ilya Sharapov. A practical guide to performance optimization of computationally intensive programs on Sun UltraSPARC platforms. A Sun Blueprint publication.

  • Sun Studio 11: OpenMP API User's Guide. This manual contains information specific to the Sun Studio implementation.

  • Parallel Programming in OpenMP by Rohit Chandra and others is a good introduction, and is published by Morgan Kaufmann. ISBN 1-55860-671-8.

  • OpenMP Support in Sun Studio Compilers and Tools

'dev > OpenMP' 카테고리의 다른 글

OpenMP  (0) 2012.02.02

gcc 는 GOMP 에 의해서 OpenMP 를 구현함. 

http://gcc.gnu.org/onlinedocs/gcc-4.2.4/libgomp/ 문서 참고

#include <stdio.h>
int main()
{
    #pragma omp parallel
    puts("openmp test");
}

g++ 에 -fopenmp 와 -lgomp 옵션을 주자.


'dev > OpenMP' 카테고리의 다른 글

OpenMP 소개글(펌 정리)  (0) 2012.02.03

list 보기                                ls          /          dir
디렉토리 생성                       mkdir        /          mkdir , md
디렉토리 삭제                       rmdir        /          rmdir , rd
디렉토리 트리                       ls -R         /          tree
파일 삭제                              rm          /          del , erase
파일 복사                              cp          /          copy
파일 이동                              mv         /          move
이름 변경                              mv         /          rename
change directory                   cd          /          cd
현재 디렉토리 표시                 pwd          /          cd
화면 정리                              clear       /          cls
명령어 해석기                    sh, csh, bash /          command.com
파일 내용 표시                      cat           /          type
도움말, 메뉴얼                      man          /          help
쉘 종료, 도스창 종료               exit           /          exit
시간 표시                             date         /          time
그대로 출력                          echo         /          echo
환경변수 표시                     set,env        /          set
경로 보기                        echo $PATH    /          path
버전 정보                         uname -a      /           ver

  • < network 관련 프로그램 >

사용자 정보 출력                                     finger       /      finger
ping                                                      ping       /       ping
라우팅 테이블                                       route -n     /       route print
네임서버 쿼리 툴                                 nslookup       /       nslookup
telnet                                                 telnet       /       telnet
ftp                                                         ftp       /       ftp
네트워크 경로 trace                          traceroute       /       tracert



  • < 파일, 디렉토리 , 문자열 관련 >


파일 안의 문자열 찾기                                   find       /      find
파일 안의 문자열 찾기                                  grep       /      findstr
긴 화일 한 화면씩 출력                                 more       /       more
2개 파일 내용 비교                                        diff       /       fc, comp
라인 에디터                                                 ed       /       edlin
문자열, 라인별 정렬                                    sort        /       sort
하위 디렉토리까지 복사                               cp -R       /       xcopy
file 속성 표시                                          lsattr        /       attrib
현재 경로를 저장 후 이동                            pushd       /        pushd
pushd로 저장한 경로로 이동                         popd       /        pupd
화일 감추기                                                   mv file .file       /       ATTRIB +h or -h
압축                                                               tar , zip          /          pkzip

  • < 시스템 관련 >

프로세스 정보                                       ps, top       /       taskmgr
컴퓨터 호스트명                                 hostname       /       hostname
scheduling                                         at, cron       /       at
프로세스 종료                                    kill , killall        /       tskill
시스템종료                        shutdown, halt, init 0       /       shutdown
file system 관련                                    mke2fs       /       format
ip표시,interface표시, 설정                        ifconfig       /       ipconfig
fdisk                                                      fdisk       /       fdisk
디스크검사                                              fsck        /        chkdsk
free memory 보기                                free, top       /       mem
scandisk                                         fsck, debugfs   /       scandisk



아래 링크는 redhat linux 문서 중

DOS와 LINUX 간에 비슷한 명령을 표로 나타낸 문서입니다. 

http://203.249.6.162/doc/starting-ko/ch-doslinux.html

 또 아래 링크를 보면 DOS 와 Linux 의 명령을 나열하고

기능상의 차이점이나 성능상의 차이점을 설명하고 있습니다.

 http://wiki.kldp.org/wiki.php/LinuxdocSgml/Dos-Win-to-Linux-HOWTO


아래 링크는 명령이 몇 개 없지만

각 리눅스/유닉스 명령을 클릭하면 설명을 볼 수 있습니다.

http://linux.sarang.net/paper/unix_help/DOStoUNIX.html

 

'dev > Linux' 카테고리의 다른 글

파일 내 문자 치환  (0) 2016.07.05
알아두면 유용한 워드 단축키  (0) 2015.05.01
tar 명령어 모음  (0) 2014.08.01
linux 시스템 정보  (0) 2012.05.14
[Linux] sub directory 별로 압축할 때  (0) 2012.02.17

Basic Syntax of Regular Expressions (정규표현식의 기본 문법)

먼저 특수문자 ‘^’와 ‘?를 살펴봅시다. 이 문자의 역할은 문자열의 시작과 끝을 의미합니다.다음과 같은 해당 예를 들 수 있습니다.

  • “^The”            : “The”로 시작하는 문자열
    “of despair$” : “of despair”로 끝나는 문자열
    “^abc$”          : “abc”로 시작하고 “abc”로 끝나는 문자열 (“abc” 라는 문자열도 해당됨)
    “notice”          : “notice”가 들어 있는 문자열

마지막 예제에서 보듯이 이 두 개의 특수문자가 없는 패턴은 검사대상이 되는 문자열에 어떤 위치에서든지 들어 있음을의미합니다.

특수문자로는 ‘*‘, ‘+‘, ‘?‘도 있습니다. 이 문자들은 어떤 문자의 반복에 관한 지정을 해주는 문자입니다. 각각 ’0또는 그 이상’, ’1또는 그 이상’, ’0또는 1′을 의미합니다. 여기에 몇 가지 예제가 있습니다.

  • “ab*” : a뒤에 0 이상의 b가 있는 문자열 (“a”, “ab”, “abbb”, 등);
  • “ab+” : 위와 동일 하지만 최소한 하나 이상의 b가 있어야 함 (“ab”, “abbb”, 등);
  • “ab?” : b가 하나 있을 수도 있고 없을 수도 있음 (ab 또는 a)
  • “a?b+$” : a가 있을 수도 있고 없을 수도 있으며 그뒤에 하나 이상의 b로 끝나는 문자열
{ }를 사용하면 반복되는 수를 영역으로 지정할 수 있습니다.

  • “ab{2}” : a뒤에 2개의 b가 있는 문자열 (“abb”);
    “ab{2,}” : a뒤에 최소한 2개 이상의 b가 있는 문자열 (“abb”, “abbbb”, 등.);
    “ab{3,5}” : a뒤에 3개에서 5개 사이의 b가 있는 문자열 (“abbb”, “abbbb”, 또는 “abbbbb”)
.

{ }를 사용할 대는 반드시 첫 번째 숫자는 적어야 됨을 유의합니다. ((O) “{0,2}”, (X) “{,2}”). 또한 ‘*’, ‘+’, ‘?’는 각각 “{0,}”, “{1,}”, “{0,1}”와 같습니다.

이제 ()를 사용해서 하나의 문자가 아닌 여러 문자를 지정하는 방법을 알아봅니다.

  • “a(bc)*” : a 뒤에 “bc”가 0또는 그이상의 수만큼 있는 문자열
    “a(bc){1,5}” : a 뒤에 “bc.”가 1에서 5번 들어 있는 문자열
또 다른 특수문자로는 OR 연산을 하는 ‘|’를 들 수 있습니다.

  • “hi|hello” : “hi”나 “hello”가 들어 있는 문자열
    “(b|cd)ef” : “bef” 또는 “cdef”
    “(a|b)*c” : a와 b가 섞여서 여러번 나타나고 그뒤에 c가 붙어있는 패턴
‘.’ (period)는 어떤 한 문자를 의미합니다.

  • “a.[0-9]” : a뒤에 한 문자와 숫자가 붙어 있는 패턴
    “^.{3}$” : 3문자로만 되어 있는 문자열
[]표현은 문자열의 해당 위치에 사용될 수 있는 문자를 표현하는데 사용합니다.

  • “[ab]” : a또는 b (“a|b”와 동일한 표현);
    “[a-d]” : 소문자 ‘a’에서 ‘d’까지 (“a|b|c|d”또는 “[abcd]“와 동일);
    “^[a-zA-Z]” : 영문자로 시작하는 문자열
    “[0-9]%” : % 문자 앞에 하나의 문자가 붙어 있는 패턴
    “,[a-zA-Z0-9]$” : 영문자, 숫자로 끝나는 문자열 패턴
[]에서 ‘^’를 표현의 가장 처음에 사용하면 나타나서는 안 되는 문자를 지정할 수 있습니다. (예> “%[^a-zA-Z]%” 두 % 사이에 영문자가 없는 패턴)

“^.[$()|*+?{"같은 특수 문자는 백슬레쉬('')를 사용해서 escape될 수 있습니다( 역자 주 : escape 이란 다른 말로 literal로 탈출한다라고 할 수 있습니다 즉 특수문자로 인식되지 않고 일반 문자로 인식되게 합니다). 사용하는 관점에서 보면 백슬레쉬도 PHP3의 문자열에서 escape되어야 하기 때문에 예를 들어 "($|?[0-9]+”같은 정규표현식은 ereg(“($|?[0-9]+”, $str) 와 같이 사용됩니다 (이 표현식은 무얼 검사하는 걸까요? ^^;(이건 역자가 한 말이 아닙니다))

하지만 []안에서는 특수문자가 모두 효력을 잃게 되기 때문에 이 법칙을 벗어남을 기억하세요 []안에서는 백슬레쉬를 포함한 모든 특수문자들이 그 힘을 잃습니다 (예> “[*+?{}.]“는 말그대로 ‘*’, ”, ‘+’, ‘?’, ‘{‘, ‘}’, ‘.’ 문자를 의미합니다. 그리고 regex man 페이지에 나오듯이 ‘]’문자 자체를 포함하려면 문자들 리스트의 첫 번째에 위치시킵니다(‘^’가 있으면 ‘^’뒤에). ‘-’를 포함하려면 첫 번째 또는 마지막 문자로 지정하고 ‘-’문자가 영역의 경계 (예> a에서 -까지)일 경우 영역지정 문자의 두 번째 경계로 지정([a--])합니다.

완벽한 설명을 하려면 대조 순서(collating sequences), 문자 클래스(character classes), 동일 클래스(equivalence classes)에 대해서도 다루어야 하지만 이 글에서는 별 상관관계가 없기 때문에 regex man 페이지를 참고하도록 합니다.

-Validating Money Strings (금액 문자열 검사하기)

ok 이제 우리는 여기서 배운 것을 뭔가 실질적인 것에 적용 시켜봅시다. 사용자가 입력한 금액을 검사하는 정규표현식에 대해 알아봅니다. 금액은 “10000.00″ 와 “10,000.00″, 와, 센트 없이, “10000″ 와 “10,000″ 이렇게 4가지 방법으로 사용됩니다. (역자주 : 달러와 센트 군요 &#34625;,.&#34625;)

다음 정규표현식을 기초로 시작해 봅시다.

  • ^[1-9][0-9]*$

이 정규표현식은 0으로 시작하지 않는 어떠한 수인지를 검사합니다. 하지만 “0″도 통과되지 못합니다. 그래서 다음과 같이 수정합니다.

  • ^(0|[1-9][0-9]*)$

말로 표현하면 “0 이거나 0으로 시작하지 않는 수”입니다. 이제 수 앞에 -부호도 사용할 수 있게 수정해 봅니다.

  • ^(0|-?[1-9][0-9]*)$

이 뜻은 “0 이거나 -이 있을 수 있는 수이고 이 수는 0으로 시작하지 않는다”입니다. 이제 좀 느슨하게 하고 유저가 0으로 시작하는 수도 입력할 수 있도록 해봅니다. 금액에 필요없는 -부호도 없애버립니다. 그리고 선택사항인 소수점 부분 패턴도 넣어서 다음 정규표현식이 나옵니다.

  • ^[0-9]+(.[0-9]+)?$

하이라이트된 부분은 소수점(.)이 항상 최소한 하나이상의 수와 붙어 있어야 함을 의미합니다. 그러므로 예를 들면 “10.”은 통과되지 못하고 “10″ 과 “10.2″는 통과합니다.

  • ^[0-9]+(.[0-9]{2})?$

이제 소수점 뒤에 반드시 2개의 수가 붙어 있어야 합니다. 이게 너무 심하다 싶으면 다음과 같이 해서

  • ^[0-9]+(.[0-9]{1,2})?$

소수점 뒤에 하나의 숫자만 올 수도 있게 합니다. 이제 1000단위를 구분하는 ‘,’를 표현해 봅니다.

  • ^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$

“1~3개의 숫자와 그 뒤에 ‘,’와 3개의 숫자로 이루어진 부분이 0개 또는 그 이상이 붙어 있는 패턴”. 쉽죠? 이제 ‘,’도 선택사항(옵션:option)으로 만들어 봅니다.

  • ^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$

이게 전부입니다. 여기서 ‘+’를 ‘*’로 바꾸면 빈 문자열도 통과되는 패턴이 됩니다. 함수호출할 때 백슬래쉬 문자 escape하는 것 (역자 : /를 //로) 잊지 마세요. 일단 문자열이 검사되어 지면 str_replace(“,” , “” , $money) 함수로 ‘,’를 없애버리고 double로 형 변환을 해서 산술연산에도 사용할 수 있게 합니다.

- Validating E-mail Addresses (E-mail 주소 검사하기)

이제 e-mail 주소를 살펴봅시다. e-mail주소는 3부분으로 구성됩니다. : user 명(@왼쪽편에 있는 모든 것), ‘@’, 그리고 서버명(나머지 부분들) user명은 대문자 또는 소문자와 숫자, ‘.’ ‘-’, ‘_’로 구성됩니다. ‘_’를 제외하면 서버명도 마찬가지입니다. user 명은 .으로 시작하거나 끝나지 않습니다. domain명도 마찬가지입니다. 또한 .이 연속으로 있을 수도 없고 . 사이에는 최소한 하나 이상의 문자가 있어야 합니다. 이제 user명 부분을 검사하는 정규표현식을 만들어 봅시다.

  • ^[_a-zA-Z0-9-]+$

이 정규표현식은 아직 .을 지원하지 않습니다. 다음과 같이 수정합니다.

  • ^[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*$

말로 하면 “최소한 하나의 유효한 문자(valid character)와 그 뒤에 .과 유효문자들로 구성된 부분이 0또는 그 이상이 있는 패턴”입니다.

좀 간단하게 하기 위해 이 정규표현식을 ereg()대신에 eregi()함수에 사용합니다. eregi()함수는 대소문자를 구분하지 않기 때문에 “a-z”와 “A-Z”같이 두 개의 영역을 지정하지 않아도 되는 이점이 있습니다.(둘 중 어떤 것이라도 상관없음)

  • ^[_a-z0-9-]+(.[_a-z0-9-]+)*$

서버명의 경우 ‘_’만 제외하고는 동일합니다.

  • ^[a-z0-9-]+(.[a-z0-9-]+)*$

이제 ‘@’를 중심으로 서로 붙여서 다음과 같이 만들어 냅니다.

  • ^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$

- 기타 사용

Extracting Parts of a String (문자열의 일부분 잘라내기)

ereg()와 eregi()함수는 문자열에서 패턴에 해당되는 부분을 잘라내는 기능이 있습니다. (메뉴얼 참고) 예를 들면 path/URL 문자열에서 파일명을 잘라내고 싶은 경우 다음과 같은 코드가 필요할 것입니다.

ereg(“([^/]*)$”, $pathOrUrl, $regs);
echo $regs[1];

Advanced Replacing (치환의 발전된 형태)

ereg_replace() 와 eregi_replace()는 아주 유용한 함수입니다. 문자열에 있는 모든 문자를 ‘,’로 구분한다고 가정해 봅시다. 다음과 같이 할 수 있습니다. (역자 : trim()함수는 문자열의 앞과 뒤에 있는 공백문자를 모두 제거하는 함수)

ereg_replace(“[ nrt]+”, “,”, trim($str));

'dev > etc' 카테고리의 다른 글

TAR  (0) 2012.03.01
우분투 타이틀바 옮기기  (0) 2012.02.03
안철수 님의 말(펌)  (0) 2010.11.09
glib  (0) 2010.11.09
[VirtualBox] Linux에서 게스트 확장 설치  (0) 2010.11.09
연초부터 아이폰, 아이패드 열풍이 대단합니다. 애플의 CEO인 스티브 잡스가 신제품을 발표할 때마다 세계의 눈이 일제히 쏠립니다. 사실 IT하면 우리나라 기업들이 선두였는데 주춤한 게 아니냐는 우려들도 나오고 있죠. 우리 IT의 현주소는 어디인가, 왜 우리나라에는 스티브 잡스가 나오지 않는가, 이런 궁금증을 속 시원하게 진단해보죠. 안철수 카이스트 석좌교수 연결돼 있습니다. 


◇ 김현정 앵커> 어렵게 모셨습니다. 요즈음도 많이 바쁘신가 봐요? 

◆ 안철수> 네, 교수가 되다보니까. 예전 회사 CEO 때는 다른 임원들이, 속된 표현으로, 대타를 할 수 있었는데요. 교수는 대타가 없더라고요. (웃음) 그래서 더 바쁜 것 같습니다. 

◇ 김현정 앵커> 교수님도 혹시 스마트폰을 사용하시나요? 

◆ 안철수> 미국에서 학교 다니고 있을 때 처음 출시가 됐는데요. 그때부터 썼습니다. 

◇ 김현정 앵커> 휴대폰의 역사가 아이폰 출시를 기준으로 해서 이전과 이후로 나눠졌다, 이런 평가까지 나오는데요. 동의하십니까? 

◆ 안철수> 절반 정도는 맞고 절반 정도는 아닌 것 같긴 한데요. 예를 들면 MP3 플레이어가 사실은 애플이 처음 만든 게 아니고 예전에 있었고, 특히 한국 기업들이 굉장히 잘 했었는데, 애플에서 아이팟을 만들면서 폭발적으로 확산이 됐죠. 그런 것과 마찬가지로 이 스마트폰이라는 것도 애플이 만든 건 아니지만 아이폰을 기점으로 폭발적으로 확산됐다는 측면이 있으니까 반반인 것 같습니다. 

◇ 김현정 앵커> IT를 하시는 분으로서 자극을 받긴 받으셨나요? 

◆ 안철수> 저는 특별하게 새롭게 자극을 받지는 않았는데요. 아마 국내기업들이 많이 긴장을 하고 계신 것 같고요. 그런데 아직도 말씀을 나누다보면 안타까운 것 중 하나가 그 의미를 정확하게 파악을 잘 못하시고 계신 것 같더라고요. 

◇ 김현정 앵커> 무슨 말씀이세요, 어떤 부분? 

◆ 안철수> 단순히 휴대폰 대 휴대폰으로, 기계측면에서만 비교를 해서 좀 더 예쁜 디자인에, 좀 더 편리하게 기계를 만들면 따라잡을 수 있을 게 아닌가, 그렇게 말씀들을 하시더라고요. 사실 제가 좀 위기감을 느끼고 설명도 드렸었는데요. 어떤 것이 있냐면, 애플의 아이폰으로 대표되는 이런 미국의 스마트폰들은 지금까지와는 다른 기계가 아니고 일종의 비즈니스 모델 간의 충돌이라고 할 수 있거든요. 

◇ 김현정 앵커> 좀 어렵네요. 

◆ 안철수> 쉽게 설명을 해드리면, 지금까지 국내기업들 대기업들은 주로 수직적인 계열화에 굉장히 익숙해있습니다. 무슨 뜻이냐 하면, 어떤 기계를 만들기 위한 부품들을 하청업체를 통해서 조달을 받는데요. 그래서 한국기업들이 대부분 수직적인 효율화에 굉장히 익숙해있는데요. 지금 미국에서 건너오는 것들은 수직적인 것이 아니라 수평적인 겁니다. 

가장 이해하기 쉬운 예가 게임기라고 볼 수 있는데요. 지금 대표적으로 닌텐도가 있고, 소니의 플레이스테이션이 있는데요. 이들을 보면 만약에 기계 대 기계간의 싸움이라고 하면 소니의 기계가 압도적으로 성능이 우수합니다. 그런데 게임 소프트웨어들을 얼마나 많이 공급을 받을 수 있는가, 그 싸움이거든요. 그러다보니까 거기선 하청업체가 아니고요, 영어표현으로 서드파티(Third Party)라고 하는데요. 다른 독립적인 게임소프트웨어 업체들이 과연 자기가 어느 회사 것들을 만들면 많은 이득을 가져올 수 있고, 그리고 또 지원도 잘 받을 수 있는지를 따져보다가 닌텐도 게임을 만드는 거죠. 그걸 한마디로 표현하자면 수평적인 네트워크를 잘 만드는 그런 전쟁입니다. 

◇ 김현정 앵커> 아이폰은 유저들이 서로 콘텐츠를 올리고 그것을 나눠 갖고, 이런 수평적인 네트워킹이 되더라고요. 우리나라 휴대폰은 일방적으로 회사에서 주는 것들을 유저들이 사용해야 되고, 이런 부분도 차이가 있는 거군요? 

◆ 안철수> 네, 그래서 만약에 애플사에서 자기들만 프로그램들을 만들어서 공급을 한다면 다양한 프로그램을 만들기 힘든데요. 그것들을 수평적으로 개방을 해서 협조를 얻고 자기편으로 끌어들이는, 일종의 장을 만들어놓으니까 엄청나게 많은 사람들이 자진해서 그 소프트웨어를 만드는 겁니다. 거기에 한국회사들이 익숙하지가 않아서요, 그게 문제입니다. 

◇ 김현정 앵커> 전혀 새로운 형태의 비즈니스 모델이 나왔다는 그 부분을 기업들이 좀 깨달아야 된다는 말씀이세요? 

◆ 안철수> 하드웨어 싸움이 아니라 비즈니스 모델의 싸움이다, 그렇게 아시면 되겠습니다. 

◇ 김현정 앵커> 사실은 그동안 우리가 휴대폰 시장에서는 가장 앞서가는 선진국이었고요, 지금도 세계시장 점유율 따져보면 20% 넘습니다. 그런데 이 스마트폰 시장에서는 주도권을 뺏긴 거라고 보고 계신 거죠, 현장에선? 

◆ 안철수> 네, 뺏긴 거죠. 

◇ 김현정 앵커> 영국의 이코노미스트 인텔리전스 유닛(EIU)에서 매년 ‘IT산업경쟁력지수’라는 걸 발표하는데 2007년에는 우리나라가 3위였는데, 2009년에는 16위까지 아주 급속하게 추락을 했더라고요. 휴대폰뿐만 아니라 IT 산업 전반이 후퇴한 거라고 보십니까? 

◆ 안철수> 지금은 점점 더 소프트웨어가 중요해지는 그런 세상이 왔습니다. 아이폰도 사실은 소프트웨어의 파워를 보여주는 거고요. 그러다 보니 우리나라가 소프트웨어가 워낙에 취약했는데 예전에 비해서 그 중요도가 굉장히 증가하면서 우리는 이렇게 밀려나는 것 같은, 그런 모습들을 보이게 되는 거죠. 

◇ 김현정 앵커> 우리가 아무리 디자인을 더 세련되게 예쁘게 해도 소프트웨어가 이 정도 수준이라면 뛰어넘기 어렵다는 말씀이세요? 

◆ 안철수> 따라 잡기 어렵습니다. 

◇ 김현정 앵커> 굉장히 지금 단호하게 말씀하고 계십니다. (웃음) 말씀 듣고 보니까 좀 겁도 나고 우려가 많이 되는데... 정부도 좀 늦었지만 지원을 하겠다고 입장은 밝혔습니다. 좀 구체적으로 조언을 해 주신다면 어떨까요? 

◆ 안철수> 정부 지원이라고 이야기가 나오면 저는 우선 사실은 걱정부터 앞서는데요. 

◇ 김현정 앵커> (웃음) 아니, 그게 무슨 말씀이세요, 지원해준다는데? 

◆ 안철수> 왜 그러냐하면, 보통 보면 직접적인 지원들을 많이 합니다. 그러니까 연구개발비를 직접 지원해 준다든지, 아니면 창업자금을 대준다든지 해서 앞으로 3년 내에 몇 개의 소프트웨어 기업을 만들겠다, 그렇게 목표들을 많이 세우시는데요. 이번에는 안 그랬으면 합니다. 왜냐하면 이렇게 지원만 해서 새롭게 창업들이 많이 되다보면 시장을 놓고 싸워야 되는데요. 그런데 시장 자체가 불공정하고 왜곡돼있는 구조 속에서는 탄생한 기업들이 제대로 살아날 수가 없습니다. 정부에서 스스로 나서서 왜곡된 시장구조, 또 불투명한 시장구조를 바로 잡고, 정부 스스로가 시장을 만드는 역할을 하면 소프트웨어 회사들, 만약 가능성이 있다면 자기가 스스로 빚을 내서라도 만들 겁니다. 그런 것들이 성공가능성이 더 높은 거죠. 

◇ 김현정 앵커> 왜곡된 부분이 어떤 부분인가요? 

◆ 안철수> 예를 들면 대기업, 중소기업 간의 거래관행에서 대기업이 중소기업의 이익을 빼앗아가는 그런 구조가 소프트웨어 쪽에 굉장히 심각한데요. 그런 상황에서 창업자금만 지원해주면 창업했던 회사들이 제대로 경영이 될 수가 없거든요. 

◇ 김현정 앵커> 그렇군요. 또 다른 쪽 생각해볼 부분이, 아이폰을 만든 애플사 CEO 스티브 잡스인데요. 같은 IT 종사자로서 어떻게 보십니까? 

◆ 안철수> 우선은 저 나름대로 그분에게 교훈을 얻는다고 하면, 어떤 출신이나 학력보다 실력으로써 지금 정상에 선 사람이라는 면에서 인정을 해줄 수 있는 사람이라고 생각하고요. 

◇ 김현정 앵커> 대학을 중퇴했죠? 

◆ 안철수> 네, 그리고 두 번째로는 크게 실패를 했죠. 그래서 자기가 창업한 회사에서 쫓겨났으니까요. 그러다가 재기를 했는데요. 그래서 실패한 사람들에게도 계속 기회를 줄 수 있는 실리콘밸리의 환경이 굉장히 부럽기도 하고요. 그리고 또 한편으로는 한 분야의 전문가가 그렇게까지 인정을 받을 수 있으니까요. 그런 부분들이 존경스러운데... 사실 스티브 잡스가 모든 면에서 탁월한 재능을 보인 건 아니거든요. 자기의 재능을 정말 100% 발휘할 수 있는 그런 기회를 맞이한 거죠. 

◇ 김현정 앵커> 대통령도 한국의 스티브 잡스, 빌 게이츠가 나와야 된다, 이런 얘기도 했습니다만. 우리나라에서 그런 세계의 트렌트를 선도할만한 이런 인물이 안 나오는 이유는 어디에 있다고 보세요? 

◆ 안철수> (웃음) 아까 말씀드린 것과 일맥상통한데요. 실력보다는 출신이나 학력을 아무래도 중요하게 생각하는 사회다보니 그런 사람들이 우선 기회 자체를 가지지를 못하는 것 같고요. 두 번째는 스티브 잡스도 엄청나게 실패를 한 사람인데도 다시 기회를 잡았던 것처럼 그런 기회가 계속 주어져야 되는데요. 

로마와 카르타고가 아주 옛날에 전쟁을 했지 않습니까? 그런데 그 과정에서 보면 로마는 실패한 장수, 전쟁에서 진 장수를 처벌을 하지를 않았더라고요. 그래서 다시 사령관으로 임명하고 다시 기회를 주다보니까 그 전에 했던 터무니없는 실수를 하지 않았는데요, 카르타고에서는 한번 장수가 전쟁에서 지면 목을 베었답니다. 결국은 카르타고는 멸망해버리고 로마가 지중해를 제패하게 됐는데요. 

그런 것들을 봐도 실패한 사람에게 만약에 이 사람이 정말로 도덕적이고 정말로 열심히 했는데도 운이 맞지 않아서 실패를 했다면 다시 기회를 주는 게 그 사람의 값진 경험을 사회적인 자산으로 만드는 방법이거든요. 그런데 그게 좀 우리나라가 아무래도 약한 것 같고요. 세 번째는 아직도 전문가보다는 일반론자, 저널리스트가 득세하는 그런 세상인 것 같습니다. 아직은... 

◇ 김현정 앵커> 그게 무슨 말씀이세요? 

◆ 안철수> 한 분야를 깊게 파는 전문가들은 아주 작은 범위의 일밖에 하지 못하고, 그런 사람이 이렇게 큰일들을 할 수 있는 기회가 상대적으로 적다는 거죠. 

◇ 김현정 앵커> 제대로 대우받지도 못하고? 

◆ 안철수> 네, 그래서 그런 전문가가 결정권을 가질 수 있는 사회가 되어야 아마 스티브 잡스 같은 인물이 출현하지 않을까... 저는 있다고 봅니다. 있는데, 사회구조적인 문제 때문에 바깥으로 드러나지도 않고 기회도 가지지 못하는 것 같습니다. 

◇ 김현정 앵커> 분명히 있다고 하셨습니다. (웃음) 빨리 발견하고 이분들이 튀어나올 수 있는 사회 분위기가 되어야 될 텐데요. 시간이 많이 갔지만 한 가지만 좀 더 여쭙고 싶어요. 지금 졸업시즌이고 방송 듣는 젊은이들 중에도 새 출발, 새 각오를 다지는 청년들이 많이 있을 텐데. 가장 중요한 조언을 짧게 한마디 해주신다면 어떤 당부 해주고 싶으세요? 

◆ 안철수> 상대적으로 남들 보다 내가 잘하는 게 없다고 그렇게 실망을 하고 계신 젊은이들도 많은 것 같더라고요. 그런데 모든 사람들은 나름대로 각기 독특한 어떤 재능의 조합을 가지고 태어난다, 그런데 단지 문제는 사람들이 자기가 어떤 재능을 가지고 있는지를 깨닫지 못하거나 오히려 자기의 약점을 보완하는 데 노력을 쓰고 시간을 쓰다보니까 미처 자기 재능을 계발할 시간을 쓰지 못했다, 그래서 저도 거기에 전적으로 동의를 하고요. 지금이라도 자기가 어떤 재능을 가지고 있는 사람이고 정말로 피나는 노력으로 해서 하나의 강점으로 만들어가는 노력들, 그런 것들을 지금부터라도 하시면 되지 않을까 싶습니다. 

'dev > etc' 카테고리의 다른 글

TAR  (0) 2012.03.01
우분투 타이틀바 옮기기  (0) 2012.02.03
정규표현식의 기본 문법  (0) 2010.11.09
glib  (0) 2010.11.09
[VirtualBox] Linux에서 게스트 확장 설치  (0) 2010.11.09

1. Overview

GLib은 C 프로그래밍을 정말 쉽게 만들어주는 또다른 유틸리티다. GLib의 기능과 이점을 소개한다.

GLib은 C프로그래밍을 좀더 즐길수 있도록 해주는 유틸리티 라이브러리다. 예전부터 이런 라이브러리는 있었지만, 대중적이지도 않았고, 중심이 잘 잡히지도 않았고, 일관된 모습을 가지지도 않았었다. GTK+/GNOME을 통해 GLib을 알기 전에는 C의 기본함수를 신뢰했었다. C프로그래머가 되었을 때, 난 펄이나 C++ 의 STL과 좋은 컨테이너, 데이타 스토리지 기능들을 부러워 했었다. C의 기본 라이브러리는 불행히도 일관되지 않은 많은 로우레벨의 함수들을 가졌는데, 다른 플랫폼에서 동작하기가 어렵거나, 특정한 플랫폼에서만 구현이 되었다.

GLib은 이런 문제에대한 해답을 제시한다.C사용자를 종종 찌푸리게하는 세가지 기본적인 문제(With respect to C, it addresses three fundamental problematic issues C users often face):

  • Data containers
  • Portability
  • Utility

GLib의 가장 두드러지고 강력한 점은 컨테이너(containers) 다. 포터블한 코드를 작성하는데 매우 좋다는 것도 그렇지만 말이다. Glib을 쓴다면, 모든 대상 플랫폼에서 동작하게 하기 위해 특정한 기능들만 사용하게 요구하지 않고, 다른 플랫폼에서 당신이 짠 코드가 만족하게 돌아가도록 자주 기도하는 모습을 스스로 발견하지 않아도 된다. C와 유사한 개념으로, C의 기본 라이브러리보다 더 일관된 유틸리티를 제공한다. Beyond all this, GLib touts the more exotic features of a simple lexical analyzer and a main loop functionality for event-driven applications.

2. Typedefs

GLib의 typedef들은 넓은 범위를 가진다. 어떤 것은 타이핑을 줄이기 위해서 어떤 것은 이식성을 위해서, 어떤 것은 단순성과 이름의 일관성을 위해서 디자인 되었다. 타이핑을 줄이기 위해서 unsigned 타입을 볼 수 있다. unsigned int 대신에 guint형을 쓸 수 있다. 이 방식은 char 타입과 모든 int 타입에 적용된다.

이식성있는 typedef은 특정한 크기의 정수형을 사용하는 문제에 사용한다. 예를 들어, 16비트 정수는 gint16, 부호없는 8비트 정수는 guint8이다. 크기는 8, 16, 32 그리고 머신과 컴파일러가 64비트 정수를 지원할 경우 64를 쓸 수 있다. 물론 G_HAVE_INT64라는 매크로를 이용해서 검사해 보고 사용해야 한다.

GLib은 코드의 간결성을 위해서 두가지 기본 typedef을 제공한다. 하나는 void * 형인 gpointer이고 다른 하나는 int형인 gboolean이다. 후자는 코드의 가독성을 증가시켜주고, automatic code scanners 에게 true/false를 검출 할 수 있게 한다. As a matter of taste rather than functionality, GLib은 모든 기본 타입앞에 "gint"처럼 "g"를 붙인다. 난 개인적으로 사용하지는 않지만, 어떤 사람들은 이런 타입들을 사용해서 일관성을 증가시킨다.

3. Memory allocation

기본 콤포넌트, 메모리 할당부터 시작해 보자. standard malloc 과 free 는 완전하지 않다. free는 충돌할 수도 있는데 예를 들어, 널값을 넘기면 malloc은 널값을 리턴한다. 널값을 체크하지 않으면 어플리케이션이 어떤 동작을 할 지 모른다. GLib은 동등한 g_malloc과 g_free를 정의한다. g_malloc은 리턴메모리를 보장한다. 메모리 할당을 더이상 할수 없으면 프로그램이 정지한다. 이것은 나중에 세그먼트 폴트를 일으키며 제대로 동작하지 않는 것 보다 낫다. g_free 는 널값을 전달할수 있는데, 아무것도 하지 않고 , free를 해야하는 많은 포인터를 가진 오브젝트면 이것을 해제하는 cleaner function을 실행한다.

g_malloc은 nice 한데, g_new와 g_new0는 더 많이 효용이 있다. 뒤의 두개는 nice하고 간단한 매크로다. 둘다 오브젝트 타입과 디자인된 여러 타입의 할당을 할 수 있다. g_new0는 할당한 메모리를 0으로 채운다. 이 함수의 장점은 쓰레기 값보다 0으로 채워진 것이 초기화 되지 않고 사용되는 에러를 찾기에 더 쉽다는 것이다. 아래는 20개의 정수 배열을 할당하고 나중에 해제하는 예제이다.

   Allocating and freeing an array
    
   int *array  g_new0(int, 20);
     ...
   g_free(array);
    
   Utility functions

당신은 C에서 문자열을 작업을 할 것이다. C에서 문자열 작업은 축복이자 저주다(-_-;). GLib의 문자열 유틸함수는 안좋은 부분을 다룰수 있게 한다. 넘긴 문자열를 조작하는 함수를 보자. 전달한 문자열의 대소문자 변환을 위해서 g_strup과 g_strdown이 있다. 처음이나 끝의 공백제거를 할 수도 있다. 처음부분의 공백을 제거하기 위해서 g_strchug을, 끝부분의 공백제거를 위해 g_strchomp를, 둘다를 위해서 g_strtrip 이 있다. 이 3가지 함수는 직접 문자열을 조작한다. 바보같이 새로운 문자열을 할당하지는 않는다. 조작된 문자열은 이런 함수들사이에 쉽게 연결되도록 한다. 파일을 읽어서 모든 시작부분의 공백을 제거하고 대문자로 바꾸는 다음 예제를 생각해 보자 :

   FILE *fp  fopen("some-file.foo", "r");
   char buf[256];
    
   while(fgets(buf, sizeof(buf), fp)) {
        g_strup(g_strchug(buf));
       /* buf is now upper case and leading whitespace is gone */
   }

새로운 문자열을 할당하는 함수를 보자. g_strdup는 기존의 strdup를 g_malloc을 이용해서 구현한 것이다. 이것은 문자열을 새로 할당하고 복사해서 리턴한다. 특정한 개수의 문자열을 복사하고 싶을 때는 g_strndup가 있다(개수를 지정하는 인수를 받는다). g_strconcat라는 다른 함수는 NULL로 끝나고 지정되지 않은 길이의 문자열을 인수로 받는다. 그리고 문자열들을 합친후 새로운 메모리를 할당해서 리턴한다. 다음은 문자열에 디렉토리 이름을 추가하고 확장하는 예이다 :

static void
 foo(char *string)
 {
         char *file;
         file  g_strconcat("/some/path/", string, ".txt", NULL);
         ...
         g_free(file);
 }     

불안전한 sprintf를 효과적으로 대체하는 두 함수가 있다. 첫째는 g_snprintf로, snprintf를 이식성있게 구현한 것이다. 첫번째 인수로 버퍼를 받고 두번째 인수로 버퍼의 크기를 받는다. 그러나 이것은 buffer overrun을 일으키지 않으면서, sprintf와 정확히 같은 동작을 한다. 종종 얼마나 많은 크기의 버퍼를 필요로 할지 모를 때가 있는데, 이럴 경우 g_strdup_prtinf를 사용할 수 있다. 이 함수는 format string만을 받아들이고, 새로운 버퍼에 할당해서 리턴된다.

g_snprintf와 g_strdup_printf의 사용 예

char foo[256];
char *bar;

g_snprintf(foo, 256, "The number pi: %g", M_PI);
bar  g_strdup_printf("The number pi: %g\n", M_PI);

물론 이외에도 많은 GLib 유틸 함수가 존재한다. 모든 함수의 리스트를 보기 원한다면 GLib문서를 보면 된다.

4. Containers

기본적인 것을 보았으니 컨테이너들을 파헤쳐 보자. 대부분의 컨테이너는 일반적인 한가지를 가는데, 데이터 저장을 위한 void pointer이다. 이것은 엄청난 유연성을 제공하지만, 컴파일러의 강제적인 type safety 는 없다. 당신이 늘 한가지 타입의 한가지 컨테이너를 사용하고 컨테이너를 overload하지 않거나 어떤 종류의 실시간 타입체크 메카니즘을 사용한다면 가능하긴 하다. 아직 난 GLib의 컨테이너를 사용했다는 이유로 인한 버그는 없는데, 큰 문제가 없다고 보인다. void pointer를 사용해서 생기는 한가지 문제는 primitive type을 사용하기 힘들다는 것이다. 그러나 당신이 생각할 수 있는 모든 플랫폼에서 포인터는 단지 정수형과 같은 크기의 공간을 차지하고, 당신은 포인터 대신에 정수를 저장할 수도 있다. 사실 GLib은 gpointer와 int간의 정확한 형변환을 하게 해주는 GINT_TO_POINTER와 GPOINTER_TO_INT를 정의한다. 이런 매크로를 통해서 당신의 코드는 쓸데없는 경고 없이 다른 플랫폼으로 이식할 수 있다.

예제 :

gpointer foo  GINT_TO_POINTER(50);
 ...
 int bar  GPOINTER_TO_INT(foo);

5. Linked lists

Linked list는 단연 GLib에서 가장 많이 쓰이는(어쩌면 남용되는) 컨테이너다. 이것의 이름은 GList와 GSList다. GList는 이중 연결리스트를 구현한 것이고, GSList는 단일 연결 리스트를 구현한 것이다. 함수에 있어서 둘다 매우 유사하며, 특별한 포인터에 대해 공간제약이 있지 않다면, 대부분의 경우 GList를 사용할 수 있다. GSList는 한쌍의 함수가 없지만, 나머지는 GList의 함수와 같다. GList에서 함수 이름을 g_lsit_로 시작하는 것을, GSList에서는 g_slist_로 시작하면 된다.

GList의 구조는 모든 리스트가 포인터로 이루어져 있지 않고 단지 하나의 노드일 뿐이다. 즉 모든 노드가 사실 GList의 구조체인 것이다. 그래서 각각의 구조체는 세개의 포인터를 가지는데, "data"는 이 노드의 데이터를 저장하고, "next"는 다음 노드를, 그리고 "prev"는 이전 노드를 가리킨다. GSList는 물론 "prev" 노드가 없다. 연결리스트에 저장하기 위해 당신은 첫번째 노드의 GList에 포인터를 저장하면 된다. NULL 포인터는 비어있는 리스트를 나타내고, 모든 GList함수는 NULL값을 받아들일 수 있으며 비어있는 리스트처럼 정확히 조작된다.

6. Basic functions

대부분의 기본 함수는 g_lsit_append와 g_list_prepend 다. 첫번째 인수는 현재의 리스트를 가리킨다. 두번째는 리스트에 append나 prepend할 데이터다. 리턴되는 것은 결과로서 생기는 리스트의 첫번째 노드의 포인터다. 다음은 세개의 문자열에 대한 리스트를 생성하고, printf로 출력하는 예제이다 :

   1 GList *list  NULL; /* our list pointer */
   2 GList *li; /* an iterator variable */
   3 
   4 
   5 list  g_list_append(list, "foo1");
   6 list  g_list_append(list, "foo2");
   7 list  g_list_append(list, "foo3");
   8 
   9 
  10 for(li  list; li ! NULL; li  li->next)
  11         printf("STRING: %s\n", (char *)li->data);

리스트를 해제하기 위해서 g_list_free를 사용한다. 이 해제는 현재의 노드 뿐만 아니라 리스트의 모든 노드를 해제한다. 당신의 리스트의 데이터를 해제할 때 주의해서 사용해야 한다. 이것과 같이 동작하는 g_lsit_foreach 라는 유틸함수가 하나 있다. 이 함수는 첫번째 인수로 리스트를 받아들이고 두번째 인수로 GFunc 타입의 포인터를, 세번째 인수로 사용자 데이터 포인터(위에 설명이 있다) 를 받는다. GFunc는 실제로 두개의 인수를 가진다 : 리스트의 데이터 값의 포인터일 경우, 사용자 데이터 포인터는 g_list_foreach의 마지막 인수로 전달된 것이다.

대부분의 경우 함수에 전달하는 사용자 데이터 인수는 신경쓰지 않는다. 아마도 당신은 단지 모든 노드의 데이터 포인터에 대해 g_free를 원할 수도 있다. 당신의 함수가 단지 하나의 인수(the data pointer) 만을 가진다면, GFunc로 전달 할 수 있다. 당신의 함수는 단지 명시된 인수를 무시할 것이다. 하지만 그렇게 하면 당신은 당신의 함수를 GFunc로 캐스트 해야 한다. 주의 : 캐스팅을 할 때 당신은 C에게 당신이 무엇을 할지 알려주어야 하는데, 다른 타입의 함수를 전달 하지 않아야 한다. (Most of the time you don't care about passing the user_data argument to the function. You perhaps just want to call g_free on the data pointer of every node. As long as your function only takes one argument (the data pointer), you can just pass that function as a GFunc. Your function will just ignore the extra argument. However, you have to then cast your function to GFunc. Be careful; with casting you are telling C that you know what you are doing, so don't pass a function of a different type.) 모든 노드에 대해서 g_free를 실행하고 그 다음에 리스트를 해제하는 예제이다 :

   1 g_list_foreach(list, (GFunc)g_free, NULL);
   2 g_list_free(list);

어떤때는 리스트의 특정한 노드로 가야할 필요가 있을 것이다. 리스트에서 n번째 GList포인터를 얻는 방법에 대해 이야기해 보자. g_list_nth를 호출하고, 리스트 포인터와 n번째를 가리키는 정수 n을 주면 해당 GList 포인터를 리턴한다. 하지만 대부분의 경우 당신은 해당 노드의 데이터 포인터를 리턴하는 g_list_nth_data를 사용하길 원할 것이다. 두 함수는 잘못된 인덱스 번호를 넘긴 경우등의 에러일때 NULL을 반환한다. 이제 어떻게 특정한 데이터 포인터의 인덱스를 얻을 것인가? 리스트와 데이터의 포인터로 g_list_index를 호출하면, 리스트 첫 노드로 부터의 위치(인덱스)를 정수로 반환한다. 리스트안의 특정한 GList의 인덱스를 얻기 위해서 g_list_position을 호출하고 데이터 포인터 대신에 GList의 포인터를 넘겨주면 된다. 둘 모두 에러시에 -1을 반환한다. 모든 인덱스는 보통 C에서의 zero-base이다( All indexes are zero-based as is usual for C.). 여기에 예제가 있다:

   1 GList *list  NULL;
   2 char *foo  "foo";
   3 char *bar  "bar";
   4 
   5 
   6 list  g_list_append(list, foo);
   7 list  g_list_append(list, bar);
   8 
   9 
  10 /* test g_list_nth_data */
  11 printf("This should be bar: '%s'\n", (char *)g_list_nth_data(list, 1));
  12 
  13 
  14 /* test g_list_index */
  15 printf("This should be 0: '%d'\n", g_list_index(list, foo));
  16 

리스트의 특정한 엘리먼트를 찾고 싶을 수도 있다. 리스트와 데이터의 포인터를 인수로서 g_list_find를 호출하면, 그런 데이터를 가진 노드의 GList의 포인터가 리턴 된다. 그러나 대부부의 경우 포인터가 완전히 다르면, 문자열 같은 실제 데이터가 같을 수도 있다. 그럴 경우 규칙적인 비교가 필요한데, g_list_find_custom 함수가 제공 된다. 단지 g_list_find 와 같지만, GCompareFunc 타입의 함수 포인터를 특별한 인수로 더 가진다. 이 함수는 두 개의 포인터를 인수로 받아서 정수를 리턴한다. 숫자가 0이면 두 포인터가 같고, 0보다 작으면 첫번째 포인터가 두번째 포인터 보다 작으며, 0보다 크면 첫번째 포인터가 더 크다. 이것은 기본 strcmp 함수와 같은 의미며, strcmp를 사용한다. 그렇지만 GCompareFunc는 두개의 void pointer를 인수로 하고 strcmp는 두개의 character pointer(이건 사실 같은 것이다.)를 인수로 하므로 형 변환이 필요하다.

정렬을 목적으로 GCompareFunc를 g_list_sort에서 사용할 수 있다. 이 함수는 리스트와 비교함수를 인수로 받아서 새로운 리스트 포인터를 반환한다.

GCompareFunc 의 사용 예 :

   1 GList *list  NULL;
   2 GList *list2;
   3 
   4 
   5 list  g_list_append(list, "foo");
   6 list  g_list_append(list, "bar");
   7 
   8 
   9 list2  g_list_find_custom(list, "bar", (GCompareFunc)strcmp);
  10 /* list2 should now point to the second node of the list */
  11 
  12 
  13 list  g_list_sort(list, (GCompareFunc)strcmp);
  14 /* list should now be sorted */

아마 몇개의 다른 함수들도 알아챘을 것이다. 순서를 역전하는 g_list_reverse, 모든 리스트의 노드를 카피하는 g_list_copy (데이터를 복사하지는 않는다. 그건 직접 해야 한다.)같은 것들 말이다. 또한 처음 노드와 마지막 노드를 찾아주는 g_list_last, g_list_first 도 있다. 이 모든 함수는 GList 포인터를 인수로 받고 GList 타입의 포인터를 반환한다.

7. A different container: GString

다른 컨테이너를 살펴보자. GString은 제멋대로인 데이터를 위해 크기를 바꿀수 있는 컨테이너다. 이것은 표준 C 문자열 보다 높은 수준에서 조작이 되지만, 보통의 C 문자열이기 때문에 항상 내부 버퍼를 얻을 수 있다. 이것은 GString으로 C 문자열을 만든는데 매우 유용하게 한다. GString은 str과 len, 두개의 엘리먼트를 가진다. str은 단지 문자열의 내부 버퍼(비록 직접 조작할 필요는 없지만, 다른 C의 문자열 처럼 사용할 수 있다)이고, len은 스트링의 길이를 나타내는 정수다.

새로운 GString을 만들기 위해 g_string_new 함수를 호출하면 된다. 이 함수는 GString을 초기화 하기위해 필요한 C문자열을 인수로 받는다. NULL값을 넘기면, empty문자열로 인식한다. GString 구조체의 'str' 엘리먼트는 항상 유효한 C 문자열이며, g_string_new에 NULL 값을 넘겨도 반환된 자신은 절대로 NULL이 아니다. 문자열을 해제하기 위해서 g_string_free를 호출하며 놀랍게도 GString 포인터와 내부 메모리를 해제할지를 지정하는 boolean값을 인수로 받는다. 완전히 문자열을 지우고 싶으면 TRUE값을 넘기면 된다. 내부 메모리를 일반 C문자열 처럼 남겨두고 GString구조체만을 해제할 때는 FALSE를 넘기면 된다. 다음은 GString을 이용해서 어떻게 C문자열을 만드는지 보여준다 :

Example code using GString

   1 static char *
   2  build_a_string(void)
   3  {
   4          GString *gstring;
   5          char *tmp;
   6 
   7 
   8          /* make a new string */
   9          gstring  g_string_new(NULL);
  10 
  11 
  12          /* here we build the string somehow */
  13          ...
  14 
  15 
  16          /* store the pointer to the internal string buffer */     
  17          tmp  gstring->str;
  18 
  19 
  20          /* free the string, but not the internal string buffer */
  21          g_string_free(gstring, FALSE);
  22 
  23 
  24          /* return the new string */
  25          return tmp;
  26  }

문자열 같은 것을 어떻게 만드는지 보자. 시작하기 전에, GString함수는 GString pointer 를 반환한다는 것을 알아두자. 그렇다고 새로운 문자열 구조체를 반환하는 것은 아니다. 주어진 것과 정확히 같은 포인터를 반환한다. 반환되는 같은 포인터는 몇개의 함수를 연결하거나 비슷한 기교를 가능하게 해준다. 대부분의 경우 이것은 매우 유용하지는 않으며 당신은 안전하게 무시할 수 있다.

기본 동작은 append와 prepend다. 각각 두가지의 경우가 있는데 C문자열을 더하건나 단일 문자를 더하는 경우다. g_string_append는 GString pointer와 C문자열을 받고 C문자열을 GString뒤에 붙인다. 반면에, g_string_append_c는 두번째 인수로 단일 문자를 받으며 단일 문자를 뒤에 추가한다. g_string_prepend와 g_string_prepend_c 도 같은 방식이며, 뒤에 추가하는 대신에 GString의 앞쪽에 추가한다.

Appending and prepending

   1 GString *gstring  g_string_new("foo");
   2 
   3 
   4  g_string_append(gstring, "bar");
   5  g_string_append_c(gstring, '!');
   6  g_string_prepend_c(gstring, '!');
   7 
   8 
   9  /* gstring->str should now contain "!foobar!" */

종종 어떤 문자열의 중간에 다른 문자열을 삽입해야 하는 경우가 있다. 이것을 하는 함수는 g_string_insert와 g_string_insert_c이다. 둘다 세개의 인수를 받아들이는데, GString pointer, 삽입할 위치(0 based) 그리고 마지막으로, 삽입하고자 하는 것이다.

   1 Using g_string_insert_c 
   2  GString *gstring  g_string_new("foobar");
   3  g_string_insert_c(gstring, 3, '-');
   4  /* now gstring->str should be "foo-bar" */

문자열의 부분을 지워고 싶을 때도 있다. g_string_erase를 사용하고 인수는 (GString pointer 와) 시작 위치를 나타내는 정수 그리고 지우고자 하는 부분의 길이를 받는다.

   1 Using g_string_erase
   2 
   3 GString *gstring  g_string_new("fooBLAHbar");
   4 
   5 
   6  g_string_erase(gstring, 3, 4);
   7 
   8 
   9  /* now gstring->str should be "foobar" */

여기에 GString을 위해 sprintf와 비슷한 정말 깔끔한 함수가 있다. 두가지 선택이 있는데, sprintf와 같이 문자열을 덮어쓰는 g_string_sprintf와 덮어쓰지않고 뒤에 추가하는 g_string_sprintfa가 있다. 추가하는 것은 목록을 만들거나 할때 매우 유용하다(Appending is very useful for building, say, lists of things). 콤마로 분리된 1부터 10까지의 숫자 리스트를 만드는 것을 생각해 보자:

   1 Using g_string_sprintfa
   2 
   3 int i;
   4  GString *gstring  g_string_new(NULL);
   5 
   6 
   7  for(i  1; i &lt; 10; i++) {
   8          if(i &gt; 1)
   9                  g_string_sprintfa(gstring, ",%d", i);
  10          else
  11                  g_string_sprintfa(gstring, "%d", i);
  12  }

문자열을 모두 대문자나 소문자로 만드는 함수도 있고(g_string_up and g_string_down), 특정 길이의 문자열로 자르는 함수(g_string_truncate -- 문자열의 길이는 두번째 인수다), 그리고 새로운 문자열을 지정하는 함수(g_string_assign)도 있다.

   1 Using g_string_assign
   2 
   3  GString *gstring  g_string_new("fooBAR");
   4 
   5 
   6  /* make all upper case */
   7  g_string_up(gstring);
   8 
   9 
  10  /* make all lower case */
  11  g_string_down(gstring);
  12 
  13 
  14  /* truncate to 3 characters */
  15  g_string_truncate(gstring, 3);
  16 
  17 
  18  /* assigning "string" to the string */
  19  g_string_assign(gstring, "string");

GLib에는 이 문서에서 다루지 못한 많은 것들이 있다. the hashes, the trees, relations, the lexical scanner, the main loop, file descriptor io 등을 다룬 문서에 관심이 있다면 나에게 알려줘~!Resources

  • Consult the GLib reference manual.
  • See a site devoted to GLib shared libraries for the Palm Pilot.
  • Read last month's column on glade and libglade.
  • A GNOME application programming tutorial is available.
  • Visit the GNOME home page.
  • Visit the home page of the GTK+ library.
  • Try a GTK+ tutorial.
  • Read the tutorial on how to make GNOME Panel applets.
  • Learn the latest from the GNU project home page.
  • Visit RHAD Labs at RedHat, where a lot of GNOME/GTK+ development goes on.

  • Look into GIMP, where GTK+ originated.
  • Find more things to do with Linux and GNOME at the author's Web site.

 


'dev > etc' 카테고리의 다른 글

TAR  (0) 2012.03.01
우분투 타이틀바 옮기기  (0) 2012.02.03
정규표현식의 기본 문법  (0) 2010.11.09
안철수 님의 말(펌)  (0) 2010.11.09
[VirtualBox] Linux에서 게스트 확장 설치  (0) 2010.11.09

+ Recent posts