Linux驅(qū)動(dòng)實(shí)踐:驅(qū)動(dòng)程序如何發(fā)送【信號(hào)】給應(yīng)用程序?
掃描二維碼
隨時(shí)隨地手機(jī)看文章
作 ?者:道哥,10 年嵌入式開發(fā)老兵,專注于:C/C 、嵌入式、Linux。關(guān)注下方公眾號(hào),回復(fù)【書籍】,獲取 Linux、嵌入式領(lǐng)域經(jīng)典書籍;回復(fù)【PDF】,獲取所有原創(chuàng)文章( PDF 格式)。目錄
- kill 命令和信號(hào)
- 使用 kill 命令發(fā)送信號(hào)
- 多線程中的信號(hào)
- 信號(hào)注冊(cè)和處理函數(shù)
- 驅(qū)動(dòng)程序代碼示例:發(fā)送信號(hào)
- 功能需求
- 驅(qū)動(dòng)程序代碼
- 驅(qū)動(dòng)模塊 Makefile
- 編譯和加載
- 應(yīng)用程序代碼示例:接收信號(hào)
- 注冊(cè)信號(hào)處理函數(shù)
- 測(cè)試驗(yàn)證
GPIO
Linux驅(qū)動(dòng)實(shí)踐:如何編寫【 GPIO 】設(shè)備的驅(qū)動(dòng)程序?。控制的方向是從應(yīng)用層到驅(qū)動(dòng)層:kill 命令和信號(hào)
使用 kill 命令發(fā)送信號(hào)
關(guān)于Linux
操作系統(tǒng)的信號(hào),每位程序員都知道這個(gè)指令:使用 kill 工具來(lái)“殺死”一個(gè)進(jìn)程:$ kill -9 <進(jìn)程的 PID>
這個(gè)指令的功能是:向指定的某個(gè)進(jìn)程發(fā)送一個(gè)信號(hào) 9,這個(gè)信號(hào)的默認(rèn)功能是:是停止進(jìn)程。雖然在應(yīng)用程序中沒(méi)有主動(dòng)處理這個(gè)信號(hào),但是操作系統(tǒng)默認(rèn)的處理動(dòng)作是終止應(yīng)用程序的執(zhí)行。除了發(fā)送信號(hào) 9
,kill
命令還可以發(fā)送其他的任意信號(hào)。在 Linux
系統(tǒng)中,所有的信號(hào)都使用一個(gè)整型數(shù)值來(lái)表示,可以打開文件 /usr/include/x86_64-linux-gnu/bits/signum.h
(你的系統(tǒng)中可能位于其它的目錄) 查看一下,比較常見的幾個(gè)信號(hào)是:/* 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)
信號(hào) 9
對(duì)應(yīng)著 SIGKILL
,而信號(hào)11
(SIGSEGV
)就是最令人討厭的Segmentfault!這里還有一個(gè)地方需要注意一下:實(shí)時(shí)信號(hào)和非實(shí)時(shí)信號(hào),它倆的主要區(qū)別是:如果我們的程序設(shè)計(jì),通過(guò)信號(hào)機(jī)制來(lái)完成一些功能,那么為了確保信號(hào)不會(huì)丟失,肯定是使用實(shí)時(shí)信號(hào)的。從文件
- 非實(shí)時(shí)信號(hào):操作系統(tǒng)不確保應(yīng)用程序一定能接收到(即:信號(hào)可能會(huì)丟失);
- 實(shí)時(shí)信號(hào):操作系統(tǒng)確保應(yīng)用程序一定能接收到;
signum.h
中可以看到,實(shí)時(shí)信號(hào)從 __SIGRTMIN
(數(shù)值:32
) 開始。多線程中的信號(hào)
我們?cè)诰帉憫?yīng)用程序時(shí),雖然沒(méi)有接收并處理SIGKILL
這個(gè)信號(hào),但是一旦別人發(fā)送了這個(gè)信號(hào),我們的程序就被操作系統(tǒng)停止掉了,這是默認(rèn)的動(dòng)作。那么,在應(yīng)用程序中,應(yīng)該可以主動(dòng)聲明接收并處理指定的信號(hào),下面就來(lái)寫一個(gè)最簡(jiǎn)單的實(shí)例。在一個(gè)應(yīng)用程序中,可能存在多個(gè)線程;當(dāng)有一個(gè)信號(hào)發(fā)送給此進(jìn)程時(shí),所有的線程都可能接收到,但是只能有一個(gè)線程來(lái)處理;在這個(gè)示例中,只有一個(gè)主線程來(lái)接收并處理信號(hào);
信號(hào)注冊(cè)和處理函數(shù)
按照慣例,所有應(yīng)用程序文件都創(chuàng)建在~/tmp/App
目錄中。// 文件:tmp/App/app_handle_signal/app_handle_signal.c
#include
#include
#include
#include
#include
// 信號(hào)處理函數(shù)
static void signal_handler(int signum, siginfo_t *info, void *context)
{
// 打印接收到的信號(hào)值
printf("signal_handler: signum = %d \n", signum);
}
int main(void)
{
int count = 0;
// 注冊(cè)信號(hào)處理函數(shù)
struct sigaction sa;
sigemptyset(