小孩通知妈妈的事情有很多:饿了、渴了、想找人玩。 Linux 系统中也有很多信号,在 Linux 内核源文件 include\uapi\asm-generic\signal.h 中,有很多信号的宏定义:
驱动程序通知 APP 时,它会发出“SIGIO”这个信号,表示有“IO 事件”要处理。 就 APP 而言,你想处理 SIGIO 信息,那么需要提供信号处理函数,并且要跟 SIGIO 挂钩。这可以通过一个 signal 函数来“给某个信号注册处理函数”,用法如下:
除了注册 SIGIO 的处理函数,APP 还要做什么事?想想这几个问题:
① 内核里有那么多驱动,你想让哪一个驱动给你发 SIGIO 信号? APP 要打开驱动程序的设备节点。
② 驱动程序怎么知道要发信号给你而不是别人? APP 要把自己的进程 ID 告诉驱动程序。
③ APP 有时候想收到信号,有时候又不想收到信号: 应该可以把 APP 的意愿告诉驱动:设置 Flag 里面的 FASYNC 位为 1,使能“异步通知”。
① 编写信号处理函数:
static void sig_func(int sig)
{
int val;
read(fd, &val, 4);
printf("get button : 0x%x\n", val);
}
② 注册信号处理函数:
signal(SIGIO, sig_func);
③ 打开驱动:
fd = open(argv[1], O_RDWR);
④ 把进程 ID 告诉驱动:
fcntl(fd, F_SETOWN, getpid());
⑤ 使能驱动的 FASYNC 功能:
flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | FASYNC);