펌웨어 RTOS 책을 썼습니다.

나빌레라의 이미지

10년만에 책을 한 권 썼습니다.

10년전에 KLDP에 쓴 글을 바탕으로 책을 냈었습니다.

이 책이죠. 아직도 절판되지 않고 팔리고 있습니다. 10년동안 꾸준히 일정 권수만큼 매년 팔리는 것 보면 아마도 어딘가에서 교재로 쓰고 있지 않나 하는 합리적 의심을 하고 있습니다.

그러는 동안 꾸역꾸역 시간은 흘렀습니다. 저도 어느덧 10년 넘는 경력의 개발자가 되었고 책도 나온지 10년이나 된 오래된 책이 되어 버렸습니다. 물론 10년이 지나서 봐도 여전히 훌륭한 책입니다. 그래도 10년이나 지났으니 새 책을 써야 겠다는 생각이 들었습니다. 10년간 바뀐 개발 환경 그리고 제가 10년간 현업에서 얻은 경험을 살짝 녹여서 책을 썼습니다.

이 책입니다.

다 쓰고 보니 오히려 내용의 난이도는 전작보다 쉬워졌습니다. 역시 경력이 쌓이니 같은 내용도 더 쉽게 설명하는 방법을 터득했나봅니다. 그리고 전작에서 실물 하드웨어 개발보드를 타겟보드로 삼아 내용을 진행했던 것과 달리 이번책에서는 전부다 QEMU에서 작업합니다. (QEMU도 10년동안 프로젝트가 안망하고 계속 발전했더군요. 이제는 완전히 메이저 오픈소스 프로젝트중 하나가 된듯 합니다.) 그래서 책만 사서 열심히 따라하면 책의 내용을 모두 실습해 볼 수 있습니다. 맞습니다. 돈을 아낄 수 있습니다.

이 책도 앞으로 한 10년간 절판없이 생존하길 바라며..
그 10년후에 저도 계속 이 바닥에서 생존하길 바라며..

많이 사 주세요~

File attachments: 
첨부파일 크기
Image icon EmbeddedOSProjectBook.jpeg107.61 KB
Image icon L.jpg92.29 KB

댓글

세벌의 이미지

reistrem의 이미지

주문했는데요.
오늘 오겠네요!!!
야호!!!

나빌레라의 이미지

참! 이 게시물 댓글로 책 내용에 대한 질문을 직접 받고 답변 드립니다.
지난 책 냈을 때 보니 책 출간하고도 한 3년 정도까지 출판사 통해서 질문이 들어오더라구요.

<임베디드 OS 개발 프로젝트>를 읽으면서 궁금한점이 있으면 여기에 댓글 달아 주세요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

김진희(IDT)의 이미지

책을 구입을 하여 차근 차근 따려 하려고 합니다.(리눅스 계열은 처음입니다.)
리눅스 설치는 워낙에 많은 자료가 있어 문제 없이 진행이 되었습니다.

리눅스 계념이 예전에 DOS 처럼 터미널을 이용한 프로그램 인거 같습니다.

아직 생소한 명령어에 이해가 가지 않지만 그럭저럭 찾아보면서 하고 있습니다.

현재 3.3 QEMU에서 실행을 하고 있습니다. 우분투버전(18.04.3) 입니다.
arm-none-eabi-gdb 를 하려는대 에러가 납니다. 책에도 같은 내용입니다.

그래서 sudo apt install gdb-arm-none-eabi 를 터미널에 입력하면
패키지를 찾을수 없다고 합니다.

우분투 버젼이 높아서 그렇다고 하던데 그렇다고 우분투 버전을
내려서 할수도 없고 책에 우분투 버젼 관련 내용이 없어서 최선 버젼을 설치를 했는데
우분터 버젼을 제시해주시면 차레대로 나갈수 있을거 같습니다.

나빌레라의 이미지

저는 리눅스 민트를 쓰고 있습니다. 최신 버전이긴 한데 리눅스 민트가 아직 우분투 리눅스 최신버전을 적용하지 않았거나 gdb-arm-none-eabi 패키지는 여전히 지원하는 듯합니다. 왜냐면 제 시스템에서는 검색이 되거든요.

