한국 임베디드 리눅스 프로젝트 (이하 KELP)에서 세미나를 개최한다고 합니다.


http://kelp.or.kr/korweblog/pages.php?page=03/10/27/3640332

당일 낮에 할 일이 없을듯 보이니... 저는 놀러갈 듯 하군요. ^^;; 밤에는 여행가기로 했고... -ㅅ-
다행히도 세미나가 집 앞(이라기에는 좀 멀지만... ^^;; ) 이니 츄리닝입고 가도 될듯하군요 ㅎㅎ

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

설정

트랙백

댓글

원래 레드햇 계열 자체를 좋아하지 않았고, 그래서 데비안으로 리눅스를 처음 입문했는데... 얼마전부터 듣기 시작한 DB 관련 강좌들을 실습하려고 보니 결국 CentOS를 설치하게 되네요.


처음 리눅스를 설치하고 공부하기 시작했을 당시에는 이 anaconda 화면이 나온다는 사실 자체로도 엄청나게 열광하면서, 이제는 리눅스도 데스크탑으로 쓸날이 멀지 않았구나 했었죠. (물론, 아직도 데스크탑에 리눅스를 설치해서 파는 곳은 많지 않습니다)

어쨋든 각설하고 11g를 데비안에서 설치했다는 글을 봤지만, 이전에도 그랬듯 결국 설치를 하다보니 이런저런 사소한 에러가 발생하더군요. 역시나 기준이 redhat, suse 같은 녀석들을 기준으로 만들었나봅니다. -_-

이제는 생각하면서 설치하기에는 리눅스 설치를 너무 많이 해봐서... 대충 선택해서 설치했습니다.


삽질하기 싫어서 그냥 레드햇 계열 찾다보니 나온게 이 녀석... 그냥 DVD 버전 토런트로 받아서 설치시작.
우분투를 보다가 이 녀석을 보니 참 초라하네요. 좌우지간, 설치를 하고 오라클 설치를 시작했습니다.
(파티션 관리자가 LVM을 기본으로 동작하는 것 같더군요. 뭐 나야 좋지하면서 그냥 패스)

설치된 결과를 보니 깔끔하긴 하더군요. 우분투처럼 이상한 쓸데없는 프로그램도 설치되어있지도 않고... (서버로 설치했다는 점을 감안해주세요 ㅎㅎ)
yum 이란 녀석이 aptitude 와 거의 유사하게 쓸 수 있군요. 꽤 마음에 듭니다.

예전에 제가 설치했던 레드햇과 다르게 rpm 명령어를 안써도 패키지 관리가 된다는 사실이 너무 좋더군요. -_-;;
뭐 결국 리눅스가 패키지 관리 툴이랑 설정파일, 로그파일 위치만 기억하면 기본적인것은 동일할테니... ㅎㅎ;

단하나 안좋은 점은 미러링 사이트가 적어서 업데이트 속도가 좀 안습...
미러링 사이트를 업데이트 하는 것 조차도 자동화 되있더군요. yum install yum-fastestmirror 를 이용하시면 됩니다.

오라클 설치는 http://refill.egloos.com/4164613 에서 참고해서 설치를 시작했고...

리눅스를 Server 모음으로 설치하니 gcc 가 설치안돼서 링크에서 에러가 발생했다.


일단 숙제부터 해야하는데... 벌써 자야할 시간이군;;

더보기


크리에이티브 커먼즈 라이선스
Creative Commons License

설정

트랙백

댓글

요즘 새롭게 떠오른 P2P 프로토콜이 있습니다.

바로 BitTorrent 라는 프로토콜로 Tracker 라는 교환서버를 기반으로 동작하는 P2P의 한 형태입니다. 자세한 사항은 위키 페디아를 참조하세요. 장점이자 단점은 검색이라는 것이 아닌 .torrent 파일을 가지고 교환된다는 점이죠. (대신에 .torrent 를 다루는 폐쇄형 공유 커뮤니티들이 더러 있습니다)

사용자 삽입 이미지

http://en.wikipedia.org/wiki/BitTorrent


사용자 삽입 이미지

이 게임은 클라이언트는 용량만 3GB이다

덕분에 torrent 파일이 없으면 다운로드는 요원한 일이라는 것은 장점이라면 장점. 단점이라면 단점이라면 단점입니다. 하지만 대용량 파일을 가진 컨텐츠를 배포해야하는 서비스에서는 이 만큼 좋은 배포 형태도 없죠.

