gpt4 book ai didi

c - 如何使用信号函数调用其他函数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:42:37 25 4
gpt4 key购买 nike

昨天我收到了一个合成器作为礼物,并且有兴趣向它写入数据。我做了这么多工作,这是一个通过一些笔记扩展的程序。然后我认为让它捕捉 Ctrl+C 信号并关闭会很整洁。仅关闭文件描述符的问题是 MIDI 设备仍在处理最后给出的音符,因此我编写了静音函数,它告诉 MIDI 设备静音。这样可行。

然后我尝试让信号处理程序在退出之前使设备静音,从那以后我一直在努力。信号(SIGINT,intHandler);函数不会接受额外的参数。所以我想我会很聪明,并编写一个调用信号函数并获取设备文件描述符和数据指针的函数 mySig,并且能够在退出之前进行最后一次写入。

IDK,这甚至可能有效,但 mySig 函数似乎从一开始就被调用,并且从未发生缩放。

在使用信号函数退出程序之前,如何调用我的静音函数?

这是我的第一个信号处理程序,我运行的是 linux,程序是用 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);
}

最佳答案

使用信号处理程序仅清除您的 keepRunning 标志。就个人而言,我更喜欢相反的标志,如 done:

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信号; Ctrl+C 产生一个 SIGINT 信号; 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 终止进程。

关于c - 如何使用信号函数调用其他函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41064891/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com