아무튼 구글로 검색해 보니

https://askubuntu.com/questions/1031103/how-to-install-gdb-arm-none-eabi-on-ubuntu-18-04

이런 게시물이 나옵니다. 내용을 보니

sudo apt install gdb-multiarch

명령으로 gdb-multiarch 패키지를 설치해서 그냥 gdb를 쓰면 되는 듯 합니다. gdb가 버전이 올라가면서 이제 자체적으로 여러 아키텍처를 지원하는 듯 하네요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

diet84의 이미지

확인한 내용 감사합니다.
제가 이해 한것은 이것 입니다.
현재 우분투 18.04.3 에서는 gdb-arm-none-eabi 설치 가 안된다.
그래서 그 대체인(상위버젼?) gdb-multiarch 설치를 한다.

그러면 책 내용의 모든 내용은 gdb-arm-none-eabi -> gdb-multiarch 이걸로 대체 가능하다 라는 결론을
얻었습니다.

우분트를 처음 접하는 거라 어려운게 많아 책은 초급자가 보기엔 어려운게 많은거 같습니다.

또한 책 내용중에

3장 28페이지 make -> 1회성 다시 빌드 하려면 clean 명령어 필수
make gdb -> makefile 파일 내용중 gdb-arm-none-eabi -> gdb-multiarch 교체로 해결

그래서 28장을 천천히 진행을 해보면 이렇습니다.
\ make -> 잘 됩니다.
\ make debug -> 잘됩니다. 그리고 창이 하나 뜹니다. 멈춤 검은색창
여기서 문제 입니다. 디버그 내용을 보면 타켓 보드를 띠어 놓는 현상 같은 걸로 보입니다.
그러면 터미널 창은 입력 하는 모양이 아니라 stop 영향으로

\ -> 아니라 그림처럼

\ make debug
생략
pulseaudio: Reason: Invalid argument
|(커서깜박 깜박)

즉 \ 명령어 입력 모드가 아닌 그냥 글자만 입력이 되는 형태가 진행이 되어서
다음 명령어인 make gdb 가 실행이 되지 않습니다. 그렇다고 창을 닫으면(검은색창)

\ 입력모드 가능
gdb 명령어 에서 targer remote:1234 는 연결시간 초과
gdb file build/navilos.axf -> 정상
gdb list -> 정상
gdb info register
The program has no regosters now.
라는 결과가 초래 됩니다. 아마 target remote 가 되면 해결이 될거 같은데 막히는 부분이 많은거 같습니다.

진행불가 jpg / 검은창 닫으면 가능2 / gdb 상황 그림파일 올려 봅니다.
감사합니다.

댓글 첨부 파일: 
첨부파일 크기
Image icon 진행불가.png121.65 KB
Image icon 검은창을 닫으면 가능2.png137.97 KB
Image icon gdb 상황.png138.83 KB
나빌레라의 이미지

터미널 두 개 띄워서 작업하세요.

사실 당연한 건데 터미널 환경(리눅스든 윈도우든) 처음 써 보는 분에겐 어려울 수도 있겠군요.

겪고 계신 문제는 구글 검색하면 쉽게 해결 가능합니다.
검색을 생활화 합시다..

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

choi7의 이미지

우선 너무나도 좋은 책 감사합니다. 마침 RTOS에 대하여 이론적으로 학교에서 공부하고 실제로 만져볼 수 있는 기회가 된다는게 너무나도 감사드립니다.
저는 우분투 16.04 LTS버전에서 편집기로 작업중입니다. 4.4절(p.51)에 stdint.h파일을 include디렉토리에 따로 만드셨는데 stdint.h파일을 어떻게 만드셨는지 궁금합니다. 리눅스에서 기본으로 제공하는 include 디렉토리에는 stdint.h을 복사하여 제가 작업중인 include 디렉토리에 추가했는데 stdint.h파일이 다른 헤더파일들을 include하고 있어서 오류가 나는 것 같은데 해결 방법을 잘 모르겠습니다.

