⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 library_21.html

📁 linux_c函数,linux下编程必备的
💻 HTML
📖 第 1 页 / 共 5 页
字号:
else if (query_action.sa_handler == SIG_DFL)
  /* <CODE>SIGINT</CODE> is handled in the default, fatal manner. */
else if (query_action.sa_handler == SIG_IGN)
  /* <CODE>SIGINT</CODE> is ignored. */
else
  /* A programmer-defined signal handler is in effect. */
</PRE>
<P>
<A NAME="IDX1551"></A>
<A NAME="IDX1552"></A>
<A NAME="IDX1553"></A>
<H3><A NAME="SEC349" HREF="library_toc.html#SEC349" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC349">Flags for <CODE>sigaction</CODE></A></H3>
<P>
The <CODE>sa_flags</CODE> member of the <CODE>sigaction</CODE> structure is a
catch-all for special features.  Most of the time, <CODE>SA_RESTART</CODE> is
a good value to use for this field.
<P>
The value of <CODE>sa_flags</CODE> is interpreted as a bit mask.  Thus, you
should choose the flags you want to set, OR those flags together,
and store the result in the <CODE>sa_flags</CODE> member of your
<CODE>sigaction</CODE> structure.
<P>
Each signal number has its own set of flags.  Each call to
<CODE>sigaction</CODE> affects one particular signal number, and the flags
that you specify apply only to that particular signal.
<P>
In the GNU C library, establishing a handler with <CODE>signal</CODE> sets all
the flags to zero except for <CODE>SA_RESTART</CODE>, whose value depends on
the settings you have made with <CODE>siginterrupt</CODE>.  See section <A HREF="library_21.html#SEC362" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC362">Primitives Interrupted by Signals</A>, to see what this is about.
<A NAME="IDX1554"></A>
<P>
These macros are defined in the header file <TT>`signal.h'</TT>.
<P>
<A NAME="IDX1555"></A>
<U>Macro:</U> int <B>SA_NOCLDSTOP</B><P>
This flag is meaningful only for the <CODE>SIGCHLD</CODE> signal.  When the
flag is set, the system delivers the signal for a terminated child
process but not for one that is stopped.  By default, <CODE>SIGCHLD</CODE> is
delivered for both terminated children and stopped children.
<P>
Setting this flag for a signal other than <CODE>SIGCHLD</CODE> has no effect.
<P>
<A NAME="IDX1556"></A>
<U>Macro:</U> int <B>SA_ONSTACK</B><P>
If this flag is set for a particular signal number, the system uses the
signal stack when delivering that kind of signal.  See section <A HREF="library_21.html#SEC380" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC380">BSD Signal Handling</A>.
<P>
<A NAME="IDX1557"></A>
<U>Macro:</U> int <B>SA_RESTART</B><P>
This flag controls what happens when a signal is delivered during
certain primitives (such as <CODE>open</CODE>, <CODE>read</CODE> or <CODE>write</CODE>),
and the signal handler returns normally.  There are two alternatives:
the library function can resume, or it can return failure with error
code <CODE>EINTR</CODE>.
<P>
The choice is controlled by the <CODE>SA_RESTART</CODE> flag for the
particular kind of signal that was delivered.  If the flag is set,
returning from a handler resumes the library function.  If the flag is
clear, returning from a handler makes the function fail.
See section <A HREF="library_21.html#SEC362" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC362">Primitives Interrupted by Signals</A>.
<P>
<A NAME="IDX1558"></A>
<H3><A NAME="SEC350" HREF="library_toc.html#SEC350" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC350">Initial Signal Actions</A></H3>
<P>
When a new process is created (see section <A HREF="library_23.html#SEC405" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_23.html#SEC405">Creating a Process</A>), it inherits
handling of signals from its parent process.  However, when you load a
new process image using the <CODE>exec</CODE> function (see section <A HREF="library_23.html#SEC406" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_23.html#SEC406">Executing a File</A>), any signals that you've defined your own handlers for revert to
their <CODE>SIG_DFL</CODE> handling.  (If you think about it a little, this
makes sense; the handler functions from the old program are specific to
that program, and aren't even present in the address space of the new
program image.)  Of course, the new program can establish its own
handlers.
<P>
When a program is run by a shell, the shell normally sets the initial
actions for the child process to <CODE>SIG_DFL</CODE> or <CODE>SIG_IGN</CODE>, as
appropriate.  It's a good idea to check to make sure that the shell has
not set up an initial action of <CODE>SIG_IGN</CODE> before you establish your
own signal handlers.
<P>
Here is an example of how to establish a handler for <CODE>SIGHUP</CODE>, but
not if <CODE>SIGHUP</CODE> is currently ignored:
<P>
<PRE>
...
struct sigaction temp;

sigaction (SIGHUP, NULL, &#38;temp);

if (temp.sa_handler != SIG_IGN)
  {
    temp.sa_handler = handle_sighup;
    sigemptyset (&#38;temp.sa_mask);
    sigaction (SIGHUP, &#38;temp, NULL);
  }
</PRE>
<P>
<A NAME="IDX1559"></A>
<H2><A NAME="SEC351" HREF="library_toc.html#SEC351" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC351">Defining Signal Handlers</A></H2>
<P>
This section describes how to write a signal handler function that can
be established with the <CODE>signal</CODE> or <CODE>sigaction</CODE> functions.
<P>
A signal handler is just a function that you compile together with the
rest of the program.  Instead of directly invoking the function, you use
<CODE>signal</CODE> or <CODE>sigaction</CODE> to tell the operating system to call
it when a signal arrives.  This is known as <DFN>establishing</DFN> the
handler.  See section <A HREF="library_21.html#SEC344" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC344">Specifying Signal Actions</A>.
<P>
There are two basic strategies you can use in signal handler functions:
<P>
<UL>
<LI>
You can have the handler function note that the signal arrived by
tweaking some global data structures, and then return normally.
<P>
<LI>
You can have the handler function terminate the program or transfer
control to a point where it can recover from the situation that caused
the signal.
</UL>
<P>
You need to take special care in writing handler functions because they
can be called asynchronously.  That is, a handler might be called at any
point in the program, unpredictably.  If two signals arrive during a
very short interval, one handler can run within another.  This section
describes what your handler should do, and what you should avoid.
<P>
<H3><A NAME="SEC352" HREF="library_toc.html#SEC352" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC352">Signal Handlers That Return</A></H3>
<P>
Handlers which return normally are usually used for signals such as
<CODE>SIGALRM</CODE> and the I/O and interprocess communication signals.  But
a handler for <CODE>SIGINT</CODE> might also return normally after setting a
flag that tells the program to exit at a convenient time.
<P>
It is not safe to return normally from the handler for a program error
signal, because the behavior of the program when the handler function
returns is not defined after a program error.  See section <A HREF="library_21.html#SEC336" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC336">Program Error Signals</A>.
<P>
Handlers that return normally must modify some global variable in order
to have any effect.  Typically, the variable is one that is examined
periodically by the program during normal operation.  Its data type
should be <CODE>sig_atomic_t</CODE> for reasons described in section <A HREF="library_21.html#SEC358" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC358">Atomic Data Access and Signal Handling</A>.
<P>
Here is a simple example of such a program.  It executes the body of
the loop until it has noticed that a <CODE>SIGALRM</CODE> signal has arrived.
This technique is useful because it allows the iteration in progress
when the signal arrives to complete before the loop exits.
<P>
<PRE>
#include &#60;signal.h&#62;
#include &#60;stdio.h&#62;
#include &#60;stdlib.h&#62;

/* This flag controls termination of the main loop.  */
volatile sig_atomic_t keep_going = 1;

/* The signal handler just clears the flag and re-enables itself.  */
void 
catch_alarm (int sig)
{
  keep_going = 0;
  signal (sig, catch_alarm);
}

void 
do_stuff (void)
{
  puts ("Doing stuff while waiting for alarm....");
}

int
main (void)
{
  /* Establish a handler for SIGALRM signals.  */
  signal (SIGALRM, catch_alarm);

  /* Set an alarm to go off in a little while.  */
  alarm (2);

  /* Check the flag once in a while to see when to quit.  */
  while (keep_going)
    do_stuff ();

  return EXIT_SUCCESS;
}
</PRE>
<P>
<H3><A NAME="SEC353" HREF="library_toc.html#SEC353" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC353">Handlers That Terminate the Process</A></H3>
<P>
Handler functions that terminate the program are typically used to cause
orderly cleanup or recovery from program error signals and interactive
interrupts.
<P>
The cleanest way for a handler to terminate the process is to raise the
same signal that ran the handler in the first place.  Here is how to do
this:
<P>
<PRE>
volatile sig_atomic_t fatal_error_in_progress = 0;

void
fatal_error_signal (int sig)
{
  /* Since this handler is established for more than one kind of signal, 
     it might still get invoked recursively by delivery of some other kind
     of signal.  Use a static variable to keep track of that. */
  if (fatal_error_in_progress)
    raise (sig);
  fatal_error_in_progress = 1;

  /* Now do the clean up actions:
     - reset terminal modes
     - kill child processes
     - remove lock files */
  ...

  /* Now reraise the signal.  Since the signal is blocked,
     it will receive its default handling, which is
     to terminate the process.  We could just call
     <CODE>exit</CODE> or <CODE>abort</CODE>, but reraising the signal
     sets the return status from the process correctly. */
  raise (sig);
}
</PRE>
<P>
<A NAME="IDX1560"></A>
<H3><A NAME="SEC354" HREF="library_toc.html#SEC354" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC354">Nonlocal Control Transfer in Handlers</A></H3>
<P>
You can do a nonlocal transfer of control out of a signal handler using
the <CODE>setjmp</CODE> and <CODE>longjmp</CODE> facilities (see section <A HREF="library_20.html#SEC326" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_20.html#SEC326">Non-Local Exits</A>).
<P>
When the handler does a nonlocal control transfer, the part of the
program that was running will not continue.  If this part of the program
was in the middle of updating an important data structure, the data
structure will remain inconsistent.  Since the program does not
terminate, the inconsistency is likely to be noticed later on.
<P>
There are two ways to avoid this problem.  One is to block the signal
for the parts of the program that update important data structures.
Blocking the signal delays its delivery until it is unblocked, once the
critical updating is finished.  See section <A HREF="library_21.html#SEC368" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC368">Blocking Signals</A>.
<P>
The other way to re-initialize the crucial data structures in the signal
handler, or make their values consistent.
<P>
Here is a rather schematic example showing the reinitialization of one
global variable.
<P>
<PRE>
#include &#60;signal.h&#62;
#include &#60;setjmp.h&#62;

jmp_buf return_to_top_level;

volatile sig_atomic_t waiting_for_i

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -