捕获信号并暂停字符设备驱动程序

时间:2017-12-08 02:47:19

标签: c linux signals linux-device-driver daemon

我是C Programming的新手,并不完全了解信号捕捉的工作原理,并且与字符设备驱动程序一致。我很感激一些帮助,但我需要说明这是我第一个C Programming课程中的项目。所以我没有发布任何直接代码,只是我最初方法的一个例子。

我的项目需要接受信号输入并将该信号设置为变量以传递给我的character device driver。我编写的另一个程序需要访问该变量的值,以便在读取时执行某个结果。我试图运行我的控制程序(<name> &),但它会立即退出。我通过在命令提示符下输入ps进行仔细检查,然后该过程就消失了。

基本上我需要我的控制程序暂停并等待接收信号。收到后,如果信号匹配,则将变量设置为其值。否则,如果它是SIGTERM它将结束或pause(),它将等待直到收到满足另一个条件的另一个信号。目前,当我使用&编译并运行它时,它只是运行并退出。以下是我的代码示例:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

static int file_state;                    //variable to pass to the driver for recording

void sig_handler(int sig);        

void sig_handler(int sig){
    while(1){
        if(sig == SIGRTMIN){
            printf("SIG = SIGRTMIN\n");
            file_state = 0;
        }else if(sig == SIGRTMIN+1){
            printf("SIG = SIGRTMIN1\n");
            file_state = 1;
        }else if(sig == SIGTERM){
            printf("Exiting\n");
            exit(0);                         //exit
        }else{
            printf("SIG = %i\n", sig);
            pause();                        //doesn't match, pause for next signal
        }
    }
}

int main(){
    signal(SIGINT, sig_handler);
    //return 0;  //tried with and without
}

我等到这个daemon收到一个信号,让device driver进入特定模式。我还没有输入任何write()方法,因为我正在尝试使用kill()发送信号时执行此步骤,并使用printf()返回正确的响应。  我的问题是,当我在等待打破pause()循环的信号时,我似乎无法将此保持在if模式。更糟糕的是(除了我缺乏知识和编程之外)我甚至无法保持这个daemon打开足够长的时间来尝试发送信号。一旦我可以暂停并接收信号,我计划使用系统write()方法将file_state变量写入/dev/<filename>,这将在我的可执行文件中交叉引用。

我离我有多远?这是(我相信)我坚持的最后一部分,我无法弄清楚应该如何处理这个问题。我在网上看过,大约有95%的例子都包含了我们还没有学到的方法。如果没有,这些示例更简单,它们不包括将值传递给character device driver以供另一个程序使用驱动程序时使用。

非常感谢任何帮助。

ETA 我已经更新了我的代码,所以现在它一直保持打开状态,直到收到信号。问题是我想要pause()并保持打开状态,直到收到SIGTERM信号,打破循环并结束程序。我似乎无法让循环正确。当收到任何信号时,即使在int循环中输入条件while()变量仍然会被破坏。以下是我的更新代码:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

static int file_state;                    //variable to pass to the driver for recording

int keep_alive = 1;                       //added for conditional checking to keep the while 
                                          //loop open to receive more than one signal

void sig_handler(int sig);        

void sig_handler(int sig){
    if(sig == SIGRTMIN){
        printf("SIG = SIGRTMIN\n");
        file_state = 0;
    }else if(sig == SIGRTMIN+1){
        printf("SIG = SIGRTMIN1\n");
        file_state = 1;
    }else if(sig == SIGTERM){
        keep_alive = 0;                     
    }else{
    }
}

int main(){
    do{
        signal(SIGINT, sig_handler);
        pause();                           //thought pausing here would help with waiting for a new signal
    }while(keep_alive == 1);               //keep looping until false
    return 0;                              //tried with and without
}

我正在试图找出一种方法来保持这个过程并使信号捕获循环活着,直到收到特定的信号。我无法理解我的生活。

ETA 2

发现了我的问题。我没有注意并完全理解signal()方法。第一个参数需要您尝试捕获的确切信号。我正在使用SIGINT,我理解它是你想要捕获的中断的“类”。然后在signal_handler()函数中,您将指定要捕获的中断类型。但是,实际上它正在寻找你感兴趣的完全信号。所以在我的示例代码中,我应该一直在使用:

int main(){
    if(signal(SIGRMIN, sig_handler) == SIG_ERR){
         printf("can't catch SIGRMIN Signal.\n")
    }
...
}

我将使用我的新脚本作为答案进行更新,如果有人认为应该采取不同的方式或有任何建设性的批评,请告诉我。再次感谢!

2 个答案:

答案 0 :(得分:0)

有2个部分,第1个用户空间,发生信号的产生和捕获。这与内核驱动程序无关。你的代码看起来还不错。

第二个是在捕获到信号时与驱动程序进行交互。对于char驱动程序,请查看此link。你可以简单地写一个值写(fd,1,&amp; buf);来自用户空间程序并在char驱动程序中实现相应的write()。

答案 1 :(得分:0)

所以我找到了我的问题,现在它正在运作。下面是我的固定代码,它会在捕获时产生正确的响应。我添加了一个for()循环来捕捉任何其他我不担心的信号并没有停止我的过程,只有SIGTERM会。期待得到批评以及为什么我永远不想做我的方法。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

static int file_state;                    //variable to pass to the driver for recording

void sig_handler(int sig);        

void sig_handler(int sig){
    if(sig == SIGRTMIN){
        printf("SIG = SIGRTMIN\n");
        file_state = 0;
    }else if(sig == SIGRTMIN+1){
        printf("SIG = SIGRTMIN1\n");
        file_state = 1;
    }else if(sig == SIGTERM){
        exit(0);
        EXIT_SUCCESS;                     
    }else{
        printf("SIGNAL CAUGHT #%d\n", sig);
    }
}

int main(){
    if(signal(SIGRTMIN, sig_handler)==SIG_ERR){
         printf("Unable to catch SIGRTMIN\n");
    }
    if(signal(SIGRTMIN+1, sig_handler)==SIG_ERR){
         printf("Unable to catch SIGRTMIN+1\n");
    }
    if(signal(SIGTERM, sig_handler)==SIG_ERR){
         printf("Unable to terminate process.\n");
    }

    //This for loop will catch all other signals except the un-catchable and
    //other user-specified above signal #31.

    int s;
    for(s = 0; s < 32; s++){
         signal(s, sig_handler);
    }

    while(1);
    pause();
    return 0;
}