시리얼 프로그램 질문입니다

nicelyj의 이미지

serial howto문서를 기본으로 해서 공부를 하고 있는데
잘 이해가 되지 않는 것들이 있어서 질문 올립니다

저 같은 경우 하나의 호스트 pc와 시리얼 케이블로 연결된 임베디드
보드사이에 시리얼 통신을 하려고 하거든요
serial howto문서에 나온 걸 토대로 컴파일 해서
임베드디 보드에서 실행을 시키면 이상하게 동작 합니다
호스트 pc에서 컴파일 한것과는 전혀 다르게..
아예 키가 먹히지 않습니다
또 호스트 pc에서 실행시키면 mimicom을 실행시킨 창이 동작을 멈추어버립니다
minicom이 동작을 멈추게 되는 건 호스트 pc에서 실행시킨 프로그램이
시리얼 포트에 무언가를 쓰기위해 가지고 있기 때문이라고 생각하는데
그것이 맞는지는 모르겠습니다
그걸 확인하기 위해서 보드쪽에서 read(fd, &ch, 1);
이런 식으로 한글자씩 보내지는 문자를 받으려고도 해봤지만
이것 역시도 잘 동작 하지 않네요..

howto를 봐도 답답하기만 하고 그렇네요

혹시 리눅스 pc에서 pc나
pc에서 보드로의 시리얼 통신에 대한 소스를 가지고 계신 분 있으시다면
좀 추천해주셨으면 합니다
mimiterm.c라는 소스도 봐봤지만
이것역시도 큰 도움을 안되더라구요
여기에 나와있는 시리얼에 대한 질문들을 보면
다 비슷비슷한 내용들인 것 같고

이전에 저처럼 시리얼 통신 프로그램때문에 고생하신 분들있으시다면
좀 도와주시기 바랍니다..

읽어주셔서 감사합니다.

lovemyin의 이미지

시리얼 통신을 하기위해
baudrate, data bit, stop bit, parity, flow control 등을 세팅하는데 그부분에서 문제가 있을듯 하네요
HowTo 문서에 있는 내용을 참조하면 임베디드 환경에서도 테스트 됩니다.
이건 확실하니 그부분을 수정해 보세요

/***************************************************
* 가장 심플한 것이 가장 아름다운 것이다.
***************************************************/

mooore의 이미지

구성이 잘 이해가 안가는군요.

이미 콘솔로 사용하고 있는 보드의 시리얼 포트를 이용해서 데이터를 송/수신하시겠다는 건가요?
PC랑 보드의 콘솔 포트가 이미 연결되어 있고 미니콤과 같은 애플리케이션이 수행중이라면 당연히 통신이 안됩니다. 이미 할당이 되었기 때문입니다.
키가 안먹는다는 것도 이런 상황일 수 있습니다. 즉 이미 콘솔로 사용되고 있던 상태에서 그 시리얼 포트를 사용하겠다고 명령을 내리면서 콘솔이 먹통이 되고 따라서 키가 안먹을 수 있습니다.

만약 콘솔 포트를 일반적인 시리얼 포트로 사용하실려고 하면 보드의 초기화 스크립트를 약간 변경하셔야 합니다.(물론 콘솔을 사용하지 못하기 때문에 다른 방법으로 보드에 접근할 수 있어야 합니다. 텔넷등)
보통 /etc/inittab 파일에서 콘솔로 사용하겠다고 설정하는 부분을 주석처리하면 됩니다.

하드웨어 연결 상태를 확인하시고 Serial HOWTO를 이용해서 프로그램 작성하시면 문제없을 듯합니다.

잘 모르시겠다면 구성도와 작성하신 프로그램을 같이 올려주시면 많은 분들께서 도움을 주실 겁니다.

별은 바라보는 자에게 빛을 준다.

nicelyj의 이미지

님께서 말씀하신 것 처럼 시리얼이 이미 콘솔로 할당 되어 있기 때문에

안되는 것 같은데

리눅스 호스트에서 보드의 부팅을 시키거나

어떠한 명령을 내리는 건 모두 미니콤을 이용해서 했었거든요

하지만 님께서 말씀하신 것처럼 하려면

미니콤이 아닌 다른 것을 이용해서 보드를 통제할 수 있어야 한다고 하시는 것

같은데 제 말이 맞는지요 (telnet등을 이용해서)

현제는 telnet등이 보드에 올라가 있지 않으니..

zImage를 만들때 그런 것들을 포함시켜서 만들고

그걸 보드에 올려야 하는 건가요??

좀 자세하세 이것 저것 적어주셨으면 합니다..

제 질문이 좀 두서없다는 건 알고 있습니다

