[질문] 이 소스에 머가 문제가 있어서.. 메시지큐가 작살이 날까요.. ㅠㅠ

oneclubs의 이미지

좀 이상하네요
쓰레드간에 통신을 할려고 하는데요
메인프로세서와 생성한 프로세스에서 간단히 메시지큐를 이용해서 데이터를 주고받고자 합니다..

쓰레드가 생성되고 나서 바로 메인프로세서는 msgrcv()상태로 들어가서 큐를 확인하고.. 메시지 있으면 꺼내서 출력하구요
생성된 쓰레드는..넘겨받은 값(5000)을 2배 3배 해서 10000 과 30000을 메시지큐에 넣습니다. 시간간격을 둬서
10000 넣고 3초 있다가 30000 넣습니다..

그럼 제가 생각한대로라면..
쓰레드에서 10000 넣으면 바로 메인에서 꺼내서 10000 출력하고 3초있다가 쓰레드가 또 30000 넣으면 메인에서 꺼내서 30000출력하구요..
이래야 하는데!!

생각대로 안되네요..
우선 무지무지 이상한게.. 그냥 while룹 탈출할려고 i값 2되면 나와라 했는데 msgrcv에서 값을 꺼내면서 i값이 이상하게 바뀌더라구요..
처음 실행할땐 생각대로 나오다가..루프탈출을 못해서 큐삭제를 못해서 그런가 2번째 부터는
아주 망가지네요..
아래 소스를 첨부할께요

#include  < stdio.h>
#include  < stdlib.h>
#include  < pthread.h>
#include  < unistd.h>
#include  < sys/ipc.h>
#include  < sys/msg.h>
#include  < sys/types.h>
 
#define QKEY	(key_t)0102
#define QPERM	0660
 
struct buffers{
	long mtype;
	char buf[100];
	int value;
};
 
 
void *threadFunction(void *data)
{
	int cons = *((int*)data);
	struct buffers test2;
	int queue_id;
 
	cons *=2;
	printf("[c] I send this value %d",cons);
 
	if ( (queue_id = msgget(QKEY, IPC_CREAT | QPERM)) <0 )
	{
		perror("msgget() error");
		exit(1);
	}
 
	test2.value = cons;
 
 
	if ( msgsnd(queue_id, &test2, sizeof(struct buffers) - sizeof(long), 0) < 0 )
	{
		perror("msgsnd() error");
		exit(1);
	}
 
	printf("[c] I die!\n");
}
 
int main()
{
	pthread_t thread;
	int value= 5000;
	int thr_id;
	int queue_id;
	int status;
	struct buffers test;
 
 
	if ( (queue_id = msgget(QKEY, IPC_CREAT | QPERM)) <0 )
	{
		perror("msgget() error");
		exit(1);
	}
 
	thr_id = pthread_create(&thread , NULL, threadFunction, (void *)&value );
	if ( thr_id <0 )
	{
		perror("pthread_create error : ");
		exit(1);
	}
 
	while(1)
	{
		if ( msgrcv(queue_id, &test, sizeof(struct buffers) - sizeof(long), 0, 0) < 0)
		{
			perror("msgrcv error : ");
			exit(1);
		}
		else
		{
			printf("somebody send %d\n",test.value);
			break;
		}
	}
 
 
 
	printf("waiting to die child\n");
	pthread_join(thread, (void **)&status);
	printf("return thread 0 is %d\n", status);
 
	return 0;
}
bugiii의 이미지

제목 그대로 메모리의 종류가 어떤 것이 있는지, 그 메모리가 어디서 왔다가 어디로 사라지는지를 생각해보셔야 합니다.

main 에서 쓰레드 생성할 때 전달하는 정보 교환용으로 쓰려고 하는 주소가 만들어진 쓰레드에서 어떻게 사용되고 있습니까? 또, 메시지를 전달할 때 로컬 변수의 주소를 넣었는데 그 쓰레드가 없어지게 되면 그 주소가 가리키는 메모리는 의미 있는 것일까요?

대부분의 플랫폼에서 위 프로그램은 루프 한번 돌고 그 다음 루프에서 (*3 해서 메시지 보내고 나서) 만들어진 쓰레는 종료될 것이고 main 쓰레드에서 메시지를 받았는데, '어?' 하는 것일 겁니다.

그 '어?' 하는 순간의 메모리 상황을 잘 생각해보시고 해결 방법을 생각해보시기 바랍니다.

p.s. 자기글에 + 를 줄 수 있다는 것에 놀라고 있습니다...

oneclubs의 이미지

계속 테스트를 해보니 메모리박살 현상은 없는듯한데

msgsnd()에서 invalid argument가 나오네요.. 이런 잠못자게 생겼군요 ㅠ

그전에 소스가 좀 이상해서 일단 단순하게 고쳤는데 에러는 똑같네요.. invalid argument..

oneclubs의 이미지

자문자답..
위의 소스에서
main에서 rcv를 받고 thread에서 send를 하는데..
이를 거꾸로 바꿔서 main에서 send하고 thread에서 recv하면 send실패가 발생하지 않습니다.

이유는 모르겠습니다.. 더 미치겟군요 ㅠㅠ

bugiii의 이미지

추가로 생성한 쓰레드가 3초후에 메시지를 보내고 어떻게 되는지 생각해보시기 바랍니다.

쓰레드에서 쓰고 있는 구조체를 담고 있는 로컬 변수가 쓰레드가 종료되면, 유효할 것이라고 생각하시면 안됩니다.

'어?' 하는 순간이 오시기를 바라면서...

chunsj의 이미지

전, 죽지 않았다는 것에서 '어?'가 나오네요. 변수가 무효화 되었는데도.

sliver의 이미지

msgq 써본적은 없지만 manpage를 보니 주어진 argument가 가리키는 영역을 '복사'해서 msgq에 넣는다고 되어있네요.

cinsk의 이미지

힌트:

sizeof(struct buffers) - sizeof(long)

참고:
질문과는 상관없지만, IPC의 일종인 message queue를 thread간 통신에 쓴 이유가 있나요? 차라리 mutex를 걸고, queue를 직접 구현하는 게 더 나을 듯.

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

oneclubs의 이미지

쓰레드와 큐를 이용한 거에 답은 못찾았습니다. 아무리 바꾸고 바꾸고 쌩 쑈를 했는데도..
어떨때는 msgsnd에서 invalid argument..ㅠㅠ 어떨때는 전송이 되고..
전송하는 쓰레드에 시간차를 두는둥.. 별짓을 다해봤지만 비슷한 사태가..

결국 cinsk님 말대로 mutex 로 큐만들고 있습니다.. 큐만들기 귀찮아서 메시지큐를 쓰자! 라고 했는데.. 더 시간만 날려먹고
리눅스 포기직전 상태 ㅋ 엉엉

ymir의 이미지

thread 함수 보니, mtype 에서 값을 정의하지 않으셨요..
mtype 이 nonpositive 일 경우에는, EINVAL 이 리턴됩니다.
msgsnd 함수의 man page 에서 ERRORS 를 참고하세요.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

댓글 달기

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