[리눅스]메세지 큐를 이용한 serial & key & timer check
develop/dogvelop 2006. 12. 11. 15:53
/**
* 부모와 자식 프로세서로 나누고,
* 부모프로세서에서는 시리얼로 부터 데이터를 받아 들이고,
* 자식프로세서는 time out체크와, CANCEL키 체크를 하도록 했다.
* 두 프로세서 간의 통신은 메세지 큐를 이용했다.
*
* 이 프로그램은 자식 프로세서에 걸린 timer가 지정된 시간을 초과시
* 부모 프로세서에게 "TIMEOUT"메세지를 보내면, 부모 프로세서가 자식
* 프로세서에게 SIGTERM을 보내서 자식 프로세서를 끝내고,
* 부모 프로세서는 자식 프로세서가 종료 됐다는 것을 알게 되면(waitpid)
* 프로그램을 종료 하도록 만들었다.
*/
#include "include.h"
#define MOL
#include "app_pub.h"
#include "app_def.h"
#include "app_func.h"
#define SIZE 10
#define KEY 1234
struct {
long mtype;
char data[SIZE];
} msg_data;/**< 메세지 큐에서 사용할 메세지 구조체*/
int main(void)
{
struct pollfd Event;
sigset_t set,oldset,pend;
int pid,cnt,status,child,i,j;
char kch;
int msgid;/**< msgget()으로 가져온 메세지 큐의 id를 저장할 변수*/
i = j = 0;
if ((pid=fork()) < 0)
{
perror("fork() Error");
exit(1);
}
if (pid)
{ //parent
// 부모 프로세서에서 메세지큐를 생성한다.
// 메세지 큐를 만든다.(mode 0666)
// 동일한 key의 메세지 큐가 있으면, 식별자만 반환(IPC_CREAT)
if ((msgid = msgget((key_t)KEY,IPC_CREAT|0666)) == -1)
{
perror("msgget() Error");
exit(1);
}
printf("parent msgid %d\n",msgid);
sio_set(PRIVATE_PORT,B9600);
memset(tempbuf,0,sizeof(tempbuf));
rlen = 0;
Event.fd = fd;
Event.events = POLLIN | POLLERR;
while(1)
{
child = waitpid(pid,&status, WNOHANG);
cnt = poll((struct pollfd *)&Event,1,1000);
if (cnt < 0)
{
perror("parent poll() Error");
exit(1);
}
else
if (!cnt)
{
printf("Parent %d\n",i++);
// 1초마다.메세지 큐에 있는 메세지를 읽는다.
// 메세지가 없으면, 기다리지 않고 -1을 리턴하고 넘어간다.
// msg_data.mtype = 1인 것만 읽어온다.
// msg_data.mtype 에 상관없이 맨 앞에것만 읽어온다.
if (msgrcv(msgid,&msg_data,SIZE,0,IPC_NOWAIT) > 0)
{ // 메세지가 있으면,
printf("msg_data mtype = %ld\n",msg_data.mtype);
printf("msg_data = %s\n",msg_data.data);
if (strstr(msg_data.data,"TIMEOUT"))
{
// 메세지 큐(msg_data.data)가 "TIMEOUT"인 경우에는
// 프로그램을 종료한다.
if (msgctl(msgid,IPC_RMID,0) == -1)
{
perror("child msgctl() Error");
release_timer();
exit(1);
}
printf("msgid(%d) Delete\n",msgid);
// child process에는 테스트를 위해 종료 부분을 뺐다
kill(pid,SIGTERM);
}
}
if (child>0)
{
printf("Child Process Term\n");
exit(1);
}
}
else
if (cnt)
{
RCH = com_getc();
tempbuf[rlen++] = RCH;
printf("tempbuf[]>> \n");
printf("%s \n",tempbuf);
}
}//while
}//parent
else
{ //child
// KEY를 갖도록 메세지큐를 생성 또는 기존에 있으면, 메세지ID(msgid)
// 를 얻어온다.(기존에 메세지 큐가 있으면, 접근 모드는 무시된다.)
if ((msgid = msgget((key_t)KEY,IPC_CREAT|0666)) == -1)
{
perror("child msgget() Error");
exit(1);
}
keyhandle = open("/dev/key",O_RDWR);
printf("child msgid %d",msgid);
Event.fd = keyhandle;
Event.events = POLLIN | POLLERR;
sigemptyset(&set);
sigaddset(&set, SIGALRM);
sigprocmask(SIG_BLOCK,&set,&oldset);
set_timer(10);
while(1)
{
cnt = poll((struct pollfd *)&Event,1,1000);
if (cnt < 0)
{
perror("child poll() Error");
exit(1);
}
else
if (!cnt)
{
printf("Child %d\n",j++);
sigpending(&pend);
if (sigismember(&pend,SIGALRM))
{
//struct msgbuf에 type(long)값을 꼭 줘야 한다.
//(msgsnd()시, type에 값이 없으면, argument error가 난다.
msg_data.mtype = 1;
strcpy(msg_data.data,"TIMEOUT");
if (msgsnd(msgid,&msg_data,strlen(msg_data.data),0) ==-1)
{
perror("child msgsnd() Error");
release_timer();
exit(1);
}
release_timer();
// set_timer()의 타임아웃을 체크했으면,
// 시그널들을 원래대로 되돌린다.
sigprocmask(SIG_SETMASK,&oldset,NULL);
}
}
else
if (cnt)
{
kch = GetKey();
if (kch == CANCEL)
{
msg_data.mtype = 1;
strcpy(msg_data.data,"CANCEL");
if (msgsnd(msgid,&msg_data,strlen(msg_data.data),0) == -1)
{
perror("child msgsnd()2 Error");
exit(1);
}
//release_timer();
//exit(1);
}
}
}//while
}//chile
}
* 부모와 자식 프로세서로 나누고,
* 부모프로세서에서는 시리얼로 부터 데이터를 받아 들이고,
* 자식프로세서는 time out체크와, CANCEL키 체크를 하도록 했다.
* 두 프로세서 간의 통신은 메세지 큐를 이용했다.
*
* 이 프로그램은 자식 프로세서에 걸린 timer가 지정된 시간을 초과시
* 부모 프로세서에게 "TIMEOUT"메세지를 보내면, 부모 프로세서가 자식
* 프로세서에게 SIGTERM을 보내서 자식 프로세서를 끝내고,
* 부모 프로세서는 자식 프로세서가 종료 됐다는 것을 알게 되면(waitpid)
* 프로그램을 종료 하도록 만들었다.
*/
#include "include.h"
#define MOL
#include "app_pub.h"
#include "app_def.h"
#include "app_func.h"
#define SIZE 10
#define KEY 1234
struct {
long mtype;
char data[SIZE];
} msg_data;/**< 메세지 큐에서 사용할 메세지 구조체*/
int main(void)
{
struct pollfd Event;
sigset_t set,oldset,pend;
int pid,cnt,status,child,i,j;
char kch;
int msgid;/**< msgget()으로 가져온 메세지 큐의 id를 저장할 변수*/
i = j = 0;
if ((pid=fork()) < 0)
{
perror("fork() Error");
exit(1);
}
if (pid)
{ //parent
// 부모 프로세서에서 메세지큐를 생성한다.
// 메세지 큐를 만든다.(mode 0666)
// 동일한 key의 메세지 큐가 있으면, 식별자만 반환(IPC_CREAT)
if ((msgid = msgget((key_t)KEY,IPC_CREAT|0666)) == -1)
{
perror("msgget() Error");
exit(1);
}
printf("parent msgid %d\n",msgid);
sio_set(PRIVATE_PORT,B9600);
memset(tempbuf,0,sizeof(tempbuf));
rlen = 0;
Event.fd = fd;
Event.events = POLLIN | POLLERR;
while(1)
{
child = waitpid(pid,&status, WNOHANG);
cnt = poll((struct pollfd *)&Event,1,1000);
if (cnt < 0)
{
perror("parent poll() Error");
exit(1);
}
else
if (!cnt)
{
printf("Parent %d\n",i++);
// 1초마다.메세지 큐에 있는 메세지를 읽는다.
// 메세지가 없으면, 기다리지 않고 -1을 리턴하고 넘어간다.
// msg_data.mtype = 1인 것만 읽어온다.
// msg_data.mtype 에 상관없이 맨 앞에것만 읽어온다.
if (msgrcv(msgid,&msg_data,SIZE,0,IPC_NOWAIT) > 0)
{ // 메세지가 있으면,
printf("msg_data mtype = %ld\n",msg_data.mtype);
printf("msg_data = %s\n",msg_data.data);
if (strstr(msg_data.data,"TIMEOUT"))
{
// 메세지 큐(msg_data.data)가 "TIMEOUT"인 경우에는
// 프로그램을 종료한다.
if (msgctl(msgid,IPC_RMID,0) == -1)
{
perror("child msgctl() Error");
release_timer();
exit(1);
}
printf("msgid(%d) Delete\n",msgid);
// child process에는 테스트를 위해 종료 부분을 뺐다
kill(pid,SIGTERM);
}
}
if (child>0)
{
printf("Child Process Term\n");
exit(1);
}
}
else
if (cnt)
{
RCH = com_getc();
tempbuf[rlen++] = RCH;
printf("tempbuf[]>> \n");
printf("%s \n",tempbuf);
}
}//while
}//parent
else
{ //child
// KEY를 갖도록 메세지큐를 생성 또는 기존에 있으면, 메세지ID(msgid)
// 를 얻어온다.(기존에 메세지 큐가 있으면, 접근 모드는 무시된다.)
if ((msgid = msgget((key_t)KEY,IPC_CREAT|0666)) == -1)
{
perror("child msgget() Error");
exit(1);
}
keyhandle = open("/dev/key",O_RDWR);
printf("child msgid %d",msgid);
Event.fd = keyhandle;
Event.events = POLLIN | POLLERR;
sigemptyset(&set);
sigaddset(&set, SIGALRM);
sigprocmask(SIG_BLOCK,&set,&oldset);
set_timer(10);
while(1)
{
cnt = poll((struct pollfd *)&Event,1,1000);
if (cnt < 0)
{
perror("child poll() Error");
exit(1);
}
else
if (!cnt)
{
printf("Child %d\n",j++);
sigpending(&pend);
if (sigismember(&pend,SIGALRM))
{
//struct msgbuf에 type(long)값을 꼭 줘야 한다.
//(msgsnd()시, type에 값이 없으면, argument error가 난다.
msg_data.mtype = 1;
strcpy(msg_data.data,"TIMEOUT");
if (msgsnd(msgid,&msg_data,strlen(msg_data.data),0) ==-1)
{
perror("child msgsnd() Error");
release_timer();
exit(1);
}
release_timer();
// set_timer()의 타임아웃을 체크했으면,
// 시그널들을 원래대로 되돌린다.
sigprocmask(SIG_SETMASK,&oldset,NULL);
}
}
else
if (cnt)
{
kch = GetKey();
if (kch == CANCEL)
{
msg_data.mtype = 1;
strcpy(msg_data.data,"CANCEL");
if (msgsnd(msgid,&msg_data,strlen(msg_data.data),0) == -1)
{
perror("child msgsnd()2 Error");
exit(1);
}
//release_timer();
//exit(1);
}
}
}//while
}//chile
}
'develop > dogvelop' 카테고리의 다른 글
mingw + eclipse로 windows에서 개발하기 (0) | 2006.12.15 |
---|---|
[Linux] key & serial 멀티 프로세서로 처리하기 (0) | 2006.12.09 |
[리눅스] sleep & usleep (0) | 2006.11.29 |
[리눅스] 현재 시간을 자신이 원하는 포맷으로 출력하기 (0) | 2006.08.22 |
프로세스 찾아서 지우고 실행하기 (0) | 2006.08.21 |