프로세스 종료 함수 wait() 에 대해서 질문이 있습니다. 전에 질문 내용을 보강 했습니다.^^;

caihan의 이미지

wait() 함수를 사용할 경우 컴파일 에러
error: incompatible type for argument 1 of `wait'
가 출력되는 문제가 있습니다. 인자의 타입이 맞질 않는다...가 되겠네요.

밑의 소스에서 sys/wait.h 을 제거하고 컴파일 하면
warning: implicit declaration of function `wait'
주의 메시지와 함께 컴파일이 되며 실행또한 문제가 없었습니다.

하지만 왠지 불안한 요소가 될거 같아 질문 합니다. 그 전 답변 주신분들 너무 감사합니다.

질문 내용자체에 대해서 그전 게시물이 내용이 부실하여 다시 올리게 되었습니다.
<,> 표시가 되질 않아 모두 제거 했습니다.

/* Header File */
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include fcntl.h
#include signal.h
#include errno.h
#include time.h
#include sqlite3.h
#include pthread.h
#include sys/time.h
#include sys/stat.h
#include sys/types.h
#include sys/wait.h
#include sys/ipc.h
#include sys/shm.h
#include sys/msg.h

wait() 함수를 사용한 함수 전문 입니다.
int ProcessWait( void )
{
	sqlite3  *WritDB = 0;
	FILE	 *wfp;
 
	int	 stat, n;
 
	struct config_file *_sptr;
	char   sptrbuf[sizeof( struct config_file )];
 
 
	_sptr = (struct config_file *)sptrbuf;
         memset( &sptrbuf[0], 0, sizeof( struct config_file ) );
 
	stat = -1;
	n = wait( &stat );
#ifdef DEBUG
	fprintf( stdout, "CO>> %d wait = (child stat=%d)\n", n, stat );
#endif
	if( n < 0 ) {
		if( errno == ECHILD ) { return 1; }
		else if( errno == EINTR ) { return 2; }
	}
	else if( n > 0 ) {
		if( stat == 7680 ) { //Process Fail
			sleep( 4 );
			WritDB = SqliteDBOpen( WritDB );
			SqliteDBDelete( WritDB );
			strcpy( &_ShmConfigPtr->ServerIp_M[0],   DEFAULT_SERVERIP_M );
			strcpy( &_ShmConfigPtr->ServerIp_S[0],   DEFAULT_SERVERIP_S );
			strcpy( &_ShmConfigPtr->ServerPort_M[0], DEFAULT_SERVERPORT_M );
			strcpy( &_ShmConfigPtr->ServerPort_S[0], DEFAULT_SERVERPORT_S );
			SqliteDBInsert( WritDB, _sptr, 2 ); SqliteDBClose( WritDB ); ConnectFlowFileSave();
			Process_exec( RES_TCP_PROC, MSGQ_KEY01, NULL, SHM_KEY00, 3 );
			ProcessIDFileSave();
		}
		else if( stat == 10240 || stat == 10496 || stat == 5120 ) {
			sleep( 4 );
			Process_exec( RES_TCP_PROC, MSGQ_KEY01, NULL, SHM_KEY00, 3 );
			ProcessIDFileSave();
		}
		else if( stat == 10752 ) {
			if( _ShmConfigPtr->Status == 1 ) {
				sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 21 );
				sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 23 );
				sleep( 1 ); Process_exec( RES_TCP_PROC, MSGQ_KEY01, NULL,   SHM_KEY00, 3 );
				ProcessIDFileSave();
			}
			else if( _ShmConfigPtr->Status == 2 ) {
				sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 24 );
				sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 22 );
				sleep( 1 ); wfp = fopen( "/etc/resolv.conf", "w" );
				fprintf( wfp, "nameserver %s\n", _ShmConfigPtr->LocalDns1 );
				fprintf( wfp, "nameserver %s\n", _ShmConfigPtr->LocalDns2 );
				fclose( wfp );
				sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 23 );
				sleep( 1 ); Process_exec( RES_TCP_PROC, MSGQ_KEY01, NULL,   SHM_KEY00, 3 );
				ProcessIDFileSave();
			}
			else if( _ShmConfigPtr->Status == 3 ) {
				sleep( 4 );
				Process_exec( RES_COM_PROC, MSGQ_KEY01, NULL,   SHM_KEY00, 4 );
				ProcessIDFileSave();
			}
		}
		return 2;
	}
	return 0;
}

아래는 main 함수에서 사용하는 부분 입니다.

while( 1 ){
	rtn = ProcessWait();
	if( rtn == 1 ) { break; }
	if( rtn == 2 ) { continue; }
}