하지만 아는 것이 없기에 질문조차 이렇게 되는 것을 이해해 주셨으면 합니다

제가 보드에서 동작시켰었던 소스를 올립니다

  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <termios.h>
  #include <stdio.h>

  /* Baudrate 설정은 <asm/termbits.h>에 정의되어 있다.
  /* <asm/termbits.h>는 <termios.h>에서 include된다. */
  #define BAUDRATE B115200
  /* 여기의 포트 장치 파일을 바꾼다. COM1="/dev/ttyS1, COM2="/dev/ttyS2 */
  #define MODEMDEVICE "/dev/ttyS0"
  #define _POSIX_SOURCE 1 /* POSIX 호환 소스 */

  #define FALSE 0
  #define TRUE 1

  volatile int STOP=FALSE;

  int main()
  {
    int fd,c, res;
    char ch;
    struct termios oldtio,newtio;
    char buf[80];// = "nicelee";
    char red[80];

    printf("hello world\n");

  /* 읽기/쓰기 모드로 모뎀 장치를 연다.(O_RDWR)
     데이터 전송 시에 <CTRL>-C 문자가 오면 프로그램이 종료되지 않도록
     하기 위해 controlling tty가 안되도록 한다.(O_NOCTTY)
  */
   if ((fd = open(MODEMDEVICE, O_RDWR)) > 0)// | O_NOCTTY );
   {
	   printf("file descripter is %d ---\n\r", fd);
   }
   else if (fd <0) 
   {
	   printf("MODEMDEVICE ERROR!! DEVICE DECRIPTER IS --> %d     ---\n\r", fd);
	   perror(MODEMDEVICE); 
	   exit(1); 
   }

   tcgetattr(fd,&oldtio); /* save current serial port settings */
   bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */

  /*
    BAUDRATE: 전송 속도. cfsetispeed() 및 cfsetospeed() 함수로도 세팅 가능
    CRTSCTS : 하드웨어 흐름 제어. (시리얼 케이블이 모든 핀에 연결되어 있는
              경우만 사용하도록 한다. Serial-HOWTO의 7장을 참조할 것.)
    CS8     : 8N1 (8bit, no parity, 1 stopbit)
    CLOCAL  : Local connection. 모뎀 제어를 하지 않는다.
    CREAD   : 문자 수신을 가능하게 한다.
  */
   newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

  /*
   IGNPAR   : Parity 에러가 있는 문자 바이트를 무시한다.
   ICRNL    : CR 문자를 NL 문자로 변환 처리한다. (이 설정을 안하면 다른
              컴퓨터는 CR 문자를 한 줄의 종료문자로 인식하지 않을 수 있다.)
    otherwise make device raw (no other input processing)
  */
   newtio.c_iflag = IGNPAR | ICRNL;

  /*
   Raw output.
  */
   newtio.c_oflag = 0;
  /*
   ICANON   : canonical 입력을 가능하게 한다.
    disable all echo functionality, and don't send signals to calling program
  */
   newtio.c_lflag = ICANON;

  /*
    모든 제어 문자들을 초기화한다.
    디폴트 값은 <termios.h> 헤더 파일에서 찾을 수 있다. 여기 comment에도
    추가로 달아놓았다.
  */
   newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */
   newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
   newtio.c_cc[VERASE]   = 0;     /* del */
   newtio.c_cc[VKILL]    = 0;     /* @ */
   newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
   newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
   newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
   newtio.c_cc[VSWTC]    = 0;     /* '\0' */
   newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */
   newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
   newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
   newtio.c_cc[VEOL]     = 0;     /* '\0' */
   newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
   newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
   newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
   newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
   newtio.c_cc[VEOL2]    = 0;     /* '\0' */

  /*
    이제 modem 라인을 초기화하고 포트 세팅을 마친다.
  */
   tcflush(fd, TCIFLUSH);
   tcsetattr(fd,TCSANOW,&newtio);

  /*
    터미널 세팅이 끝났고, 이제는 입력을 처리한다.
    이 예제에서는 한 줄의 맨 첫 문자를 'z'로 했을 때 프로그램을
    종료한다.
  */


   while (STOP==FALSE) 
   {     
	/* 종료 조건(STOP==TRUE)가 될 때까지 루프 */
   /* read()는 라인 종료 문자가 나올 때까지 255 문자를 넘어가더라도
      block 된다. read 하고자 하는 문자 개수가 입력 가능한 문자 개수보다
      적은 경우에는 또 한번의 read를 하여 나머지를 읽어낼 수 있다.
      res는 read에 의해서 실제로 읽혀진 문자의 개수를 갖게 된다. */
      
	   		/* set end of string, so we can printf */
	gets(red);
	puts("*____________*");
	printf("\r");
	puts(red);
	printf("\r");
      res = write(fd, red, strlen(red)+1);
      printf("send %d byte \n\r", res);
      
      printf("send : %s  byte : %d\n\r", red, res);
      
      if (red[0]=='q') 
      {	      
	      printf("bye!!!\n\r");
	      STOP=TRUE;
      }
      puts("hi");
      printf("\r");
   }
   /* restore the old port settings */
   tcsetattr(fd,TCSANOW,&oldtio);

   printf("bye!!!\n\r");

   return 0;
  }
