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 <[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.Interruptsis
type
Interrupt_IDis
(Implementation_Defined);type
Parameterless_Handleris
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.Interrupts
的示例:Rosetta Code、GitHub (gists)、任何 Alire crate 或 本维基教科书。 - 在以下位置搜索与
Ada.Interrupts
相关的帖子:Stack Overflow、comp.lang.ada 或 任何与 Ada 相关的页面。
FSF GNAT
- 规范:a-interr.ads
- 主体:a-interr.adb
drake