2016-11-01 5 views
1

4 대의 카메라에서 동시에 비디오를 캡처하는 프로그램을 작성하고 있으므로 각 카메라를 제어하는 ​​4 개의 스레드가 있습니다. 각 스레드에서 키를 누르기 전까지 계속 캡쳐를하고 키는 'q'또는 그와 일치합니다. 나는이 같은 인터넷과 발견 방법을 검색 키를 누를 때 손잡이를 들어리눅스에서 다중 스레드 프로그램에서 C++이 키 누르기를 처리합니다.

:

static void *capureVideo(void *para) { 
    // Some code... 
    while(!(kbhit('q') { 
     // Read frame... 
    } 
} 

void creatThread() { 
    if (pthread_create(&threadID, NULL, capureVideo, this) != 0) { 
     perror("thread create faild"); 
     exit(EXIT_FAILURE); 
    }  
} 

하면 프로그램이 실행 :

#include <stdio.h> 
#include <termios.h> 
#include <unistd.h> 
#include <fcntl.h> 

int kbhit(int key) { 
    int ch; 
    int old_file_status; 
    struct termios old_term_attr; 
    struct termios new_term_attr; 

    tcgetattr(STDIN_FILENO, &old_term_attr); 
    new_term_attr = old_term_attr; 
    new_term_attr.c_lflag &= ~(ICANON | ECHO); 
    tcsetattr(STDIN_FILENO, TCSANOW, &new_term_attr); 

    old_file_status = fcntl(STDIN_FILENO, F_GETFL, 0); 
    fcntl(STDIN_FILENO, F_SETFL, old_file_status | O_NONBLOCK); 

    ch = getchar(); 

    tcsetattr(STDIN_FILENO, TCSANOW, &old_term_attr); 
    fcntl(STDIN_FILENO, F_SETFL, old_file_status); 

    if(ch == c) 
     return 1; 
    return 0; 
} 

그리고 (완료되지 않음)이 같은 코드를 내 VideoCapture 클래스의

일단 'q'키를 4 번 누르면 프로그램이 종료되고 제어가 쉘로 돌아갑니다. 그러나 특정 상황 (정확하게 모르지만 매번 발생하지 않음)에서 문제가 발생합니다. 즉, 쉘에 명령을 입력하면 입력 한 문자가 표시되지 않습니다. Enter 키를 누르면 명령이 제출됩니다.

이 문제점을 검색하여 다음을 찾았습니다. https://askubuntu.com/a/172747 : 터미널 특성이 올바르게 재설정되지 않았 음을 나타냅니다. 그러나 keypress 핸들 코드에서이 두 줄의 코드가 나타났습니다.

tcsetattr(STDIN_FILENO, TCSANOW, &old_term_attr); 
fcntl(STDIN_FILENO, F_SETFL, old_file_status); 

은 터미널 속성을 재설정했습니다. 그래서 멀티 스레드와 관련이 있는지 궁금합니다. 나는 mutlithread 프로그래밍에 익숙하지 않고 그것을 스스로 해결할 수 없기 때문에 누군가 나를 도울 수 있습니까? 모든 제안은 높이 평가됩니다. 터미널 속성은 완전히 무작위이없이

tcgetattr(STDIN_FILENO, &old_term_attr); 
new_term_attr = old_term_attr; 
new_term_attr.c_lflag &= ~(ICANON | ECHO); 
tcsetattr(STDIN_FILENO, TCSANOW, &new_term_attr); 

이 고정되고 :

+0

CTRL-C 또는 다른 신호로 프로그램이 종료되면 수동으로 터미널 속성을 재설정해도 아무런 성과가 없습니다. 명시 적으로 터미널 속성을 기본값으로 재설정하는 것 외에도, 시그널 핸들러는 최소한'SIGINT','SIGHUP','SIGTERM', 그리고 아마도'SIGQUIT'에 대해서'sigaction()'을 통해 설정되어야합니다. 터미널 속성을 기본값으로 재설정합니다. –

+0

다른 스레드가'getchar()'을 입력하기 직전에 터미널 속성을 기본값으로 재설정하고 표준 입력에서 블로킹을 끝내는 경합 조건도 있습니다. 전반적으로 버그 투성이입니다. 터미널은 처음에는 비 차단 모드와 비표준 처리 모드로 설정되어야하며 프로그램이 종료되기 전에만 재설정되어야합니다. 그리고'getchar()'대신에 파일 기술자 0에서'read()'를 사용하십시오. –

+0

'터미널은 비 차단 모드와 비표준 처리 모드로 시작될 때 한 번만 설정되어야하고 프로그램이 종료되기 전에 재설정되어야합니다 그것이 싱글 톤 패턴을 사용할 수 있다는 것을 의미합니까? 또한'getchar()'이 권장되지 않는 이유를 설명 할 수 있습니까? 고맙습니다. @SamVarshavchik – Gzy

답변

0

당신은 여러 스레드가 동시에 (정적) 단자의 매개 변수를 변경하려고합니다. 수정 사항은 뮤텍스를 사용하여이를 보호하거나 키보드를 읽도록 다른 스레드를 생성하고 'q'를 눌렀을 때의 플래그를 설정하는 것입니다. 다른 스레드에서 읽을 수있는 내용을 다음과 같이 할 수 있습니다.

(pardon the psudo code) 
bool shouldRun = true 


void captureThreadMain { 
    while (shouldRun) { 
     captureFrame(); 
    } 
} 

void keyboardPressMain { 
    while (getKey('q')); 
    shouldRun = false; 
} 

이렇게하면 'q'를 한 번만 누르면 모든 프레임 수집 스레드가 중지됩니다.

+0

키보드를 읽고 전역 변수'bool shouldCapture'를 설정하는 새 스레드를 생성합니다. 작동 했으니 까, 고마워요! – Gzy