[Linux] key & serial 멀티 프로세서로 처리하기

fork(), signal, poll()을 사용한 프로그램이다.

/**
 * 멀티프로세서 프로그램 *
 * 부모 프로세서에서는 전용선(ttyS3)에서 데이터를 읽어오고(1byte)
 * set_timer()로 지정한 시간이 경과하면 자식프로세서를 종료시키고 종료한다.
 *
 * 자식 프로세서는 키입력을 받아오고, 종료(CANCEL)키가 들엉오면,
 * 부모프로세서에게 종료(SIGTERM)시그널을 보내고 종료한다.
 */
#include "include.h"
#define MOL
#include "app_pub.h"
#include "app_def.h"
#include "app_func.h"

int main(void)
{
    int pid,ppid, cnt,child,parent,status;
    struct pollfd Event;
    sigset_t set1,oldset,pend;
    if ((pid = fork()) < 0)
    {
        perror("fork() Error");
        exit(2);
    }
    else
    if (pid != 0)
    {   //parent
        sio_set(PRIVATE_PORT, B9600);
        Event.fd = fd;
        Event.events = POLLIN | POLLERR;
        //시그널 집합 set1을 비우고,
        sigemptyset(&set1);
        // SIGALRM만 추가한다.
        sigaddset(&set1, SIGALRM);
        // SIGALRM을 제외한 모든 시그널은 블록되고,
        // 기존의 시그널은 oldset에 저장한다.
        // 현재 프로시져 내의 모든 시그널에 영향을 미친다.(set_timer포함)
        sigprocmask(SIG_BLOCK,&set1,&oldset);
        memset(tempbuf,0,sizeof(tempbuf));
        rlen = 0;
        // setitimer()로 timeout 10초 설정
        set_timer(10);
        parent = 0;
        while(waitpid(pid, &status, WNOHANG)==0)
        {
            cnt = poll((struct pollfd *)&Event, 1, 1*1000);
            if (cnt < 0)
            {
                perror("poll() Error");
                exit(2);
            }
            else
            if (!cnt)
            {
                //poll()로 1초마다, 시그널을 체크한다.
                //블목화된 시그널 가져온다.
                sigpending(&pend);
                // set_timer()는 지정한 시간이 초과되면,
                // SIGALRM 시그널을 발생시킨다.
                // sigismember()로 pend에 있는 가져온 시그널을 체크
                // SIGALRM시그널이면, 부모&자식프로세서를 종료시킨다.
                if (sigismember(&pend,SIGALRM))
                {
                    if (sigismember(&pend, SIGALRM))
                        printf("Get SIGALRM\n");
                    printf("Time Out\n");
                    sio_close(PRIVATE_PORT);
                    //프로시져의 시그널들을 oldset으로 변경한다.
                    sigprocmask(SIG_SETMASK,&oldset,NULL);
                    // set_timer을 풀어야 나중에 발생할 수도 있는
                    // SIGALRM시그널로 인한 종료를 막는다.
                    release_timer();
                    // 자식 프로세서에게 정상종료한다.
                    kill(pid,SIGTERM);
                    return 1;
                }
                printf("parent = %d\n",parent++);
            }
            else
            if (cnt)
            {
                RCH = com_getc();
                tempbuf[rlen++] = RCH;
                printf("tempbuf>>\n");
                printf("%s\n",tempbuf);
            }
        }
        printf("Get status : %d\n",status);
        sio_close(PRIVATE_PORT);
        return status;
    }
    else
    {
        if ((keyhandle = open("/dev/key",O_RDWR)) < 0)
        {
                perror("open key Fail");
                exit(3);
        }
        Event.fd = keyhandle;
        Event.events = POLLIN | POLLERR;
        child = 0;
        printf("parent PID : %u\n",getppid());
        printf("child  PID : %u\n",getpid());
        while(1)
        {
            cnt = poll((struct pollfd *)&Event, 1, 1000);
            if (cnt < 0)
            {
                perror("key poll() Error");
                exit(3);
            }
            else
            if (!cnt)
            {
                printf("child = %d\n",child++);
            }
            else
            if (cnt)
            {
                RCH = GetKey();
                if (RCH == CANCEL)
                {
                    close(keyhandle);
                    //부모프로세서에게 정상종료 시그널을 보낸다.
                    kill(getppid(), SIGTERM);
                    exit(3);
                }
                else printf("RCH = 0x%X\n",RCH);
            }
        }
    }
}