가깝게는 블리자드사의 World Of Warcraft 한글판을 이 형태로 배포하고 있습니다. 서비스 제공자의 입장에서는 최소한의 비용 투자로 최대의 효과를 거두어 들이는 거죠 ^^

당연하겠지만 역시 리눅스 콘솔에도 이 프로토콜의 콘솔 클라이언트가 있습니다. rTorrent 라는 녀석입니다. ncurse 라이브러리를 이용해서 콘솔 프로그램임에도 불구하고 굉장히 편하게 사용할 수 있다는 장점이 있습니다.
(오페라 브라우저의 다운로드 매니저는 기본적으로 .torrent 를 지원합니다.)

이번에는 rTorrent 라는 프로그램을 사용해보려고 합니다.

우선은 aptitude 를 이용해서 rTorrent를 설치합니다.
사용자 삽입 이미지

aptitude install rtorrent

사용자 삽입 이미지

엔터키를 이용해 load> 라는 창에 .torrent 의 내용을 입력한다. (파일, URL 무관하다)

방향키로 다운로드 리스트 아이템을 선택하고 오른쪽 버튼을 누르면 해당 다운로드에 대한 정보를 볼 수 있다.
사용자 삽입 이미지사용자 삽입 이미지
사용자 삽입 이미지사용자 삽입 이미지
사용자 삽입 이미지사용자 삽입 이미지
사용자 삽입 이미지사용자 삽입 이미지

※ rTorrent 개발 페이지에서 가져온 단축키 내역입니다. 최신 버전과 약간 차이가 있는 듯합니다.

