윈도우즈는 WaitForSingleObject() API 함수를 이용하면 아주 간단히 끝낼 수 있지만, 맥을 비롯한 POSIX 쪽으로 넘어가면 상황이 좀 더 복잡해진다. 기본적으로 유닉스는 stdin을 통해 비동기 입출력을 할 수 없기 때문이다.
하지만 기본적으로 안 된다는 거지, 불가능하다는 소린 아니다.
여기 도움이 될 만한 링크가 하나 있다.
Non-blocking user input in loop without ncurses.
이 글을 참고하면 앞 포스팅에서 말했던 nonblocking 입력을 구현해 낼 수 있지만, 윈도우즈에서와 다른 점이 하나 있다. echo가 없어지지 않는다는 점이다. 이 문제는 termios 설정 과정에서 플래그를 조금만 조작해 주면 해결할 수 있다.
이건 여담인데.. BSD 계열의 개선된 폴링 메커니즘인 kqueue는 애초에 stdin, tty 등 콘솔 장치와 연계되지가 않고, poll의 경우는 타이거에서 stdin과 연계가 안되는 '버그'가 있다. 결국 select 뿐이다...
확인은 안해봤지만 위 코드는 아마 POSIX 표준을 만족하는 운영체제에서는 다 실행될 것으로 본다.
이건 여담 2인데, 사파리에선 텍스트큐브 위지윅 편집기가 동작하지 않는 것 같다.
에코 관련해서 버그가 있다. 손좀 봐야겠다.
하지만 기본적으로 안 된다는 거지, 불가능하다는 소린 아니다.
여기 도움이 될 만한 링크가 하나 있다.
Non-blocking user input in loop without ncurses.
이 글을 참고하면 앞 포스팅에서 말했던 nonblocking 입력을 구현해 낼 수 있지만, 윈도우즈에서와 다른 점이 하나 있다. echo가 없어지지 않는다는 점이다. 이 문제는 termios 설정 과정에서 플래그를 조금만 조작해 주면 해결할 수 있다.
/** @a http://cc.byexamples.com/20070408/non-blocking-user-input-in-loop-without-ncurses/ with few modification. */ #include<sys/time.h> // sys time.h #include<sys/types.h> // sys types.h #include<termios.h> // termios.h #include<unistd.h> // unistd.h #include<cstdio> // C라면 그냥 stdio.h로 바꿔 주면 된다.. #define NB_ENABLE 0 #define NB_DISABLE 1 void nonblock(int state) { struct termios ttystate; // 터미널 상태를 읽어온다. // STDIN_FILENO = fileno(stdin) (정수형이다) tcgetattr(STDIN_FILENO, &ttystate); if (state==NB_ENABLE) { //turn off canonical mode ttystate.c_lflag &= ~ICANON; // 에코를 끄는 방법은 간단하다 ttystate.c_lflag &= ~ECHO; // 최소로 읽어올 글자수를 정함 ttystate.c_cc[VMIN] = 1; } else if (state==NB_DISABLE) { // Canonical 모드를 다시 사용한다 ttystate.c_lflag |= ICANON; // 에코도 복구해줘야 한다... ㅡㅡ ttystate.c_lflag |= ECHO; } // 지정한 옵션대로 터미널을 설정한다. tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); } int kbhit() { struct timeval tv; fd_set fds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0 select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); return FD_ISSET(STDIN_FILENO, &fds); } int main() { char c; int i=0; nonblock(NB_ENABLE); while(!i) { usleep(1); i=kbhit(); if (i!=0) { c=fgetc(stdin); if (c=='q') i=1; else i=0; } } printf("\n you hit %c. \n",c); nonblock(NB_DISABLE); return 0; }
이건 여담인데.. BSD 계열의 개선된 폴링 메커니즘인 kqueue는 애초에 stdin, tty 등 콘솔 장치와 연계되지가 않고, poll의 경우는 타이거에서 stdin과 연계가 안되는 '버그'가 있다. 결국 select 뿐이다...
확인은 안해봤지만 위 코드는 아마 POSIX 표준을 만족하는 운영체제에서는 다 실행될 것으로 본다.
이건 여담 2인데, 사파리에선 텍스트큐브 위지윅 편집기가 동작하지 않는 것 같다.
에코 관련해서 버그가 있다. 손좀 봐야겠다.

댓글을 달아 주세요