跳转到内容

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 <[email protected]>
--   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

华夏公益教科书