댓글 첨부 파일: 
첨부파일 크기
Image icon 스크린샷, 2020-02-14 14-35-55.png237.17 KB
나빌레라의 이미지

arm-gcc에 있는 stdint.h 파일에서 필요한 내용만 가져다가 새로 만들었습니다.

가장 쉬운 방법은 책에 적어 놓은 github 저장소에서 나빌눅스 소스 코드 파일을 받아서 사용하시는 겁니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

choi7의 이미지

https://github.com/navilera/Navilos 여기서 제가 stdint.h파일이 있는지 찾아 봤지만 찾지 못했습니다 ㅠ.ㅠ

그리고 4장 맨 앞에 공유해 놓으신 코드 링크 해놓으신 명령어도 stdint.h파일은 찾지 못했습니다.

혹시 가능하시면 선생님께서 새로 만드신 stdint.h파일을 공유 받을 수 있을까요??

나빌레라의 이미지

없을리가 있나요~ㅎㅎㅎ
자세히 찾아보세요. 100% 있습니다.
그냥 링크 달아드리고 싶으나,
이런것 찾아보는것도 공부라 생각되어
확신만 드립니다.
파일이 있으니 찾아보세요.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

choi7의 이미지

말씀하신대로 제가 잘못 찾았던거였던군요.. stdint.h파일은 찾았습니다.

그러나 main 함수를 찾지 못하는 것 같습니다. undefined reference to main error가 뜹니다..

구글링 해본 결과 오타 혹은 gcc옵션실수 나 함수의 공개 범위문제라고 어떤문제일까요?

댓글 첨부 파일: 
첨부파일 크기
Image icon Makefile.png303.99 KB
Image icon Main.png188.54 KB
Image icon Entry.png289.45 KB
Image icon error.png233.54 KB
choi7의 이미지

제가 바보같은 오류를 범했더군요 ㅠㅠ 이제부터 더 깊게 생각해보겠습니다! (ㅡㅡ)

손혁준의 이미지

출판사로 내용을 보냈는데, 여기를 앞으로 이용하라고 해서 일단 다시 올립니다.

책을 사서 읽어 정리가 잘되어 책에 대해서 대단히 만족합니다.

몇가지 질문과 제가 찾은 오타 등 정리해서 올립니다.

일단 전체적으로 정리가 잘된 책이라고 생각합니다. 저자에게 진심으로 감사드립니다.

첫째, 모든 코드에서 struct, union, enum typedef할 때 보면
typedef struct queue_t {
....
....
} queue_t
같은 코딩스타일을 사용하는데, 저는 typedef struct queue_t queue_t 이런 코딩스타일을 처음 보아서 왜 이런 스타일을 일관되게 사용하시는지 궁금합니다.

P136

코드 8.1:태스크 컨트롤 블록과 관련 함수 정의 task.c -> task.h로 변경이 필요함.

P148

if (pNextTcb != pNextTcb) -> if (pNextTcb != sCurrent )

P163 상단에 문장 의미를 좀 더 명확하게 해주었으면 함.

지금까지의 컨텍스트는 모두 사라지고 태스크의 컨텍스트를 ARM 코어에 덮어 씁니다.

>> 지금까지의 (ARM Core에서의) 컨텍스트는 모두 사라지고 (스택에 있는) 태스크의 컨텍스를 ARM 코어에 덮어 씁니다.

p170 상단의 문장 의미를 좀 더 명확하게 해주었으면 함.

그리고 개별 프로그램의 버튼 클릭 이벤트 함수가 태스크에 있는 이벤트 핸들러 함수와 같은 역활을 한다.

>> 그리고 (MS윈도우즈에서의) 개별 프로그램의 버튼 클릭 이벤트 함수가 (우리가 애기하고 있는) 태스크에있는 이벤트 핸들러 함수와 같은 역할을 합니다.

p178 하단

만약 기다리는 이벤트가 커널에 없으면 Kernel_yield() 커널 API를 호출해서 다른 태스크로 컨텍스트를 넘깁니다.

>> 컨텍스트를 넘긴다는 말이 좀 모호하다. 컨텍스트를 넘긴다는 것이 문맥교환(컨텍스트 스위칭)이 이루어진 다는 말 또는 CPU를 넘긴다(양보한다)