torrents 추가 및 제거
backspace URL, 파일 이름을 이용해서 torrent 를 추가한다. 디렉토리 내용을 보고 자동 완성하려고 Tab 키를 이용할 수 있다. 이때 ~/torrent/* 같이 와일드 카드 문자를 사용해서 입력하는 것이 가능하다.
return torrent 를 비 활성화된 상태로 남긴다는 점을 제외하면 backsapce 와 동일한 기능을한다. (활성화 단축키 ^s )
^O 선택된 torrent 를 위한 새로운 다운로드 디렉토리를 설정한다. torrent 가 아직 활성화된 상태가 아닐때만 동작한다.
^s 다운로드 시작. (완료 직전 이라면 해싱 작업을 먼저 시작한다)
^d 다운로드 중지. 혹은 정지된 다운로드를 제고
^r 다운로드와 무관하게 torrent 의 해싱 체크를 시작한다.

대역폭 제한
a/s/d 1/5/50 KB 씩 업로드 대역폭 증가.
z/x/c 1/5/50 KB 씩 업로드 대역폭 감소.
A/S/D 1/5/50 KB 씩 다운로드 대역폭 증가.
Z/X/C 1/5/50 KB 씩 다운로드 대역폭 감소.
※ 대역폭 제한은 단일 torrent 에 대한 제한이 아니라 전역적으로 제한된다.

네비게이션
1. 전역키
^q 프로그램 종료. (중복으로 명령을 내리면 트래커와 주고받는 신호를 무시하고 종료한다.)
up/down torrent 선택
left 이전 화면으로 복귀

2. 메인 뷰
right 다운로드 뷰로 전환
^r 토런트의 해시 체크 시작
+/- 토런트의 우선 순위 변경
l 로그 보기. Space 키로 종료
M-1 모든 다운로드 내역 보기
M-2 이름 순으로 모든 다운로드 내역 보기
M-3 시작된 다운로드 내역 보기
M-4 정지된 다운로드 내역 보기
M-5 완료된 다운로드 내역 보기
M-6 해싱중인 다운로드 내역 보기

3. 다운로드 뷰 키보기
right 토런트 파일 리스트로 전환
left 메인 뷰로 전환
1/2 최대 업로드 조절
3/4 최소 피어수 조절
5/6 최대 피어수 조절
o 트리커 리스트 출력.스페이스바로 한 구룹내의 트래커들을 순환. * 키를 이용해 선택된 트래커 의 활성화 설정을 토글
p 피어와 토런트 정보를 보기
t/T 트래커 요청 시작. 대문자 T를 이용하면 최소 요청 간격을 무시하고 강제로 요청을 할 수 있음.
u 전송 내역 보기
i Chunk 빈도 보기

4. 파일리스트 뷰
left 다운로드 뷰로 전환
space 파일 우선 순위 변경
* 모든 파일의 우선 순위 변경

크리에이티브 커먼즈 라이선스
Creative Commons License

설정

트랙백

댓글

오늘 우분투 대퍼를 설치했습니다.

워낙에 소문이 자자했지만 뭐 그러려니하다가 간만에 리눅스를 다시 설치해봅니다. (한 일년만인가 ㅡㅡ;;) 윈도우가 2번째 하드에 설치되있어서 GRUB 설정이 바로 안되더군요. -_- 귀찮게 스리...

정말로 많이 좋아졌더군요. 좋아졌다는 것은 시스템적인 측면이 아니라.. 최초 사용자의 접근성 측면에서 대폭 향상이 이루어진 듯합니다. 내공 높으신 분들은 그때나 지금이나 잘들 이용하시 겠지만 저 같은 하수인 경우에는 정말 엄청나게 힘들었던 설정들이 이제는 그냥 되네요. 헐;;;

대표적인게 바로 윈도우 글꼴... 예전에는 볼드체가 않나와서 pango 패치까지 해가면서 설정했던 것 같은데 이제는 fc-cache 만하면 바로 넘어가네요 -_-;;;

무엇보다도 SCIM 이란 놈이 생겼네요. 아마 입력기의 통합형 인터페이스 비슷한놈이라고 생각되는데 맞는지 모르겠습니다. (윈도우의 IME 처럼...)



단지 이제 아쉬운건 오픈 오피스네요. -_-; PPT의 문서 인식률은 거의 100%더군요. 단지 속도가 MS의 그것보다 반응이 상당히 느리고 애니메이션에 대한 인식이 불완전한 것 같습니다. (얼추보아서....) 아마 오픈 오피스 전용 포맷을 이용하면 해결이 되겠지만...

ODF 를 MS에서도 공식적으로 지원한다고 발표했던데... 나중에 오픈 오피스와 MS 오피스 사이에 이런식의 문제가 발생하는게 아닐까 불안하네요.

WORD 파일은 예전에 해봤을때 거의 인식이 잘 안되던데-_-; 지금은 어떤지 모르겠습니다.
(요즘은 워드보다 PPT 사용률이 높아서;;)
크리에이티브 커먼즈 라이선스
Creative Commons License

설정

트랙백

댓글

2.5 소켓 관련 UNIX 시스템 콜

2.5.1 signal()

▶ 유닉스 시스템에서 어떤 이벤트(event)가 발생하면 이것을 프로세스 사이에

알리는 수단으로 시그널이 사용된다.

표 2-3 소켓 관련 시그널 종류

SIGINT

인트럽트 키(Ctrl+C) 입력시 발생

SIGFPE

부동 소수점 연산 에러를 나타냄

SIGIO

I/O가 가능한 상태를 나타냄.

SIGURG

Out-of-band 데이터 도착과 같은 긴급한(urgent) 소켓 상태를 나타냄.

▶ 시그널이 발생하였을 때 유닉스 커널이 제공하는 디폴트 처리 내용 대신 다른

동작을 수행하도록 하려면 signal() 시스템 콜을 사용한다. 아래에서 signal

(SIGIO, sigio_func) 호출 후 SIGIO 시그널이 발생하면 sigio_func() 함수가 수행

된다.

      #include <signal.h>
      int sigio_func();               /* 사용자 정의 함수 선언 */
      main() {
      signal(SIGIO, sigio_func); /* 시그널 처리 함수 지정 */
      :
      }

        int sigio_func() {
        /* SIGIO 시그널 발생시 처리 내용 */
        }

▶ 어떤 시그널이 발생하였을 때 이를 단순히 무시하려면 다음과 같이 무시할 시

그널의 종류(예를 들면 SIGIO)를 지정하고 옵션으로 시그널 무시(SIG_IGN)를 선

택한다.

      signal(SIGIO, SIG_IGN);