총 4개의 프로세스를 생성하여 사용하고 있습니다. 그래서 while 루프로 돌린 것입니다.
이 외의 소스는 필요없다 생각되어 포함하지 않았습니다.
필요한 부분 요청이 있으면 다시 올리겠습니다.

컴파일 환경은
컴파일OS : 페도라 리눅스8 커널버전 2.6.X
컴파일러 : arm-linux-gcc 버전 3.4.3
컴파일 옵션 : arm-linux-gcc -c -W -Wall -O2 -I/usr/local/include -fpack-struct XXXX.c
링크 옵션 : arm-linux-gcc -lm -o XXXX XXXX.o -L/usr/local/lib -lsqlite3 -lpthread -D_REENTRANT
참고로 /usr/local/include 이곳은 sqlite DB 라는 라이브러리(arm-linux-gcc로 컴파일)가 있는 곳입니다.

sys/wait.h 파일을 추적해본 결과
extern __pid_t wait (__WAIT_STATUS __stat_loc);
가 있었습니다. 맞는지 모르겠네요;;

bushi의 이미지

정말 전의 댓글을 읽어보긴 하셨는지요.

더 말할 필요없이 본인의 코드로 테스트해보면 컴파일러 버그인지 아닌지 나오겠죠.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
 
#if 0
#  include <sqlite3.h>
#  define RESOLV_CONF           "/etc/resolv.conf"
#else
#  define RESOLV_CONF           "/tmp/resolv.conf"
#  define DEFAULT_SERVERIP_M    "0.0.0.0"
#  define DEFAULT_SERVERPORT_M  "0"
#  define DEFAULT_SERVERIP_S    "0.0.0.0"
#  define DEFAULT_SERVERPORT_S  "0"
 
#  define sqlite3               void
#  define SqliteDBOpen(x)       (void*)(NULL)
#  define SqliteDBDelete(x)     do {} while (0)
#  define SqliteDBInsert(x,y,z) do {} while (0)
#  define SqliteDBClose(x)      do {} while (0)
 
#  define ConnectFlowFileSave() do {} while (0)
#  define Process_exec(a,b,c,d,e) do {} while (0)
#  define ProcessIDFileSave()   do {} while (0)
struct config_file {
};
static struct ShmConfig {
        char ServerIp_M[64];
        char ServerPort_M[64];
        char ServerIp_S[64];
        char ServerPort_S[64];
        char LocalDns1[64];
        char LocalDns2[64];
        int Status;
} ShmConfig;
static struct ShmConfig *_ShmConfigPtr = &ShmConfig;
#endif
 
int ProcessWait( void )
{
        sqlite3  *WritDB = 0;
        FILE     *wfp;
 
        int      stat, n;
 
        struct config_file *_sptr;
        char   sptrbuf[sizeof( struct config_file )];
 
        _sptr = (struct config_file *)sptrbuf;
         memset( &sptrbuf[0], 0, sizeof( struct config_file ) );
 
        stat = -1;
        n = wait( &stat );
#ifdef DEBUG
        fprintf( stdout, "CO>> %d wait = (child stat=%d)\n", n, stat );
#endif
        if( n < 0 ) {
                if( errno == ECHILD ) { return 1; }
                else if( errno == EINTR ) { return 2; }
        }
        else if( n > 0 ) {
                if( stat == 7680 ) { //Process Fail
                        sleep( 4 );
                        WritDB = SqliteDBOpen( WritDB );
                        SqliteDBDelete( WritDB );
                        strcpy( &_ShmConfigPtr->ServerIp_M[0],   DEFAULT_SERVERIP_M );
                        strcpy( &_ShmConfigPtr->ServerIp_S[0],   DEFAULT_SERVERIP_S );
                        strcpy( &_ShmConfigPtr->ServerPort_M[0], DEFAULT_SERVERPORT_M );
                        strcpy( &_ShmConfigPtr->ServerPort_S[0], DEFAULT_SERVERPORT_S );
                        SqliteDBInsert( WritDB, _sptr, 2 ); SqliteDBClose( WritDB ); ConnectFlowFileSave();
                        Process_exec( RES_TCP_PROC, MSGQ_KEY01, NULL, SHM_KEY00, 3 );
                        ProcessIDFileSave();
                }
                else if( stat == 10240 || stat == 10496 || stat == 5120 ) {
                        sleep( 4 );
                        Process_exec( RES_TCP_PROC, MSGQ_KEY01, NULL, SHM_KEY00, 3 );
                        ProcessIDFileSave();
                }
                else if( stat == 10752 ) {
                        if( _ShmConfigPtr->Status == 1 ) {
                                sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 21 );
                                sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 23 );
                                sleep( 1 ); Process_exec( RES_TCP_PROC, MSGQ_KEY01, NULL,   SHM_KEY00, 3 );
                                ProcessIDFileSave();
                        }
                        else if( _ShmConfigPtr->Status == 2 ) {
                                sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 24 );
                                sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 22 );
                                sleep( 1 ); wfp = fopen( RESOLV_CONF, "w" );
                                fprintf( wfp, "nameserver %s\n", _ShmConfigPtr->LocalDns1 );
                                fprintf( wfp, "nameserver %s\n", _ShmConfigPtr->LocalDns2 );
                                fclose( wfp );
                                sleep( 1 ); Process_exec( NULL, NULL, NULL, NULL, 23 );
                                sleep( 1 ); Process_exec( RES_TCP_PROC, MSGQ_KEY01, NULL,   SHM_KEY00, 3 );
                                ProcessIDFileSave();
                        }
                        else if( _ShmConfigPtr->Status == 3 ) {
                                sleep( 4 );
                                Process_exec( RES_COM_PROC, MSGQ_KEY01, NULL,   SHM_KEY00, 4 );
                                ProcessIDFileSave();
                        }
                }
                return 2;
        }
        return 0;
}
 
