이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4FE7CE007255739A07C68401
원문 작성일 : 2012.06.25

 

------------------------------------------------------------------------------------------

 

첨부파일 : getChar.zip

 

 

getchar() 함수를 클래스화 시켜서 좀 편하게 써보자 생각함.
getChar.h 랑 getChar.cpp 두개의 파일을 둠.
쉽게 생각했다가 프로그램 종료 시, getchar() 에서 블럭걸리는 증상 발견됨.
하루종일 방법을 고민하다 못찾고 kldp 에 물어 봄.
http://kldp.org/node/133482
pipe(), select() 함수를 사용하여 어케어케 함. 공부할게 생겼다.
위 답변을 가지고 아래처럼 정리하여 동작함을 확인하였다.
제일 아래 main.cpp 에 클래스 사용 예제가 있다.

 


############ getChar.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef _GETCHAR_H_
#define _GETCHAR_H_
#include "pthread.h"
 
typedef void (*CALLBACK_GETCHAR)(char ) ;
 
class CGetChar
{
public :
        CGetChar() ;
        ~CGetChar() ;
        int init(CALLBACK_GETCHAR callback) ;
        int stop() ;
        int destroy(void) ;
 
        // This only use in callback function.
        CALLBACK_GETCHAR m_callbackGetChar ;
        int m_flagStop ;
private :
        pthread_t m_thGetChar ;
};
#endif
 

 

 

 

############ getChar.cpp

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "getChar.h"
#include<stdio.h>
#include<termio.h>
#include<unistd.h>
#include<fcntl.h>
 
static int poll_getch[2] = {-1, -1} ;
 
void* threadGetChar(void* pData)
{
        int fd_cancel, fd_stdin, ch ;
        struct termios org_term, new_term ;
        fd_set rdfds ;
        int max_fd ;
        int r ;
        CGetChar* pGetChar = (CGetChar*)pData ;
 
        while(1)
        {
                fd_cancel = poll_getch[0] ;
                fd_stdin = fileno(stdin) ;
 
                ch = -1 ;
                tcgetattr(fd_stdin,&org_term) ;
                new_term = org_term ;
                new_term.c_lflag&= ~(ICANON | ECHO) ;
                new_term.c_cc[VTIME] = 0 ;
                new_term.c_cc[VMIN] = 1 ;
                tcsetattr(fd_stdin, TCSANOW,&new_term) ;
 
                FD_ZERO(&rdfds) ;
                FD_SET(fd_stdin,&rdfds) ;
                FD_SET(fd_cancel,&rdfds) ;
 
                max_fd = fd_stdin>fd_cancel ? fd_stdin : fd_cancel ;
 
                r = select(max_fd + 1,&rdfds, NULL, NULL, NULL) ;
 
                if( r>0&&FD_ISSET(fd_stdin,&rdfds))
                        ch = getchar() ;
 
                tcsetattr(fd_stdin, TCSANOW,&org_term) ;
                pGetChar->m_callbackGetChar(ch) ;
 
                if(pGetChar->m_flagStop)
                        break ;
 
                usleep(1000) ;
        }
        return 0 ;
}
 
CGetChar::CGetChar() :
m_flagStop(0)
{
}
 
CGetChar::~CGetChar()
{
}
 
int CGetChar::init(CALLBACK_GETCHAR callback)
{
        if(pipe(poll_getch)<0)
        {
                perror("pipe") ;
                return 1 ;
        }
 
        m_callbackGetChar = callback;
        pthread_create(&m_thGetChar, NULL,&threadGetChar, (void*)this) ;
        return 1 ;
}
 
int CGetChar::stop()
{
        m_flagStop = 1 ;
        int fd = poll_getch[0] ;
 
        if( fd>= 0)
                write(poll_getch[1],&fd, 1) ;
        return 1 ;
}
 
int CGetChar::destroy(void)
{
        int nStatus ;
        m_flagStop = 0 ;
 
        if(!m_flagStop)
        {
                int fd = poll_getch[0] ;
                if( fd>= 0)
                        write(poll_getch[1],&fd, 1) ;
                m_flagStop = 1 ;
        }
 
        pthread_join(m_thGetChar, (void**)&nStatus) ;
        return 1 ;
}
 

 

############# main.cpp

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<cstdio>
#include<unistd.h>
#include "getChar.h"
#include<termio.h>
 
typedef void (*CALLBACK_GETCHAR)(char ) ;
static char m_char ;
 
void cbGetChar(char ch)
{
        m_char = ch ;
        printf("ch : %c\n", m_char) ;
}
 
int main()
{
        CGetChar getChar ;
        getChar.init(&cbGetChar) ;
 
        while(1)
        {
                if(m_char == 'q')
                {
                        getChar.stop() ;
                        break ;
                }
                usleep(1000) ;
        }
 
        getChar.destroy() ;
        usleep(1000) ;
        return 1 ;
}
 

첨부파일 : getChar.zip

+ Recent posts