■ signal_test.c

      카운터 프로그램이 실행되는 도중에 사용자가 Ctrl-C를 입력하면 시그널 SIGINT

      가 발생하는데, 이 때 프로그램이 종료되는 것이 아니라 my_signal()이라는 함수가

      호출된다.

      실행예

        > signal_test
        0
        1
        ^C
        Ctrl-C pressed.
        2
        3
        ^C
        Ctrl-C pressed.
        4
        ^C
        Ctrl-C pressed.
        >

      프로그램 리스트

      /*---------------------------------------
      파일명 : signal_test.c
      기 능 : signal() 시스템 콜 사용 예
      컴파일 : cc -o signal_test signal_test.c
      사용법 : signal_test
      ----------------------------------------*/
      #include <sys/types.h>
      #include <signal.h>
      #include <stdio.h>
      #include <unistd.h>
      int my_signal();    /* 새로운 시그널 처리 함수 선언 */
      int count = 0;       /* Ctrl-C 입력 횟수 카운터 */

      int main() {
      int i = 0;
      if(signal(SIGINT, my_signal) == SIG_ERR) {

      printf("singal() error\n");
      exit(0);
      }
      while(count < 3) {
      sleep(1);      /* 1초간 기다림 */
      printf("%d\n", i++);
      }
      }
      /* end of main  */

      /* 시그널 처리 함수 정의 */
      int my_signal() {
      printf("\nCtrl-C pressed.\n");
      count++;

      signal(SIGINT, my_signal);  /* signal()을 다시 호출함 */

      return 0;
      }

2.5.2 fork()

유닉스에서 프로세스는 fork()를 이용해서 자신과 똑같은 기능을 수행

하는 프로세스를 하나 복제할 수 있다.

두 프로세스는 프로그램 코드, 스택, 파일기술자, 소켓번호 등은 공유하나, 변

수들은 공유하지 않는다.

▶ fork()가 불리면 그 순간에 하나의 프로세스가 두 개의 프로세스로 되는데, 두

프로세스는 수행할 일을 구분하기 위하여 두 프로세스의 fork() 리턴문이 서로 다

르다는 것을 이용한다.

▶ 새로 생긴 자식 프로세스의 ID 번호(PID: Process Identification)는 부모 프로

세스의 PID와 구별된다.

▶ 부모 프로세스에게는 fork()의 리턴값으로 새로 생성된 자식 프로세스

의 PID가 리턴되며 자식 프로세스의 fork()의 리턴값은 0이 된다.

그림 2-14 fork()의 수행과정

▶ 프로세스의 작업 구분 예

        int  PID;
        PID = fork();
        if(PID == 0) {

        child_work(); /* 자식 프로세스용 코드 */
        } else {
        parent_work();/* 부모 프로세스용 코드 */
        }

■ fork_test.c

      부모와 자식 프로세스가 같은 이름의 변수를 각각 증가시키고 그 결과를 확인한

      다.

프로그램 리스트

/* ----------------------------------------------------
파일명 : fork_test.c
기 능 : fork() 시스템 콜 사용 예
컴파일 : cc -o fork_test fork_test.c
사용법 : fork_test
-----------------------------------------------------*/
#include <sys/types.h>
#include <unistd.h>
int global_var = 0;      /* 전역 변수 선언 */

int main(void) {
pid_t pid;
int    local_var = 0;     /* 지역 변수 선언 */
if((pid = fork()) < 0) {
printf("fork error\n");
exit(0);

/* 자식 프로세스 */
} else if (pid == 0) {
global_var++;
local_var++;
printf("CHILD - my pid is %d and parent's pid is %d\n", getpid(), getppid());
} else {

/* 부모 프로세스 */
sleep(2);/* 2초 쉰다 */
global_var += 5;
local_var += 5;
printf("PARENT - my pid is %d, child's pid is %d\n", getpid(), pid);
}
printf("\t global var : %d\n", global_var);
printf("\t local var : %d\n", local_var);
}

    실행예
    > fork_test
    CHILD - my pid is 12557 and parent's pid is 12556
    global var : 1
    local var : 1
    PARENT - my pid is 12556 and child's pid is 12557
    global var : 5
    local var : 5

    ▶ 여기서 부모 프로세스가 global_var과 local_var을 각각 5씩 증가시켰

    는데 6이 되지 않고 5가 되었다는 사실에 주목하자!! (파일이나 소켓은 공

    유하지만 변수는 공유하지 않는다)

    참조) http://cafe.naver.com/segame.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=94

크리에이티브 커먼즈 라이선스
Creative Commons License

설정

트랙백

댓글

다중 사용자의 connect 를 처리하기 위한 방법은 총 3가지의 방식으로 구분한다.

1. 유닉스 호환환경에서 제공하는 fork() 를 이용한 다중 프로세스
2. IO 멀티플렉싱을 이용한 다중 연결
3. 멀티 쓰레드를 이용한 다중 연결

3가지의 방법은 어떤 것이 좋다 나쁘다고 할 것이 아니고 적당한 상황하에서 적정한 기술을 이용하는 것이 관건이라고 할 수 있을 것이다.