int main()
{
        int rtn;
 
        while( 1 ){
                rtn = ProcessWait();
                if( rtn == 1 ) { break; }
                if( rtn == 2 ) { continue; }
        }
        return 0;
}

OTL

ihavnoth의 이미지

전 낼쯤 테스트 해볼 수 있겠네요...

없음

ihavnoth의 이미지

wait(*status) 시스템콜 호출후에 자식프로세스 종료 정보가
(아마도 4바이트 union wait형태인듯) status에 포인팅 되는데...

컴파일시에 -fpack-struct를 쓰는 바람에 union의 크기가 변경되고

포인팅시 에러가 나는것 같습니다.

man gcc보니 -fpack-struct의 경우 모든 구조체를 pack해버려서

성능상의 큰 문제가 있다고합니다.(-O 옵티마이징 안됨)

pack할 구조체만 __attribute__ ((packed))를 써야 할것 같습니다.

커널 소스보니 필요한부분만 __attribute__ 로 지정하더군요..

방금 컴파일해보고 구글링한거라서 조금 답변이 조잡하네요 -.-

없음

caihan의 이미지

noth 님 그럴수도 있겠다 라는 생각을 해봅니다.
pack 하는 구조체를 선별해서 써야 겠네요.
사용하는 구조체가 많칠 않아서....귀차니즘 모드로 컴파일 옵션으로 햇던건데...
성능에 영향이 많다면...수정이 불가피 하겠네요.
좋은 정보 정말 감사 드립니다.
bushi 님...제 질문에 답변을 꼬박꼬박 달아 주시지 정말 고맙습니다.
근데...이해가 잘 가지 않습니다...

"
컴파일러가 좀 이상한 것 같기는 합니다만,
어지간하면 변수이름을 바꾸시죠.

원형(prototype) 선언을 제대로 하지 않고 코딩을 하면 버그가 숨어들 가능성이 커지게 된다는 것을 보여줄 뿐,
별로 재밌지는 않은 것 같은데요.
"

컴파일러 warnning 자체 메시지가 원형선언이 되지 않아 발생하는 문제인줄은 알고 있습니다.
그 원형이 sys/wait.h 에 있는것 또한 알고 있습니다.
재밌다고 표현한것도 원형이 분명 wait.h 에 있는데도 불구하고
인클루드 하면 인자 타입이 맞지 않는 에러가 출력되어 그렇게 표현한 겁니다.

"
설령 sys/stat.h 를 include 했다하더라도 에러가 나지않는 것이 정상입니다.

컴파일러가 개판이던가 예제 코드를 올리면서 실제 본인의 코드와는 다르게 올렸던가 했겠죠.
실제 코드를 추측해보면

#include
#include
#include

int main()
{
int my_stat;

wait(&stat);
}

이정도 ?

보통 이해할 수 없는 증상을 만나면 libc 나 컴파일러를 의심하던데,
이분은 특이하게도 커널을 의심하십니다.
자기 코드는 틀린데가 없다고 굳게 믿는 것은 피차일반이지만...
"

인클루드 한 상황에서 위 같은 실수가 나온다면 분명 다른식 메시지로 컴파일러가
알려줄겄같습니다.
현재 나온 문제도 모든 주의 메시지를 제거하는 과정에서 나온 것입니다.
모든 컴파일 주의 메시지는 나오지 않게 고쳤고 wait 함수 하나만이 남은 상황 입니다.
커널을 의심한게 아니라는건 이미 답변 했습니다.