"컨텍스트를 넘긴다"는 말이 여러 군데서 사용되는데 의미가 모호함

p184 상단

비트맵으로 설계되어 있으므로 논리 OR 연산자(|)로 원하는

>> 비트 OR 연산자(|)

p193 코드 12.2 7번째 라인

KernelCirQ_t sMsgQ[KernelMsgQ_Num];

>> 이 책에서 일관되게 사용한 코딩 스타일을 보면 변수에 s가 붙으면 static 변수 였는데 그렇다면

static KernelCirQ_t sMsgQ[KernelMsgQ_Num];

p208

이 페이지에 synch.h헤더 파일이 있어야 할 것 같은데, 바로 코드 13.1 세마포어 구현 synch.c가 나옴

p219 코드 11.3에 나오는 synch.h 파일 삽입이 필요해 보임

p209 하단

당연히 이 값이 2면 컨텍스트 두 개까지, 3이면 컨택스트 세 개까지 진입 가능합니다.

>> 여기서 컨텍스트가 태스크를 의미하는 건가요? 모호한 것 같아 보임

p210 하단

kernel_yield() 함수를 호출해야만 스케줄링이 동작하므로 동기화

>> 명확한 표현을 위해 kernel_yield() 함수를 명시적으로 호출해야만

p219 코드 13.9 첫번째 라인

KernelMutext_t sMutx;

>> 이 책에서 일관되게 사용한 코딩 스타일을 보면 변수에 s가 붙으면 static 변수 였는데 그렇다면

static KernelMutex_t sMutex;


다시 한번 훌륭한 책에 감사드립니다.

나빌레라의 이미지

책을 그야말로 정독해 주셔서 감사합니다.

그럼 아래 답변입니다..

첫째, 모든 코드에서 struct, union, enum typedef할 때 보면 typedef struct queue_t { .... .... } queue_t 같은 코딩스타일을 사용하는데, 저는 typedef struct queue_t queue_t 이런 코딩스타일을 처음 보아서 왜 이런 스타일을 일관되게 사용하시는지 궁금합니다.

해당 코딩 스타일은 매우 일반적이고 많이 사용하는 코딩스타일입니다. 대부분 타이핑 길게하기 싫어서 그렇죠

P136

코드 8.1:태스크 컨트롤 블록과 관련 함수 정의 task.c -> task.h로 변경이 필요함.

감사합니다. 출판사에 전달하겠습니다.

P148

if (pNextTcb != pNextTcb) -> if (pNextTcb != sCurrent )

감사합니다. 출판사에 전달하겠습니다.

P163 상단에 문장 의미를 좀 더 명확하게 해주었으면 함.

지금까지의 컨텍스트는 모두 사라지고 태스크의 컨텍스트를 ARM 코어에 덮어 씁니다.

지금까지의 (ARM Core에서의) 컨텍스트는 모두 사라지고 (스택에 있는) 태스크의 컨텍스를 ARM 코어에 덮어 씁니다.

감사합니다. 출판사에 전달하겠습니다.

p170 상단의 문장 의미를 좀 더 명확하게 해주었으면 함.

그리고 개별 프로그램의 버튼 클릭 이벤트 함수가 태스크에 있는 이벤트 핸들러 함수와 같은 역활을 한다.

그리고 (MS윈도우즈에서의) 개별 프로그램의 버튼 클릭 이벤트 함수가 (우리가 애기하고 있는) 태스크에있는 이벤트 핸들러 함수와 같은 역할을 합니다.

감사합니다. 제안해 주신 문장을 참고해서 해당 문장은 새로 쓰는게 나을것 같습니다.

p178 하단

만약 기다리는 이벤트가 커널에 없으면 Kernel_yield() 커널 API를 호출해서 다른 태스크로 컨텍스트를 넘깁니다.

컨텍스트를 넘긴다는 말이 좀 모호하다. 컨텍스트를 넘긴다는 것이 문맥교환(컨텍스트 스위칭)이 이루어진 다는 말 또는 CPU를 넘긴다(양보한다)

