REENTRANT... 어떻게 써야 하는지...
글쓴이: MythRab / 작성시간: 화, 2003/12/16 - 1:49오후
thread에서 REENTRANT라는 것을 정의해 주어야 한다고 하는데요, 어떻게 정의하고 써야하는지 잘 몰라서요. 의미도 잘 모르겠고 :( ...
thread 프로그램에서 stdout 출력이 잘려서 나온다고 하니 어떤 분이 REENTRANT를 빼먹은것이 아니냐고 하네요.
의미와 선언 또는 사용법 알려주시면 감사하겠습니다. 게시판에서 찾아 읽어봐도 무슨 말인지 잘 모르겠네요...
'출력이 잘린다'는 말은 printf("This is a error!!!\n"); 하는 문장이 있다고 가정하면
s a error!!! <- 이런 식으로 출력되는 것입니다.
Forums:
[size=18]gcc -o 아웃풋 source.c [b][color=b
gcc -o 아웃풋 source.c -D_REENTRANT -lpthread
What a Cool Days!!!
Re: REENTRANT... 어떻게 써야 하는지...
이건 REENTRANT 가 아니라 스레드 동기화 문제가 아닐까요..?
간단하게 pthread_mutex_* 같은 녀석들을 한번 사용해서 테스트해보시는것도 괜찮을듯 하네요.
--
http://www.deisys.net
나도 알고 싶은데..
REENTRANT 에 대해서 문서를 여러개 읽어봤는데
구체적으로 설명해 놓은 문서를 찾을 수가 없었습니다.
한가지...제가 알고 있는 것을 말씀드립니다.
다른 분들도 아시는것을 말씀해주시면 저도 공부되겠네요
errno는 전역변수이잔아요
만약 여러 스레드가 동시에 시스템콜호출시 에러가 발생하면
errno값은 마지막에 발생한 에러값만이 저장될 것입니다.
다른 스레드가 perror() 호출하면 잘못된 에러코드를 가질수 있겠지요
그런데 REENTRANT를 define하면
errno전역변수가 스레드 고유의 영역에 저장된다고 합니다.
그래서 각각의 스레드가 자신만의 errno 값을 가질수 있지요
그래서 perror()함수를 어느스레드에서 호출해도 자신의 에러메시지만
나오게 됩니다.
헤더파일 보면 그냥 int errno 가 아니더군요
복잡하고 알수없는 매크로가 정의되어 잇어요
부트노프 저서 포직스 스레드 프로그래밍 책이 있는데요
이 책에 스레드에 대한 많은 내용이 언급되어있습니다. (강추도서)
스레드 고유의 errno값을 사용하는 것은 성능저하가 있답니다.
(있으면 얼마나 있겠냐 하는 생각으로 그냥 사용합니다만 ^^;)
이 책에서는 만약 새로운 API를 만든다면 전역변수 errno에 에러코드를
저장하는 방식을 사용하지 말고
함수가 성공일때는 0을 리턴하고 그렇지 않으면 errno값을 리턴하도록
만들라고 하더군요
대표적인 함수들이 바로
pthread_xxxx () 이런 함수들이죠
if( pthread_create() != 0 )
{ // 에러 처리 }
pthread_xxx 들과 같은 방식의 함수를 만들어쓰라고 하데요
다른 분들의 도움말을 듣고 싶습니다.
stdout
stdout 이 짤린다는 것의 정확한 의미를 모르겠지만...
stdout 의 사용자 공간의
버퍼를 여러스레드가 동시에 접근할수 있을것 같습니다.
보통은 flockfile() 과 funlockfile() 을 이용하면
스트림을 잠글수 있는데요
여러스레드가 동시에 출력하는 것은 사용자가 알아볼수 없기에
의미가 없는 경우가 많습니다.
그래서 stdout을 잠금한 후에 출력하고 stdout을 잠금해제하는
방식으로 하시면 됩니다.
글구..여러스레드가 동시에 출력하는 프로그램에서는
setvbuf()를 이용해서 _IONBF 옵션을 주어 No-Buffering을 해야할 것 같습니다.
setvbuf( stdout, _IONBF); // 인자가 정확하지는 않음.
flockfile( stdout );
printf("hello");
funlockfile(stdout);
흠 ...아는데로 주절거려본다면
putc()나 putchar()같은 것은 출력할때 잠금을 걸고 출력합니다.
만약 putc()를 루프에서 출력한다면
여러번의 잠금을 걸었다 풀었다해야겠지요
이것은 ansi 표준에 그렇게 되어있다던가 그랫답니다.
따라서 출력의 성능을 높이기 위해서는
잠금을 걸지 않는 putc()를 이용해야 하는데
잠금을 걸지 않는 putc()는 putchar_unlocked()입니다.
flock(stdout);
for( i=0;i<100;i++)
putchar_unlocked('a');
funlockfile(stdout);
지금 어이없는 일이 생겨서..이만 마치겠습니다.
Re: REENTRANT... 어떻게 써야 하는지...
REENTRANT 알기쉽게 설명된 예...링크입니다.
http://www.pie.pe.kr/wiki/moin.cgi/Reentrant
Programmers never die: They just GOSUB without RETURN.
스트림의 경우에는 짤리는게 당연합니다.
일반적으로 스트리밍 되면 쓰레드는 이를 공유하므로 출력이 될때 버퍼링이나 기타 다른 이유로도 중간에 다른 출력이 끼어들 수 있습니다.
정 출력이 중요하시면 write() 함수로 출력하시기 바랍니다. PIPE_SIZE 까지는 atomic을 보장해주니까요. 스트림의 경우에도 넌 버퍼링의 경우에는 버퍼링을 하지 않으므로 다른 출력이 끼어들기 힘들기는 하지만, 완전하지는 않습니다.
따라서 쓰레드나 혹은 시그널을 사용하는 경우는 버퍼출력은 write()로 하는게 속편합니다.
========================================
* The truth will set you free.
추가내용입니다.
debug print 라서 출력이 중요하기도 하지만
출력이 잘린뒤에 segmentation fault가 나거든요.
혹시 출력이 잘린게 segmentation fault의 원이이 되는게 아닌가 해서요...
근데, printf를 fprintf(stderr)로 바꾸면 segmentation fault가 안나는 것 같아요.
안나는 것 같다고 말할 수 밖에 없는 것은 한 30번 정도 돌려봐서 fault가 안나도 안난다고는 할 수 없는 일이기에 ㅡㅡ.
여튼 printf 일 때는 평균적으로 8번 정도 실행 시키면 났는데 fprintf로 바꾸고나서 30-40번 해도 안났으니까 안나는 것 같습니다.
printf와 fprintf의 내부 처리 방식이 다른건지.... 잘 모르겠네요...
fprintf 는 자체적으로 lock 기능이 있는건지...
Heading, heading again, again, ... ㅜㅜ 피난다
Re: REENTRANT... 어떻게 써야 하는지...
쓰레드에서 전역변수를 사용하면 당연히 안되는거죠.
런타임라이브러리(리눅스에서도 이렇게 부르나요?)의 경우 전역변수를 사용하는 버젼과 사용하지 않는 버젼이 있습니다.
멀티쓰레딩을 사용하려면 전역변수를 사용하지 않는 버젼을 사용해야 합니다.
REENTRANT란 것을 우리 말로 "재진입" 이라고 하는것 같던데...
하나의 펑션이 실행되고 있는 동안 다시 실행되는걸 의미합니다.
다중 쓰레딩의 경우가 하나의 코드가 여러개의 쓰레드에 의해 실행되니까 REENTRANT가 지원되도록 프로그래밍을 해야 합니다.
댓글 달기