美文网首页走在路上ThinkPHP烟风
Linux驱动编程之信号机制

Linux驱动编程之信号机制

作者: 超低空 | 来源:发表于2014-09-18 21:56 被阅读3250次

    编写Linux驱动的过程中,需要考虑与应用程序交互的情况。当设备驱动完成某项任务或者达到某种状态的时候(如设备文件可以写入或读取),此时可以让驱动程序主动通知应用程序进行相应的处理(个人感觉类似于Android应用程序中的广播)。这种在Linux内核中使用的“广播”就是本文要详细介绍的“信号”。

    1. Linux信号类型

    使用信号进行进程间通信(IPC)是LInux系统的重要通信机制。在Linux系统中,异步通知使用信号来实现。以下是Linux系统支持的信号及其含义:(asm/signal.h)

    #define SIGHUP       1
    #define SIGINT       2
    #define SIGQUIT     3
    #define SIGILL       4
    #define SIGTRAP     5
    #define SIGABRT     6
    #define SIGIOT       6
    #define SIGBUS       7
    #define SIGFPE       8
    #define SIGKILL     9
    #define SIGUSR1     10
    #define SIGSEGV     11
    #define SIGUSR2     12
    #define SIGPIPE     13
    #define SIGALRM     14
    #define SIGTERM     15
    #define SIGSTKFLT     16
    #define SIGCHLD     17
    #define SIGCONT     18
    #define SIGSTOP     19
    #define SIGTSTP     20
    #define SIGTTIN     21
    #define SIGTTOU     22
    #define SIGURG       23
    #define SIGXCPU     24
    #define SIGXFSZ     25
    #define SIGVTALRM     26
    #define SIGPROF     27
    #define SIGWINCH       28
    #define SIGIO         29
    #define SIGPOLL     SIGIO
    #define SIGPWR       30
    #define SIGSYS       31
    
    /* These should not be considered constants from userland.  */
    #define SIGRTMIN       32
    #define SIGRTMAX       _NSIG
    
    #define SIGSWI       32
    

    注:以上除了SISSTOP和SIGKILL两个信号外,进程可以忽略或捕获其他的全部信号。

    如果其中一个信号被捕获,说明在应用程序中为该信号指定了一个处理函数。如果一个信号没有被某个进程捕获,Linux内核会对该信号采用默认处理方式进行处理。

    2. 接收Linux信号

    在用户程序中,为了捕捉信号,需要使用signal函数来设置信号接收的回调函数:

    void  (*signal(int signum, void (* handler)(int)))(int);
    

    从signal函数原型上看有些复杂, 但主要有两个参数:signum和handler,signum表示信号代码,handler表示回调函数。

    在应用程序中捕获信号比较简单,如下例子:

    void signal_handler(int signo)
    {
            printf("捕获到%d信号\n",signo);
    }
    main()
    {
            printf("信号ID是%d\n",getpid());
            signal(SIGINT, signal_handler);            //设置SIGINT信号的处理函数
            signal(SIGHUP, signal_handler);          //设置SIGHUP信号的处理函数
            signal(SIGQUIT, signal_handler);         //设置SIGQUIT信号的处理函数
           getchar();
    }
    

    以上代码示例了如何捕捉信号,并设置相应的处理函数。

    3、发送信号

    在设备驱动和应用程序的异步通知过程中,驱动程序需要向应用程序发出信号,为了完成发送信号的任务,需要完成以下工作:

    1. 支持F_SETDOWN命令。通过这个命令可以设置file_f_owner为对应进程的ID。
    2. 支持F_SETFL命令的处理。每当FASYNC标志改变时,驱动程序中的fasync函数就会执行。
    3. 再满足条件时,调用kill_fasync函数发送相应的信号。

    接收信号可以用signal函数和sigaction函数来完成,他们之间有以下几个区别:
    signal函数
    1、signal在调用handler之前先把信号的handler指针恢复;sigaction调用之后不会恢复handler指针,直到再次调用sigaction修改handler指针。
    :这样,(1)signal就会丢失信号,而且不能处理重复的信号,而sigaction就可以。因为signal在得到信号和调用handler之间有个时间把handler恢复了,这样再次接收到此信号就会执行默认的handler。(虽然有些调用,在handler的以开头再次置handler,这样只能保证丢信号的概率降低,但是不能保证所有的信号都能正确处理)
    2、signal在调用过程不支持信号block;sigaction调用后在handler调用之前会把屏蔽信号(屏蔽信号中自动默认包含传送的该信号)加入信号中,handler调用后会自动恢复信号到原先的值。
    (2)signal处理过程中就不能提供阻塞某些信号的功能,sigaction就可以阻指定的信号和本身处理的信号,直到handler处理结束。这样就可以阻塞本身处理的信号,到handler结束就可以再次接受重复的信号。

    在驱动程序编写过程中与应用程序进行交互是非常重要的,他可以确保用户程序能够顺利执行,也能保证驱动能够更好地服务于用户。以上是本人学习中的一些总结,希望对大家有帮助~~

    相关文章

      网友评论

      • 超低空:@秋纫 嗯,好的! 谢谢关注 :blush:
      • 秋纫:求写完,欢迎投稿到「硬件&嵌入式」专题 :wink:

      本文标题:Linux驱动编程之信号机制

      本文链接:https://www.haomeiwen.com/subject/upkutttx.html