"컨텍스트를 넘긴다"는 말이 여러 군데서 사용되는데 의미가 모호함

모호하지 않습니다. 정말 컨택스트를 넘기는 것이니까요.

p184 상단

비트맵으로 설계되어 있으므로 논리 OR 연산자(|)로 원하는

비트 OR 연산자(|)

감사합니다. 출판사에 전달하겠습니다.

p193 코드 12.2 7번째 라인

KernelCirQ_t sMsgQ[KernelMsgQ_Num];

이 책에서 일관되게 사용한 코딩 스타일을 보면 변수에 s가 붙으면 static 변수 였는데 그렇다면

static KernelCirQ_t sMsgQ[KernelMsgQ_Num];

감사합니다. 출판사에 전달하겠습니다. 깃헙에 올린 코드는 static인데 책에는 누락되어 있네요.

p208

이 페이지에 synch.h헤더 파일이 있어야 할 것 같은데, 바로 코드 13.1 세마포어 구현 synch.c가 나옴

p219 코드 11.3에 나오는 synch.h 파일 삽입이 필요해 보임

해당 설명을 하는 시점에 너무 뻔한 코드는 넣지 않았습니다. 불필요한 설명이니까요. p219에는 뻔하지 않은 KernelMutex_t 구조체에 대한 선언을 설명하기 때문에 synch.h가 필요한 것입니다.

p209 하단

당연히 이 값이 2면 컨텍스트 두 개까지, 3이면 컨택스트 세 개까지 진입 가능합니다.

여기서 컨텍스트가 태스크를 의미하는 건가요? 모호한 것 같아 보임

세마포어는 일반적 개념입니다. 나빌로스에는 없지만 태스크가 여러개의 컨택스트를 가질 수 있지요(쓰레드). 그래서 컨택스트라는 용어를 사용한것입니다.

p210 하단

kernel_yield() 함수를 호출해야만 스케줄링이 동작하므로 동기화

명확한 표현을 위해 kernel_yield() 함수를 명시적으로 호출해야만

C언어에서 모든 호출은 명시적입니다. 굳이 '명시적'이라는 용어를 쓸 필요없습니다.

p219 코드 13.9 첫번째 라인

KernelMutext_t sMutx;

이 책에서 일관되게 사용한 코딩 스타일을 보면 변수에 s가 붙으면 static 변수 였는데 그렇다면

static KernelMutex_t sMutex;

감사합니다. 출판사에 전달하겠습니다. 그러고 보니 저거 오타네요.. 깃헙 코드에도 오타가 있네요..헐...

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

hjs1543의 이미지

struct, union, enum typedef할 때 보면 typedef struct queue_t { .... .... } queue_t 에서 제가 문의한 것은
typedef struct queue_t queue_t가 좀 의아하다는 것입니다. 보통 typdef struct queue queue_t라고 사용하는데.. 특이해 보여서 여쭤 보았습니다. 혹시 self-referential pointer를 일관되게 사용하기 위해서 인지...

나빌레라의 이미지

딱히 대단한 이유는 없습니다.
평소에는 typedef struct _name_t_ {....} name_t; 이런식으로 많이하는데 나빌로스의 첫 번째 구조체를 작성하던 날 기분이 typedef struct name_t {....} name_t;로 하고 싶어서 그렇게 썼고 그 이후로는 그냥 일관성 유지하려고 똑같은 스타일로 쓴 것 뿐입니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

choi7의 이미지

UART 베이스 주소와 인터럽트 컨트롤러 베이스 주소를 지정 할때 특정한 주소를 지정해야 하나요?

그리고 베이스 주소를 지정하는 이유가 있을까요??

제 생각에는 베이스 주소가 없으면 어디에서 시작해야하는 지 몰라서 지정하는 것 같은데...

나빌레라의 이미지

네, 특정한 주소를 지정해야 합니다. 그 주소는 HW마다 다릅니다. 정해진 주소를 데이터시트에서 찾아서 써야 합니다.
베이스 주소가 해당 HW의 레지스터가 매핑된 주소입니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.