그리고 bushi 님.
제가 bushi 님의 답변을 골고루 읽어 봤습니다만.
이곳에 답변 정말 잘해 주시고 열심히 활동하고 계시고...정말 고마운 분이라는건 알고 있습니다.
하지만 부탁드리고 싶은 내용은
말씀을 좀 순화해서 써달라는 부탁을 좀 하고 싶습니다.
경력이 얼마나 되시는지 또 얼마나 많은 지식을 알고 계시는진 모르겠으나.
답변을 듣고 해결되면 기분이 좋아야 하는데 또 아니라고 치더라도
답변을 읽고 기분이 나쁘다면...문제가 있다고 생각합니다.
질문자의 지식수준 실력 경력이 잘 드라나지 않는 게시판 입니다.
아무리 경력이 높다고 하더라도 별것아닌 부문에서 막힐 수 있는 것이 개발 입니다.
저도 리눅스 네트워크,시스템 프로그램을 많이 만들어 봤고 이같은 문제 또한 처음 발견된 것입니다.
혹시나 하여 비슷한 경험이 있으신분이 있다면 어떻게 해결 했는지 듣고 싶었을 뿐입니다.
제가 질문이나 댓글에서 실수한 부문에 대해서는 사과도 드렸고 했는데...
답변을 보고 기분이 별로 좋지 않아...두서없이 글을 썻습니다. 양해 바랍니다.

bushi의 이미지

엔지니어는 외교관이 아니라 병사라고 생각합니다.
적을 앞에 두고,
"이리오세요. 요렇게 조준하시고 저길 쏘세요. 아 이걸 당기면 총알이 나간답니다." 라고 하기엔 너무 답답하지 않습니까 ?
더군다나 이제 갓 들어온 신병도 아니고 짬밥 좀 먹은 동료에게는.

OTL

ihavnoth의 이미지

padding, pack, alignment에 대해서
다시한번 보게 되는 좋은 기회가 됬네요..

경험이 미천한 관계로... 사실 쓸일이 한번도 없었다는....

없음

caihan의 이미지

noth님 정말 감사합니다. -fpack-struct 제거하고 컴파일 하니 되더군요.^^;;
noth님이 적어주신 예상내용이 맞는것 같습니다...
경험이 많치 않다고 하셨는데...단 시간에 그렇게 예상까지 하시다니..
제가 보기엔 굉장한 실력자님 같습니다.ㅎㅎ;
정말 전혀 생각지도 못했던 곳에서 noth님 덕에 해결 했습니다.
정말 감사합니다! 꾸벅

외국사이트에도 저와 같은 문제로 질문한 게시판이 두개 정도 있던데...
제가 noth님 아이디 올리고 해결 답변 올려야 겠네요.^^

bushi의 이미지

두서없이 씁니다.

"인자의 크기가 변해서일까 ?" 라는 의심에 대한 테스트는 간단하게 해볼 수 있습니다.
qemu-arm 과 EABI 를 지원하지 않는 것이 확실한 툴체인을 준비합니다.
버전도 3.4 대로 맞추면 좋겠지요.

[bushi@rose wait]$ rpm -qf `which qemu-arm`
qemu-0.9.0-7.fc8
[bushi@rose wait]$ 
[bushi@rose wait]$ /opt/host/strongarm/bin/armv4l-softfloat-linux-gnu-gcc -v
Reading specs from /opt/host/strongarm/bin/../lib/gcc/armv4l-softfloat-linux-gnu/3.4.5/specs
Configured with: /work/crosstool/crosstool-0.43/build/armv4l-softfloat-linux-gnu/gcc-3.4.5-glibc-2.3.6/gcc-3.4.5/configure --target=armv4l-softfloat-linux-gnu --host=i686-host_pc-linux-gnu --prefix=/work/crosstool/crosstool-0.43/result/gcc-3.4.5-glibc-2.3.6/armv4l-softfloat-linux-gnu --with-float=soft --with-headers=/work/crosstool/crosstool-0.43/result/gcc-3.4.5-glibc-2.3.6/armv4l-softfloat-linux-gnu/armv4l-softfloat-linux-gnu/include --with-local-prefix=/work/crosstool/crosstool-0.43/result/gcc-3.4.5-glibc-2.3.6/armv4l-softfloat-linux-gnu/armv4l-softfloat-linux-gnu --disable-nls --enable-threads=posix --enable-symvers=gnu --enable-__cxa_atexit --enable-languages=c,c++ --enable-shared --enable-c99 --enable-long-long
Thread model: posix
gcc version 3.4.5
[bushi@rose wait]$

