Linux驱动实践:驱动程序如何发送【信号】给应用程序?
扫描二维码
随时随地手机看文章
作 者:道哥,10 年嵌入式开发老兵,专注于:C/C 、嵌入式、Linux。关注下方公众号,回复【书籍】,获取 Linux、嵌入式领域经典书籍;回复【PDF】,获取所有原创文章( PDF 格式)。目录
- kill 命令和信号
- 使用 kill 命令发送信号
- 多线程中的信号
- 信号注册和处理函数
- 驱动程序代码示例:发送信号
- 功能需求
- 驱动程序代码
- 驱动模块 Makefile
- 编译和加载
- 应用程序代码示例:接收信号
- 注册信号处理函数
- 测试验证
GPIO
Linux驱动实践:如何编写【 GPIO 】设备的驱动程序?。控制的方向是从应用层到驱动层:那么,如果想让程序的执行路径从下往上,也就是从驱动层传递到应用层,应该如何实现呢?最容易、最简单的方式,就是通过发送信号!这篇文章继续以完整的代码实例来演示如何实现这个功能。kill 命令和信号
使用 kill 命令发送信号
关于Linux
操作系统的信号,每位程序员都知道这个指令:使用 kill 工具来“杀死”一个进程:$ kill -9 <进程的 PID>
这个指令的功能是:向指定的某个进程发送一个信号 9,这个信号的默认功能是:是停止进程。虽然在应用程序中没有主动处理这个信号,但是操作系统默认的处理动作是终止应用程序的执行。除了发送信号 9
,kill
命令还可以发送其他的任意信号。在 Linux
系统中,所有的信号都使用一个整型数值来表示,可以打开文件 /usr/include/x86_64-linux-gnu/bits/signum.h
(你的系统中可能位于其它的目录) 查看一下,比较常见的几个信号是:/* Signals. */
#define SIGINT 2 /* Interrupt (ANSI). */
#define SIGKILL 9 /* Kill, unblockable (POSIX). */
#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */
#define SIGSEGV 11 /* Segmentation violation (ANSI). */
#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */
...
...
#define SIGSYS 31 /* Bad system call. */
#define SIGUNUSED 31
#define _NSIG 65 /* Biggest signal number 1
(including real-time signals). */
/* These are the hard limits of the kernel. These values should not be
used directly at user level. */
#define __SIGRTMIN 32
#define __SIGRTMAX (_NSIG - 1)
信号 9
对应着 SIGKILL
,而信号11
(SIGSEGV
)就是最令人讨厌的Segmentfault!这里还有一个地方需要注意一下:实时信号和非实时信号,它俩的主要区别是:如果我们的程序设计,通过信号机制来完成一些功能,那么为了确保信号不会丢失,肯定是使用实时信号的。从文件
- 非实时信号:操作系统不确保应用程序一定能接收到(即:信号可能会丢失);
- 实时信号:操作系统确保应用程序一定能接收到;
signum.h
中可以看到,实时信号从 __SIGRTMIN
(数值:32
) 开始。多线程中的信号
我们在编写应用程序时,虽然没有接收并处理SIGKILL
这个信号,但是一旦别人发送了这个信号,我们的程序就被操作系统停止掉了,这是默认的动作。那么,在应用程序中,应该可以主动声明接收并处理指定的信号,下面就来写一个最简单的实例。在一个应用程序中,可能存在多个线程;当有一个信号发送给此进程时,所有的线程都可能接收到,但是只能有一个线程来处理;在这个示例中,只有一个主线程来接收并处理信号;
信号注册和处理函数
按照惯例,所有应用程序文件都创建在~/tmp/App
目录中。// 文件:tmp/App/app_handle_signal/app_handle_signal.c
#include
#include
#include
#include
#include
// 信号处理函数
static void signal_handler(int signum, siginfo_t *info, void *context)
{
// 打印接收到的信号值
printf("signal_handler: signum = %d \n", signum);
}
int main(void)
{
int count = 0;
// 注册信号处理函数
struct sigaction sa;
sigemptyset(