2016-12-09 1 views
1

어제 Synthasizer를 선물로 받았고 데이터를 쓰는 데 관심이있었습니다. 이 작업이 많아 졌는데 여기 몇 가지 노트를 통해 비례하는 프로그램이 있습니다. 그런 다음 Ctrl + C를 눌러서 닫는 것이 깔끔할 것이라고 생각했습니다. 파일 디스크립터를 닫을 때의 문제는 MIDI 장치가 주어진 마지막 노트를 여전히 처리한다는 것입니다. 그래서 mute 함수를 작성했습니다.이 함수는 MIDI 장치에 음소거를 지시합니다. 그거야.신호 기능이있는 다른 기능을 어떻게 호출합니까?

그렇다면 신호 처리기를 종료하기 전에 장치를 음소거 시키려고 했으므로 나는 그 후로 어려움을 겪어 왔습니다. 신호 (SIGINT, intHandler); 함수는 추가 인수를 취하지 않습니다. 그래서 나는 영리하다고 생각하고 신호 함수를 호출하고 장치 파일 설명자와 데이터 포인터를 취하고 끝내기 전에 마지막으로 쓸 수있게 할 함수 인 mySig을 작성합니다.

IDK, 작동 할 수도 있지만 mySig 함수가 처음부터 호출 된 것으로 보이며 스케일링이 발생하지 않습니다.

신호 기능이있는 프로그램을 종료하기 전에 어떻게 음소거 기능을 호출 할 수 있습니까?

이 내 제 1 신호 나눠 프로그램, 메신저 실행 리눅스가하고 프로그램 C.

#include <sys/soundcard.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
static volatile int keepRunning = 1; 
char* device = "/dev/midi1"; 
//function headers: 
void mute(int fd, char *data); 
void intHandler(int dummy); 
void mySig(void (*intHandler)(int dummy), int fd, char *data); 

int main(void){ 

    unsigned int note=50; 

    char data[3] = {0x90, note, 33}; //device address, note, volume 
    int fd = open(device, O_WRONLY, 0); 
    if(fd < 0){ 
     printf("Error: cannot open Synth %s\n", device); 
     exit(1); 
     } 
    signal(SIGINT, intHandler);  
//  mySig(intHandler,fd,data); 

while(keepRunning){ 
    for(note=30; note < 95; note++){ 
     data[1]=note;//change note 
     write(fd, data, sizeof(data)); 
     usleep(100000); 
     if(note>=89){ 
      note =30; 
      } 
     } 
mute(fd,data); //mutes the data stream. 
    close(fd); // close device 

    return 0; 
} 
} 
//functions: 
void mute(int fd, char *data){ 
    data[2]=0;//setVolume to 0 
    write(fd, data, sizeof(data)); 
    close(fd); 
    } 

void mySig(void (*intHandler)(int dummy), int fd, char *data){ 
    printf("my Sig has been called\n"); 
    mute(fd,data); 
    signal(SIGINT, intHandler); 
    } 

void intHandler(int dummy) { 
    printf("my Sig has been called\n"); 
    keepRunning = 1; 
    printf("ctrl+c was pressed, exiting\n"); 
    usleep(10000); 
    exit(1); 
} 
+0

은 더 나은 제목을 제안합니다. – j0h

+0

제목은이 질문에서 유일한 명확한 부분입니다. –

+0

http://stackoverflow.com/questions/6970224/providing-passing-argument-to-signal-handler – dekkard

답변

0

사용에 만 keepRunning 플래그를 지우에 대한 신호 처리기이다. 사용자가 단말기에서 프로그램을 실행

static volatile sig_atomic_t done = 0; 

static void done_handler(int signum) 
{ 
    done = 1; /* Or, in Linux, done = signum. */ 
} 

static int install_done(const int signum) 
{ 
    struct sigaction act; 

    memset(&act, 0, sizeof act); 

    sigemptyset(&act.sa_mask); 
    act.sa_flags = 0; 
    act.sa_handler = done_handler; 
    if (sigaction(signum, &act, NULL) == -1) 
     return errno; 

    return 0; 
} 

경우, 그들은 프로그램이 SIGHUP 신호를 수신합니다, 예기치 않게 터미널을 닫습니다; 개인적으로 , 나는 done 같이 반대 플래그를 선호 Ctrl + CSIGINT 신호를 발생시킵니다. SIGTERM은 종종 프로그램이 종료하도록 요청하는 데 사용됩니다. 그래서 개인적으로하고 싶은데

if (install_done(SIGINT) || 
     install_done(SIGHUP) || 
     install_done(SIGTERM)) { 
     fprintf(stderr, "Cannot install signal handlers: %s.\n", strerror(errno)); 
     return EXIT_FAILURE; 
    } 

main() 일찍. 내 경우

while (!done) { 
     /* Play notes or whatever */ 
    } 

루프 후

, 다음 장치를 닫습니다, 마지막 음이 연주 음소거 -

당신이해야 할 모든

, 당신의 루프를하는 것입니다.

신호가 단지 으로 끝나자 마자 그 신호를 고려하자. 즉시 끝내라는 요구가 아닙니다. 프로그램은 퇴거를 요구하는 신호를 받으면 필요한 정리 작업을해야합니다. 프로그램에서 을 바로 종료하려면을 누르십시오. SIGKILL으로 프로세스를 종료 할 수 있습니다.

관련 문제