跳轉到內容

Ada 程式設計/庫/Ada.Interrupts

來自華夏公益教科書,開放書籍,開放世界

Ada. Time-tested, safe and secure.
Ada. 經久耐用、安全可靠。

該語言特性從 Ada 95 開始可用。

Ada.Interrupts預定義語言環境 自 Ada 95 以來的一部分。

有時您的程式需要能夠捕獲並處理諸如 SIGINTSIGTERMSIGHUP 之類的中斷,為此,我們有 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。

catch_signals.gpr

[編輯 | 編輯原始碼]

此檔案設定編譯選項。它告知編譯器原始檔的位置以及將物件檔案和可執行檔案放在哪裡。當然,如果您沒有克隆 Git 儲存庫,則必須建立 exebuild 目錄。

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;

catch_signals.adb

[編輯 | 編輯原始碼]

這是主程式檔案。這裡沒有太多操作。我們只是在 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;

src/process_control.ads

[編輯 | 編輯原始碼]

在此檔案中,我們定義了中斷處理程式。有關如何動態附加中斷處理程式的示例,請檢視 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;

src/process_control.adb

[編輯 | 編輯原始碼]

請特別注意 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
-- -------------------------------------------------------------------------

with System;

package Ada.Interrupts is

   type Interrupt_ID is (Implementation_Defined);

   type Parameterless_Handler is access protected procedure;

   function Is_Reserved (Interrupt : in Interrupt_ID) return Boolean;

   function Is_Attached (Interrupt : in Interrupt_ID) return Boolean;

   function Current_Handler (Interrupt : in Interrupt_ID)
     return Parameterless_Handler;

   procedure Attach_Handler (New_Handler : in Parameterless_Handler;
                             Interrupt   : in Interrupt_ID);

   procedure Exchange_Handler (Old_Handler :    out Parameterless_Handler;
                               New_Handler : in     Parameterless_Handler;
                               Interrupt   : in     Interrupt_ID);

   procedure Detach_Handler (Interrupt : in Interrupt_ID);

   function Reference (Interrupt : in Interrupt_ID) return System.Address;

private

end Ada.Interrupts;

另請參閱

[編輯 | 編輯原始碼]

華夏公益教科書

[編輯 | 編輯原始碼]

外部示例

[編輯原始碼]

Ada 語言參考手冊

[編輯 | 編輯原始碼]

開源實現

[編輯 | 編輯原始碼]

FSF GNAT

drake

華夏公益教科書