mooore의 이미지

nicelyj wrote:
님께서 말씀하신 것 처럼 시리얼이 이미 콘솔로 할당 되어 있기 때문에

안되는 것 같은데

리눅스 호스트에서 보드의 부팅을 시키거나

어떠한 명령을 내리는 건 모두 미니콤을 이용해서 했었거든요

하지만 님께서 말씀하신 것처럼 하려면

미니콤이 아닌 다른 것을 이용해서 보드를 통제할 수 있어야 한다고 하시는 것

같은데 제 말이 맞는지요 (telnet등을 이용해서)

현제는 telnet등이 보드에 올라가 있지 않으니..

zImage를 만들때 그런 것들을 포함시켜서 만들고

그걸 보드에 올려야 하는 건가요??

좀 자세하세 이것 저것 적어주셨으면 합니다..

제 질문이 좀 두서없다는 건 알고 있습니다

하지만 아는 것이 없기에 질문조차 이렇게 되는 것을 이해해 주셨으면 합니다

제가 보드에서 동작시켰었던 소스를 올립니다

  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <termios.h>
  #include <stdio.h>

  /* Baudrate 설정은 <asm/termbits.h>에 정의되어 있다.
  /* <asm/termbits.h>는 <termios.h>에서 include된다. */
  #define BAUDRATE B115200
  /* 여기의 포트 장치 파일을 바꾼다. COM1="/dev/ttyS1, COM2="/dev/ttyS2 */
  #define MODEMDEVICE "/dev/ttyS0"
  #define _POSIX_SOURCE 1 /* POSIX 호환 소스 */

  #define FALSE 0
  #define TRUE 1

  volatile int STOP=FALSE;

  int main()
  {
    int fd,c, res;
    char ch;
    struct termios oldtio,newtio;
    char buf[80];// = "nicelee";
    char red[80];

    printf("hello world\n");

  /* 읽기/쓰기 모드로 모뎀 장치를 연다.(O_RDWR)
     데이터 전송 시에 <CTRL>-C 문자가 오면 프로그램이 종료되지 않도록
     하기 위해 controlling tty가 안되도록 한다.(O_NOCTTY)
  */
   if ((fd = open(MODEMDEVICE, O_RDWR)) > 0)// | O_NOCTTY );
   {
	   printf("file descripter is %d ---\n\r", fd);
   }
   else if (fd <0) 
   {
	   printf("MODEMDEVICE ERROR!! DEVICE DECRIPTER IS --> %d     ---\n\r", fd);
	   perror(MODEMDEVICE); 
	   exit(1); 
   }

   tcgetattr(fd,&oldtio); /* save current serial port settings */
   bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */

  /*
    BAUDRATE: 전송 속도. cfsetispeed() 및 cfsetospeed() 함수로도 세팅 가능
    CRTSCTS : 하드웨어 흐름 제어. (시리얼 케이블이 모든 핀에 연결되어 있는
              경우만 사용하도록 한다. Serial-HOWTO의 7장을 참조할 것.)
    CS8     : 8N1 (8bit, no parity, 1 stopbit)
    CLOCAL  : Local connection. 모뎀 제어를 하지 않는다.
    CREAD   : 문자 수신을 가능하게 한다.
  */
   newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

  /*
   IGNPAR   : Parity 에러가 있는 문자 바이트를 무시한다.
   ICRNL    : CR 문자를 NL 문자로 변환 처리한다. (이 설정을 안하면 다른
              컴퓨터는 CR 문자를 한 줄의 종료문자로 인식하지 않을 수 있다.)
    otherwise make device raw (no other input processing)
  */
   newtio.c_iflag = IGNPAR | ICRNL;

  /*
   Raw output.
  */
   newtio.c_oflag = 0;
  /*
   ICANON   : canonical 입력을 가능하게 한다.
    disable all echo functionality, and don't send signals to calling program
  */
   newtio.c_lflag = ICANON;

  /*
    모든 제어 문자들을 초기화한다.
    디폴트 값은 <termios.h> 헤더 파일에서 찾을 수 있다. 여기 comment에도
    추가로 달아놓았다.
  */
   newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */
   newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
   newtio.c_cc[VERASE]   = 0;     /* del */
   newtio.c_cc[VKILL]    = 0;     /* @ */
   newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
   newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
   newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
   newtio.c_cc[VSWTC]    = 0;     /* '\0' */
   newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */
   newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
   newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
   newtio.c_cc[VEOL]     = 0;     /* '\0' */
   newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
   newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
   newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
   newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
   newtio.c_cc[VEOL2]    = 0;     /* '\0' */

  /*
    이제 modem 라인을 초기화하고 포트 세팅을 마친다.
  */
   tcflush(fd, TCIFLUSH);
   tcsetattr(fd,TCSANOW,&newtio);

  /*
    터미널 세팅이 끝났고, 이제는 입력을 처리한다.
    이 예제에서는 한 줄의 맨 첫 문자를 'z'로 했을 때 프로그램을
    종료한다.
  */


   while (STOP==FALSE) 
   {     
	/* 종료 조건(STOP==TRUE)가 될 때까지 루프 */
   /* read()는 라인 종료 문자가 나올 때까지 255 문자를 넘어가더라도
      block 된다. read 하고자 하는 문자 개수가 입력 가능한 문자 개수보다
      적은 경우에는 또 한번의 read를 하여 나머지를 읽어낼 수 있다.
      res는 read에 의해서 실제로 읽혀진 문자의 개수를 갖게 된다. */
      
	   		/* set end of string, so we can printf */
	gets(red);
	puts("*____________*");
	printf("\r");
	puts(red);
	printf("\r");
      res = write(fd, red, strlen(red)+1);
      printf("send %d byte \n\r", res);
      
      printf("send : %s  byte : %d\n\r", red, res);
      
      if (red[0]=='q') 
      {	      
	      printf("bye!!!\n\r");
	      STOP=TRUE;
      }
      puts("hi");
      printf("\r");
   }
   /* restore the old port settings */
   tcsetattr(fd,TCSANOW,&oldtio);

   printf("bye!!!\n\r");

   return 0;
  }

