Ada 程式設計/庫/Ada.Interrupts
該語言特性從 Ada 95 開始可用。
Ada.Interrupts 是 預定義語言環境 自 Ada 95 以來的一部分。
有時您的程式需要能夠捕獲並處理諸如 SIGINT、SIGTERM 或 SIGHUP 之類的中斷,為此,我們有 Ada.Interrupts 包。可以靜態或動態地將處理程式附加到中斷,幸運的是,這兩種方法都易於理解。以下程式將向您展示這兩種方法。
我已經對程式進行了註釋,因此應該很容易理解正在發生的事情。您可以從這個 Git 儲存庫中獲取整個程式
https://github.com/kjseefried/Catch_Signals
Git 可用於所有 Linux 發行版。使用 Git 獲取 Catch_Signals 然後編譯它的命令是
$ git clone https://github.com/kjseefried/Catch_Signals $ cd Catch_Signals $ gnatmake -P catch_signals.gpr
現在可以在 exe/ 目錄中找到可執行檔案。
如果您不想使用 Git,可以從下面複製完整的原始碼。我當然會盡力確保此頁面上的程式碼與 Git 儲存庫中的程式碼一致,但由於這是一個任何人都可以進行更改的維基,我無法保證在頁面上執行程式碼的安全性,因此請謹慎使用。
該程式將訊號處理程式附加到這些中斷
- SIGHUP
- SIGINT
- SIGPWR
- SIGTERM
您可以像這樣將這些中斷髮送到正在執行的程式
kill -SIGHUP pid
其中 pid 是程式的程序 ID。
此檔案設定編譯選項。它告知編譯器原始檔的位置以及將物件檔案和可執行檔案放在哪裡。當然,如果您沒有克隆 Git 儲存庫,則必須建立 exe 和 build 目錄。
catch_signals.gpr
-------------------------------------------------------------------------------
-- --
-- Catch_Signals Project File --
-- --
-- Copyright (C) 2010, Thomas Løcke --
-- --
-- Catch_Signals is free software; you can redistribute it and/or modify --
-- it under terms of the GNU General Public License as published by the --
-- Free Software Foundation; either version 2, or (at your option) any --
-- later version. Catch_Signals is distributed in the hope that it will be --
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --
-- General Public License for more details. You should have received a --
-- copy of the GNU General Public License distributed with Catch_Signals. --
-- If not, write to the Free Software Foundation, 51 Franklin Street, --
-- Fifth Floor, Boston, MA 02110 - 1301, USA. --
-- --
-------------------------------------------------------------------------------
project Catch_Signals is
for Source_Dirs use (".",
"src");
for Main use ("catch_signals.adb");
for Exec_Dir use "exe";
for Object_Dir use "build";
package Ide is
for Compiler_Command ("ada") use "gnatmake";
end Ide;
package Compiler is
Common_Options := ("-gnatwa",
"-gnaty3abcdefhiklmnoprstux",
"-Wall",
"-O2",
"-gnat05");
for Default_Switches ("Ada") use Common_Options;
end Compiler;
end Catch_Signals;
這是主程式檔案。這裡沒有太多操作。我們只是在 Process_Control.Wait 語句處等待中斷。
-------------------------------------------------------------------------------
-- --
-- Catch_Signals --
-- --
-- Copyright (C) 2010, Thomas Løcke --
-- --
-- Catch_Signals is free software; you can redistribute it and/or modify --
-- it under terms of the GNU General Public License as published by the --
-- Free Software Foundation; either version 2, or (at your option) any --
-- later version. Catch_Signals is distributed in the hope that it will be --
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Gene- --
-- ral Public License for more details. You should have received a copy --
-- of the GNU General Public License distributed with Catch_Signals. If --
-- not, write to the Free Software Foundation, 51 Franklin Street, --
-- Fifth Floor, Boston, MA 02110 - 1301, USA. --
-- --
-------------------------------------------------------------------------------
with Ada.Text_IO;
with Process_Control;
procedure Catch_Signals
is
use Ada.Text_IO;
begin
Put_Line ("Lets catch some interrupts!");
Process_Control.Wait;
-- Wait for an interrupt here. The program is "stuck" here until the
-- Process_State variable is set to Shutdown by one of the registered
-- interrupt handlers.
Put_Line ("Interrupt caught - shutting down.");
end Catch_Signals;
在此檔案中,我們定義了中斷處理程式。有關如何動態附加中斷處理程式的示例,請檢視 SIGHUP 程式碼。
-------------------------------------------------------------------------------
-- --
-- Catch_Signals --
-- --
-- process_control --
-- --
-- SPEC --
-- --
-- Copyright (C) 2010, Thomas Løcke --
-- --
-- Catch_Signals is free software; you can redistribute it and/or modify --
-- it under terms of the GNU General Public License as published by the --
-- Free Software Foundation; either version 2, or (at your option) any --
-- later version. Catch_Signals is distributed in the hope that it will be --
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Gene- --
-- ral Public License for more details. You should have received a copy --
-- of the GNU General Public License distributed with Catch_Signals. If --
-- not, write to the Free Software Foundation, 51 Franklin Street, --
-- Fifth Floor, Boston, MA 02110 - 1301, USA. --
-- --
-------------------------------------------------------------------------------
with Ada.Interrupts.Names;
with Ada.Text_IO;
package Process_Control is
pragma Unreserve_All_Interrupts;
-- Make sure that GNAT does not handle any interrupts automatically.
-- As per GNAT 2010, this pragma only affects SIGINT.
procedure Wait;
-- Wait until Process_State is Shutdown.
private
type State is (Running, Shutdown, Stopped);
-- Define three different states of the running process.
package State_IO is new Ada.Text_IO.Enumeration_IO (State);
-- Instantiate a package so we can output the value of Process_State using
-- the familiar Put procedure.
Wait_Called : Boolean := False;
-- Set to True when Wait is called the first time.
protected Controller is
entry Check;
-- Check the Process_State is Shutdown, and if so, shut down the process
function Get_State return State;
-- Return the current Process_State.
procedure Handle_SIGINT;
procedure Handle_SIGPWR;
procedure Handle_SIGTERM;
pragma Attach_Handler (Handle_SIGINT, Ada.Interrupts.Names.SIGINT);
pragma Attach_Handler (Handle_SIGPWR, Ada.Interrupts.Names.SIGPWR);
pragma Attach_Handler (Handle_SIGTERM, Ada.Interrupts.Names.SIGTERM);
-- Statically attach handlers to the SIGINT, SIGPWR, SIGHUP and SIGTERM
-- interrupts.
procedure Handle_SIGHUP_Change_Handler;
procedure Handle_SIGHUP_Shutdown;
pragma Interrupt_Handler (Handle_SIGHUP_Change_Handler);
pragma Interrupt_Handler (Handle_SIGHUP_Shutdown);
-- Handle_SIGHUP_* can now be dynamically assigned using the
-- Ada.Interrupts.Attach_Handler procedure.
entry Start;
-- Set Process_State to Running.
private
Process_State : State := Stopped;
-- What state the process is in.
end Controller;
end Process_Control;
請特別注意 Wait 過程,其中 SIGHUP 中斷附加到 Handle_SIGHUP_Change_Handler 過程,然後重新附加到 Handle_SIGHUP_Shutdown 過程。這意味著要使用 SIGHUP 殺死程式,您必須執行 kill -SIGHUP pid 兩次。
-------------------------------------------------------------------------------
-- --
-- Catch_Signals --
-- --
-- process_control --
-- --
-- BODY --
-- --
-- Copyright (C) 2010, Thomas Løcke --
-- --
-- Catch_Signals is free software; you can redistribute it and/or modify --
-- it under terms of the GNU General Public License as published by the --
-- Free Software Foundation; either version 2, or (at your option) any --
-- later version. Catch_Signals is distributed in the hope that it will be --
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Gene- --
-- ral Public License for more details. You should have received a copy --
-- of the GNU General Public License distributed with Catch_Signals. If --
-- not, write to the Free Software Foundation, 51 Franklin Street, --
-- Fifth Floor, Boston, MA 02110 - 1301, USA. --
-- --
-------------------------------------------------------------------------------
with Ada.Interrupts;
package body Process_Control is
------------
-- Wait --
------------
procedure Wait
is
use Ada.Interrupts;
use Ada.Text_IO;
use State_IO;
begin
if not Wait_Called then
Wait_Called := True;
Attach_Handler
(New_Handler => Controller.Handle_SIGHUP_Change_Handler'Access,
Interrupt => Ada.Interrupts.Names.SIGHUP);
-- Dynamically attach a handler to the SIGHUP interrupt.
Put ("Wait called. Process_State is ");
Put (Controller.Get_State);
New_Line;
Controller.Start;
Controller.Check;
end if;
end Wait;
------------------
-- Controller --
------------------
protected body Controller is
-------------
-- Check --
-------------
entry Check when Process_State = Shutdown
is
use Ada.Text_IO;
use State_IO;
begin
Put ("Check called. Process_State is ");
Put (Controller.Get_State);
New_Line;
end Check;
-----------------
-- Get_State --
-----------------
function Get_State return State
is
begin
return Process_State;
end Get_State;
------------------------------------
-- Handle_SIGHUP_Change_Handler --
------------------------------------
procedure Handle_SIGHUP_Change_Handler
is
use Ada.Interrupts;
use Ada.Text_IO;
begin
Put_Line ("Handle_SIGHUP_Change_Handler called.");
Put_Line
("Dynamically changing handler to Handle_SIGHUP_Shutdown.");
Put_Line ("Next SIGHUP will stop the program.");
Attach_Handler (New_Handler => Handle_SIGHUP_Shutdown'Access,
Interrupt => Ada.Interrupts.Names.SIGHUP);
-- Dynamically assign a new handler to the SIGHUP interrupt.
end Handle_SIGHUP_Change_Handler;
------------------------------
-- Handle_SIGHUP_Shutdown --
------------------------------
procedure Handle_SIGHUP_Shutdown
is
use Ada.Text_IO;
begin
Put_Line ("Handle_SIGHUP_Shutdown called.");
Process_State := Shutdown;
end Handle_SIGHUP_Shutdown;
---------------------
-- Handle_SIGINT --
---------------------
procedure Handle_SIGINT
is
use Ada.Text_IO;
begin
Put_Line ("Handle_SIGINT called.");
Process_State := Shutdown;
end Handle_SIGINT;
---------------------
-- Handle_SIGPWR --
---------------------
procedure Handle_SIGPWR
is
use Ada.Text_IO;
begin
Put_Line ("Handle_SIGPWR called.");
Process_State := Shutdown;
end Handle_SIGPWR;
----------------------
-- Handle_SIGTERM --
----------------------
procedure Handle_SIGTERM
is
use Ada.Text_IO;
begin
Put_Line ("Handle_SIGTERM called.");
Process_State := Shutdown;
end Handle_SIGTERM;
-------------
-- Start --
-------------
entry Start when Process_State = Stopped
is
use Ada.Text_IO;
use State_IO;
begin
Process_State := Running;
Put ("Start called. Process_State is ");
Put (Controller.Get_State);
New_Line;
Put_Line ("I will react on SIGHUP, SIGINT, SIGPWR and SIGTERM.");
end Start;
end Controller;
end Process_Control;
-- Standard Ada library specification -- Copyright (c) 2003-2018 Maxim Reznik <reznikmm@gmail.com> -- Copyright (c) 2004-2016 AXE Consultants -- Copyright (c) 2004, 2005, 2006 Ada-Europe -- Copyright (c) 2000 The MITRE Corporation, Inc. -- Copyright (c) 1992, 1993, 1994, 1995 Intermetrics, Inc. -- SPDX-License-Identifier: BSD-3-Clause and LicenseRef-AdaReferenceManual -- -------------------------------------------------------------------------withSystem;packageAda.InterruptsistypeInterrupt_IDis(Implementation_Defined);typeParameterless_Handlerisaccessprotectedprocedure;functionIs_Reserved (Interrupt :inInterrupt_ID)returnBoolean;functionIs_Attached (Interrupt :inInterrupt_ID)returnBoolean;functionCurrent_Handler (Interrupt :inInterrupt_ID)returnParameterless_Handler;procedureAttach_Handler (New_Handler :inParameterless_Handler; Interrupt :inInterrupt_ID);procedureExchange_Handler (Old_Handler :outParameterless_Handler; New_Handler :inParameterless_Handler; Interrupt :inInterrupt_ID);procedureDetach_Handler (Interrupt :inInterrupt_ID);functionReference (Interrupt :inInterrupt_ID)returnSystem.Address;privateendAda.Interrupts;
外部示例
[編輯原始碼]- 在以下位置搜尋
Ada.Interrupts的示例:Rosetta Code、GitHub (gists)、任何 Alire crate 或 本華夏公益教科書。 - 在以下位置搜尋與
Ada.Interrupts相關的帖子:Stack Overflow、comp.lang.ada 或 任何與 Ada 相關的頁面。
FSF GNAT
- 規範:a-interr.ads
- 主體:a-interr.adb
drake