sys/wait.h, bits/waitstatus.h 와 비스무리한 정의를 사용하는 테스트 코드를 작성합니다.
좀 더 확실히 하기 위해 gcc -E 의 결과 중 필요한 부분을 copy&paste 해서 작성했습니다.

[bushi@rose wait]$ cat s.c
#include <stdio.h>
struct aa {
 unsigned int __w_termsig:7;
 unsigned int __w_coredump:1;
 unsigned int __w_retcode:8;
 unsigned int:16;
};
 
struct bb {
 unsigned int __w_stopval:8;
 unsigned int __w_stopsig:8;
 unsigned int:16;
};
 
int main()
{
        if (sizeof(struct aa) == 4) {
                printf("ok!!\n");
        }
        if (sizeof(struct bb) == 4) {
                printf("ok!!\n");
        }
        return 0;
}
[bushi@rose wait]$

컴파일해서 실행시켜 봅니다.

[bushi@rose wait]$ /opt/host/strongarm/bin/armv4l-softfloat-linux-gnu-gcc -s -o s s.c -static
[bushi@rose wait]$ /opt/host/strongarm/bin/armv4l-softfloat-linux-gnu-gcc -s -o s_pack s.c -static -fpack-struct
[bushi@rose wait]$ 
[bushi@rose wait]$ sudo qemu-arm ./s
ok!!
ok!!
[bushi@rose wait]$ sudo qemu-arm ./s_pack
ok!!
ok!!
[bushi@rose wait]$

이상없습니다. 당연한 결과 이기도 하고요.

그렇다면... 진실은 뭘까요.
sys/wait.h 의 일부입니다.

typedef union
  {
    union wait *__uptr;
    int *__iptr;
  } __WAIT_STATUS __attribute__ ((__transparent_union__));
...
extern __pid_t wait (__WAIT_STATUS __stat_loc);

arm gcc 는 -fpack-struct 옵션이 주어질 때
__attribute__ ((__transparent_union__)) 를 무시합니다.
결과적으로 wait() 함수의 인자는 반드시 __WAIT_STATUS 형이어야만 됩니다.
다른 형이 주어진다면 컴파일러는

error: incompatible type for argument 1 of `wait'

라는 에러를 뱉을 수 밖에 없습니다.

덧.

잘 나가다 이상한 길로 빠지시는 것 같아 댓글달았습니다.

OTL

ihavnoth의 이미지

하나씩 해봐야 겠네요 ^.^

일찍 자야하는데 여기저기서 너무 유혹하네요...

_______________________________________

대충 짐작하다... 민폐를 ... 덜덜

두분께 죄송합니다. 하지만 오늘도 하나 더 배우고 감니다..

오늘은 처음으로 gcc 매뉴얼을 보게 되네요..
(manpage말고 gcc.pdf)

qemu-arm 과 EABI는 내일 찾아봐야겠네요

시간은 순식간에 지나가고 할일은 많고 힘듭니다.

$ arm-linux-gcc test.c -Wall -O2 -o test ; echo $?
0
$ arm-linux-gcc test.c -Wall -O2 -o test -fpack-struct; echo $?
test.c:9: warning: '__transparent_union__' attribute ignored
test.c: In function 'main':
test.c:21: error: incompatible type for argument 1 of 'wait'
1

정말 짧은 영어지만... ignored는 잘보이네요

#include unistd.h
#include stdio.h
#include sys/types.h
//#include wait.h
typedef union
{
        union wait *__uptr;
        int *__iptr;
} __WAIT_STATUS __attribute__ ((__transparent_union__));
 
extern __pid_t wait (__WAIT_STATUS __stat_loc);
 
 
int main(void)
{
        pid_t pid;
        int status;
 
        pid = fork();
 
        if (pid !=0) {
                wait(&status);
        }
        return 0;
}

없음

caihan의 이미지

bushi 님! 이제야 이해가 좀 갑니다.
헤더파일 쪽 설명도 읽어보고 bushi 님 말씀대로 컴파일도 해 보았습니다.
이제야 정확히 이해가 갑니다.ㅜㅜ
제가 조금더 깊히 생각해 보고 했었어야 했는데...
noth, bushi 님 두분덕에 저 정말 많은 부분 배우고 갚니다...
두분 정말 감사 합니다...
생각 같아선 삼겹살에 소주를 사고 싶은 마음 굴뚝 같습니다.;

댓글 달기

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