소스에는 별 이상이 없는 것 같습니다. serial HOWTO에 있는 소스의 모습을 가지고 있는 것 같네요.

콘솔은 사용자와 시스템 사이의 논리적인 연결 수단입니다.
물리적으로는 지금 사용하시는 것 처럼 시리얼 포트가 될 수도 있고 네트워크 포트가 될 수도 있겠죠. 물론 시리얼 포트를 사용한 콘솔이 역사적으로도 훨씬 정확하긴 합니다만.

시리얼 포트 자체는 커널 상에서 지원하는 것입니다. 콘솔은 이러한 시리얼 포트를 단순한 데이터의 주고 받음이 아니라 특정한 용도로 사용하겠다는 의미가 됩니다.
따라서 이미 콘솔로 사용하고 있는 시리얼 포트를 다른 애플리케이션에서 재사용한다면 할당이 제대로 되지도 않을 뿐더러 설령 할당이 제대로 되었다고 하더라도 동작에 대한 보장을 할 수 없습니다.

구성하신 임베디드 보드가 어떤 용도로 사용되는 지는 모르겠지만 보통 임베디드 보드에는 이더넷 트랜시버를 넣어서 개발합니다. 아니면 시리얼 포트를 2개 둬서 하나는 콘솔로, 하나는 일반적인 시리얼 포트로 사용할 수 있겠죠.

제가 말씀드린 것처럼 텔넷 등을 이용해서 보드를 제어할려고 한다면 당연히 네트워크 기능이 추가되어 있어야 합니다. 물리적으로는 이더넷 트랜시버가 CPU와 붙어서 제대로 동작해야 할 테고 소프트웨어적으로는 해당 디바이스 드라이버가 커널에 구현되고 이더넷 관련 프로그램들(ifconfig나 텔넷 데몬같은)이 루트 파일 시스템에 구축되어 있어야 합니다.

다시 말씀드리자면 보드가 이더넷이 되는 상태이고 텔넷이나 ssh 서버등의 역할을 수행할 수 있으면 굳이 미니콤을 통해서 콘솔로 접근할 필요없이 네트워크를 이용해서 보드에 로긴/사용할 수 있다는 뜻입니다.
이렇게 되면 콘솔로 사용하던 시리얼 포트를 일반적인 RS-232C 통신을 위한 포트로 사용할 수 있습니다.(물론 이를 위해서 inittab 등에서 적절히 설정을 하셔야 합니다.)

ps. 휴가 다녀오느라고 답변이 좀 늦었습니다. 그새 해결하셨다면 다행이구요.

별은 바라보는 자에게 빛을 준다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.