国产无码免费,人妻口爆,国产V在线,99中文精品7,国产成人无码AA精品一,制度丝袜诱惑av,久久99免费麻辣视频,蜜臀久久99精品久久久久久酒店
        訂閱
        糾錯
        加入自媒體

        Linux:驅動程序如何發送【信號】給應用程序?

        2021-12-06 14:47
        道哥分享
        關注

        作  者:道哥,10+年嵌入式開發老兵,專注于:C/C++、嵌入式、Linux。

        目錄

        kill 命令和信號

        使用 kill 命令發送信號

        多線程中的信號

        信號注冊和處理函數

        驅動程序代碼示例:發送信號

        功能需求

        驅動程序代碼

        驅動模塊 Makefile

        編譯和加載

        應用程序代碼示例:接收信號

        注冊信號處理函數

        測試驗證

        別人的經驗,我們的階梯!

        大家好,我是道哥,今天我為大伙兒解說的技術知識點是:【驅動層中,如何發送信號給應用程序】。

        在上一篇文章中,我們討論的是:在應用層如何發送指令來控制驅動層的 GPIOLinux驅動實踐:如何編寫【 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!

        這里還有一個地方需要注意一下:實時信號和非實時信號,它倆的主要區別是:

        1. 非實時信號:操作系統不確保應用程序一定能接收到(即:信號可能會丟失);

        2. 實時信號:操作系統確保應用程序一定能接收到;

        如果我們的程序設計,通過信號機制來完成一些功能,那么為了確保信號不會丟失,肯定是使用實時信號的。

        從文件 signum.h 中可以看到,實時信號從 __SIGRTMIN(數值:32) 開始。

        多線程中的信號

        我們在編寫應用程序時,雖然沒有接收并處理 SIGKILL 這個信號,但是一旦別人發送了這個信號,我們的程序就被操作系統停止掉了,這是默認的動作。

        那么,在應用程序中,應該可以主動聲明接收并處理指定的信號,下面就來寫一個最簡單的實例。

        在一個應用程序中,可能存在多個線程;

        當有一個信號發送給此進程時,所有的線程都可能接收到,但是只能有一個線程來處理;

        在這個示例中,只有一個主線程來接收并處理信號;

        信號注冊和處理函數

        按照慣例,所有應用程序文件都創建在 ~/tmp/App 目錄中。

        image.png

        這個示例程序接收的信號是 SIGUSR1 和 SIGUSR2,也就是數值 10 和 12。

        編譯、執行:

        $ gcc app_handle_signal.c -o app_handle_signal

        $ ./app_handle_signal

        此時,應用程序開始執行,等待接收信號。

        在另一個終端中,使用kill指令來發送信號SIGUSR1或者 SIGUSR2。

        kill 發送信號,需要知道應用程序的 PID,可以通過指令: ps -au | grep app_handle_signal 來查看。

        其中的15428就是進程的 PID。

        執行發送信號SIGUSR1指令:

        $ kill -10 15428

        此時,在應用程序的終端窗口中,就能看到下面的打印信息:

        說明應用程序接收到了 SIGUSR1 這個信號!

        注意:我們是使用kill命令來發送信號的,kill 也是一個獨立的進程,程序的執行路徑如下:

        在這個執行路徑中,我們可控的部分是應用層,至于操作系統是如何接收kill的操作,然后如何發送信號給 app_handle_signal 進程的,我們不得而知。

        下面就繼續通過示例代碼來看一下如何在驅動層主動發送信號。

        驅動程序代碼示例:發送信號功能需求

        在剛才的簡單示例中,可以得出下面這些信息:

        1. 信號發送方:必須知道向誰[PID]發送信號,發送哪個信號;

        2. 信號接收方:必須定義信號處理函數,并且向操作系統注冊:接收哪些信號;

        發送方當然就是驅動程序了,在示例代碼中,繼續使用 SIGUSR1 信號來測試。

        那么,驅動程序如何才能知道應用程序的PID呢?可以讓應用程序通過oictl函數,把自己的PID主動告訴驅動程序:

        驅動程序

        這里的示例代碼,是在上一篇文章的基礎上修改的,改動部分的內容,使用宏定義 MY_SIGNAL_ENABLE 控制起來,方便查看和比較。

        以下所有操作的工作目錄,都是與上一篇文章相同的,即:~/tmp/linux-4.15/drivers/。

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png

        這里大部分的代碼,在上一篇文章中已經描述的比較清楚了,這里把重點關注放在這兩個函數上:gpio_ioctl 和 send_signal。

        (1)函數 gpio_ioctl

        當應用程序調用 ioctl() 的時候,驅動程序中的 gpio_ioctl 就會被調用。

        這里定義一個簡單的協議:當應用程序調用參數中 cmd 為 100 的時候,就表示用來告訴驅動程序自己的 PID。

        驅動程序定義了一個全局變量 g_pid,用來保存應用程序傳入的參數PID。

        需要調用函數 copy_from_user(&g_pid, pArg, sizeof(int)),把用戶空間的參數復制到內核空間中;

        成功取得PID之后,就調用函數 send_signal 向應用程序發送信號。

        這里僅僅是用于演示目的,在實際的項目中,可能會根據接收到硬件觸發之后再發送信號。

        (2)函數 send_signal

        這個函數主要做了3件事情:

        構造一個信號結構體變量:struct siginfo info;

        通過應用程序傳入的 PID,獲取任務信息:pid_task(find_vpid(g_pid), PIDTYPE_PID);

        發送信號:send_sig_info(sig_no, &info, my_task);

        驅動模塊 Makefile

        $ touch Makefile

        內容如下:

        image.png

        編譯驅動模塊

        $ make

        得到驅動程序: my_driver_signal.ko 。

        加載驅動模塊$ sudo insmod my_driver_signal.ko

        通過 dmesg 指令來查看驅動模塊的打印信息:

        因為示例代碼是在上一篇GPIO的基礎上修改的,因此創建的設備節點文件,與上篇文章是一樣的:

        應用程序代碼示例:接收信號注冊信號處理函數

        應用程序仍然放在 ~/tmp/App/ 目錄下。

        $ mkdir ~/tmp/App/app_mysignal

        $ cd ~/tmp/App/app_mysignal

        $ touch mysignal.c

        文件內容如下:

        image.png

        image.png

        可以看到,應用程序主要做了兩件事情:

        (1)首先通過函數 sigaction() 向操作系統注冊了信號 SIGUSR1 和 SIGUSR2,它倆的信號處理函數是同一個:signal_handler()。

        除了 sigaction 函數,應用程序還可以使用 signal 函數來注冊信號處理函數;

        (2)然后通過 ioctl(fd, 100, &pid); 向驅動程序設置自己的 PID。

        編譯應用程序:

        $ gcc mysignal.c -o mysignal

        執行應用程序:

        $ sudo ./mysignal

        根據剛才驅動程序的代碼,當驅動程序接收到設置PID的命令之后,會立刻發送兩個信號:

        先來看一下 dmesg 中驅動程序的打印信息:

        可以看到:驅動把這兩個信號(10 和 12),發送給了應用程序(PID=6259)。

        應用程序的輸出信息如下:

        可以看到:應用程序接收到信號 10 和 12,并且正確打印出信號中攜帶的一些信息!

        聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯系舉報。

        發表評論

        0條評論,0人參與

        請輸入評論內容...

        請輸入評論/評論長度6~500個字

        您提交的評論過于頻繁,請輸入驗證碼繼續

        暫無評論

        暫無評論

          掃碼關注公眾號
          OFweek人工智能網
          獲取更多精彩內容
          文章糾錯
          x
          *文字標題:
          *糾錯內容:
          聯系郵箱:
          *驗 證 碼:

          粵公網安備 44030502002758號

          主站蜘蛛池模板: 一区二区水蜜桃| 51国产在线| 欧美黑人一区| 国产XX00| 77777AV| 久草资源在线| 国产精品成人无码A片噜噜| 太原市| 亚洲日韩第9页| 伊人久久AV| 日本人妻丰满熟妇久久久久久| 懂色av,蜜臀AV粉嫩av| 亚洲丝袜熟女| 91人人妻| 凤台县| 亚洲熟妇色自偷自拍另类| 会昌县| 国产熟女精品视频| 国产黄拍| 国产精品久久| 天天干天天射天天操| 91乱伦视频| 赤水市| 宜城市| 欧美午夜福利| 啪啪电影| 91高级网站| 亚洲日韩字幕| 日逼免费视频| 亚洲一区二区av| 恩平市| 蜜臀久久99精品久久久久久酒店| 国产熟女区| 铁岭县| 人人干干| 人妻无码一卡| 欧美Aⅴ| 欧洲丰满熟女a片| 91视频免费| 日本久久69| 亚洲成人av在线|