1. fork() 이용 소스
[CODE] /** 멀티 프로세스를 이용한 에코 서버 프로그램 리눅스 환경하에서 컴파일 하세요. 출처 : 열혈강의 TCP/IP **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/socket.h> #define BUFFSIZE 30 void error_handling(const char* message); void z_handler(int sig); int main(int argc, char **argv) { int serv_sock; int clnt_sock; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; struct sigaction act; int addr_size, str_len, state; pid_t pid; char message[BUFFSIZE]; if(argc!=2) { printf("USAGE: %s <port>\n", argv[0]); exit(1); } act.sa_handler = z_handler; sigemptyset(&act.sa_mask); act.sa_flags=0; state = sigaction(SIGCHLD, &act, 0); if (state != 0) { puts("sigaction() error!"); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) error_handling("bind() error"); if(listen(serv_sock, 5) == -1) error_handling("listen() error"); while(1) { addr_size = sizeof(clnt_addr); clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &addr_size); if (clnt_sock == -1) continue; if ((pid ==fork()) == -1) {   close(clnt_sock);   continue; } else if (pid >0) {   puts("connection success");   close("clnt_sock");   continue; } else {   close(serv_sock);   while( (str_len = read(clnt_sock, message, BUFFSIZE)) != 0) {   write(clnt_sock, message, str_len);   write(1, message, str_len);   }   puts("connection closing");   close(clnt_sock);   exit(0); } } return 0; } void z_handler(int sig) { pid_t pid; int rtn; pid = waitpid(-1, &rtn, WNOHANG); printf("zombi process ID: %d\n", pid); printf("return data : %d\n", WEXITSTATUS(rtn)); } void error_handling(const char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } [/CODE]

2. select 이용 소스
[CODE] /** IO 멀티플렉싱을 이용한 에코 서버 프로그램 리눅스 환경하에서 컴파일 하세요. 출처 : 열혈강의 TCP/IP **/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/time.h> #include <netinet/in.h> #define BUFFSIZE 100 void error_handling(const char* message); int main(int argc, char **argv) { int serv_sock; struct sockaddr_in serv_addr; fd_set reads, temps; int fd_max; char message[BUFFSIZE]; int str_len; struct timeval timeout; if (argc != 2) { printf("USAGE : %s <port>\n", argv[0]); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(atoi(argv[1])); if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) error_handling("bind() error"); if (listen(serv_sock, 5) == -1) error_handling("listen() error"); FD_ZERO(&reads); FD_SET(serv_sock, &reads); fd_max = serv_sock; while (1) { int fd, str_len; int clnt_sock, clnt_len; struct sockaddr_in clnt_addr; temps = reads; timeout.tv_sec = 5; timeout.tv_usec = 0; if (select(fd_max + 1, &temps, 0, 0, &timeout) == -1)   error_handling("select() error"); for (fd = 0; fd < fd_max+1; fd++) {   if(fd == serv_sock) {   clnt_len = sizeof(clnt_addr);   clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_len);   FD_SET(clnt_sock, &reads);   if (fd_max < clnt_sock)   fd_max = clnt_sock;   printf("client connection : file descriptor %d\n", clnt_sock);   }   else {   str_len = read(fd, message, BUFFSIZE);   if (str_len == 0) {   FD_CLR(fd, &reads);   close(fd);   printf("client closing: file descriptor %d\n", fd);     }   else {   write(fd, message, str_len);   }   } } } } void error_handling(const char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } [/CODE]
크리에이티브 커먼즈 라이선스
Creative Commons License

설정

트랙백

댓글

지난 반년간은 학기중의 프로젝트 및 아르바이트가 MFC 에 종속된 것들이 많아서 리눅스를 안쓰느니만 못한 상황이었다.
그러던 것이 이번 학기에 들어오면서 완전히 역전되었다.

주요 프로젝트인 PL, 네트워크의 프로젝트가 순수 ANSI C 를 기반으로 작성하기 때문인데,...

덕분에 윈도우 플랫폼에 종속된 프로그램을 하지 않아도 되게되었다.

그래서 다시 리눅스로 복귀

이번 학기에는 리눅스에서 P2P를 이용해서 뭔가를 만들어 볼 생각이다.

나도 먼가 하나 만들어 봐야하겠다라는 생각이 들어서 랄까?
  
크리에이티브 커먼즈 라이선스
Creative Commons License

설정

트랙백

댓글