zoukankan      html  css  js  c++  java
  • linux advancing program signal [copy]

    Signalsare mechanisms for communicating with and manipulating processes in Linux.
    The topic of signals is a large one; here we discuss some of the most important signals
    and techniques that are used for controlling processes.
    A signal is a special message sent to a process. Signals are asynchronous; when a
    process receives a signal, it processes the signal immediately, without finishing the cur-rent function or even the current line of code.There are several dozen different sig-nals, each with a different meaning. Each signal type is specified by its signal number,
    but in programs, you usually refer to a signal by its name. In Linux, these are defined
    in /usr/include/bits/signum.h. (You shouldn’t include this header file directly in
    your programs; instead, use <signal.h>.)

    2. A method for serializing the two processes is presented in Section 3.4.1,“Waiting for
    Process Termination.”

     When a process receives a signal, it may do one of several things, depending on the
    signal’s disposition. For each signal, there is a default disposition, which determines what
    happens to the process if the program does not specify some other behavior. For most
    signal types, a program may specify some other behavior—either to ignore the signal
    or to call a specialsignal-handler function to respond to the signal. If a signal handler is
    used, the currently executing program is paused, the signal handler is executed, and,
    when the signal handler returns, the program resumes.

    The Linux system sends signals to processes in response to specific conditions. For
    instance,SIGBUS(bus error),SIGSEGV(segmentation violation), and SIGFPE(floating
    point exception) may be sent to a process that attempts to perform an illegal opera-tion.The default disposition for these signals it to terminate the process and produce a
    core file.
    A process may also send a signal to another process. One common use of this
    mechanism is to end another process by sending it a SIGTERMor SIGKILLsignal.
    3
    Another common use is to send a command to a running program.Two “user-defined”signals are reserved for this purpose:SIGUSR1and SIGUSR2.The SIGHUPsignal
    is sometimes used for this purpose as well, commonly to wake up an idling program
    or cause a program to reread its configuration files.
    The sigactionfunction can be used to set a signal disposition.The first parameter
    is the signal number.The next two parameters are pointers to sigactionstructures; the
    first of these contains the desired disposition for that signal number, while the second
    receives the previous disposition.The most important field in the first or second
    sigactionstructure is sa_handler. It can take one of three values:
    n SIG_DFL, which specifies the default disposition for the signal.

    SIG_IGN, which specifies that the signal should be ignored.
    n A pointer to a signal-handler function.The function should take one parameter,
    the signal number, and return void.

    Because signals are asynchronous, the main program may be in a very fragile state
    when a signal is processed and thus while a signal handler function executes.
    Therefore, you should avoid performing any I/O operations or calling most library
    and system functions from signal handlers.
    A signal handler should perform the minimum work necessary to respond to the
    signal, and then return control to the main program (or terminate the program). In
    most cases, this consists simply of recording the fact that a signal occurred.The main
    program then checks periodically whether a signal has occurred and reacts accordingly.
    It is possible for a signal handler to be interrupted by the delivery of another signal.
    While this may sound like a rare occurrence, if it does occur, it will be very difficult to
    diagnose and debug the problem. (This is an example of a race condition, discussed in
    Chapter 4,“Threads,”Section 4.4,“Synchronization and Critical Sections.”) Therefore,
    you should be very careful about what your program does in a signal handler.

    3.What’s the difference? The SIGTERMsignal asks a process to terminate; the process may
    ignore the request by masking or ignoring the signal.The SIGKILLsignal always kills the process
    immediately because the process may not mask or ignore SIGKILL.

    Even assigning a value to a global variable can be dangerous because the assignment
    may actually be carried out in two or more machine instructions, and a second signal
    may occur between them, leaving the variable in a corrupted state. If you use a global
    variable to flag a signal from a signal-handler function, it should be of the special type
    sig_atomic_t. Linux guarantees that assignments to variables of this type are per-formed in a single instruction and therefore cannot be interrupted midway. In Linux,
    sig_atomic_tis an ordinary int; in fact, assignments to integer types the size of intor
    smaller, or to pointers, are atomic. If you want to write a program that’s portable to
    any standard UNIX system, though, use sig_atomic_tfor these global variables.
    This program skeleton in Listing 3.5, for instance, uses a signal-handler function to
    count the number of times that the program receives SIGUSR1, one of the signals
    reserved for application use.

    Listing 3.5 (sigusr1.c) Using a Signal Handler
    #include <signal.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    sig_atomic_t sigusr1_count = 0;
    void handler (int signal_number)
    {
    ++sigusr1_count;
    }
    int main ()
    {
    struct sigaction sa;
    memset (&sa, 0, sizeof (sa));
    sa.sa_handler = &handler;
    sigaction (SIGUSR1, &sa, NULL);
    /* Do some lengthy stuff here. */
    /* ... */
    printf (“SIGUSR1 was raised %d times\n”, sigusr1_count);
    return 0;
    }

     信号(Signal)是Linux系统中用于进程之间相互通信或操作的一种机制。信号是一个
    相当广泛的课题;在这里,我们仅仅探讨几种最重要的信号以及利用信号控制进程的技术。
    信号是一个发送到进程的特殊信息。信号机制是异步的;当一个进程接收到一个信号时,
    它会立刻处理这个信号,而不会等待当前函数甚至当前一行代码结束运行。信号有几十种,
    分别代表着不同的意义。信号之间依靠它们的值来区分,但是通常在程序中使用信号的名字
    来表示一个信号。在Linux系统中,这些信号和以它们的名称命名的常量均定义在
    usr/include/bits/signum.h文件中。(通常程序中不需要直接包含这个头文件,而应
    该包含<signal.h>。)
    当一个进程接收到信号,基于不同的处理方式(disposition),该进程可能执行几种不同
    操作中的一种。每个信号都有一个默认处理方式(default disposition),当进程没有指定自己
    对于某个信号的处理方式的时候,默认处理方式将被用于对对应信号作出响应。对于多数种
    类的信号,程序都可以自由指定一个处理方式——程序可以选择忽略这个信号,或者调用一
    个特定的信号处理函数。如果指定了一个信号处理函数,当前程序会暂停当前的执行过程,
    同时开始执行信号处理函数,并且当信号处理函数返回之后再从被暂停处继续执行。
    Linux系统在运行中出现特殊状况的时候也会向进程发送信号通知。例如,当一个进程
    执行非法操作的时候可能会收到SIGBUS(主线错误),SIGSEGV(段溢出错误)及  SIGFPE
    (浮点异常)这些信号。这些信号的默认处理方式都是终止程序并且产生一个核心转储文件
    (core file)。
    一个进程除了响应系统发来的信号,还可以向其它进程发送信号。对于这种机制的一个
    最常见的应用就是通过发送SIGTERM或SIGKILL信号来结束其它进程。

    #3 除此之外,它
    还常见于向运行中的进程发送命令。两个“用户自定义”的信号SIGUSR1和SIGUSR2就是
    专门作此用途的。SIGHUP信号有时也用于这个目的——通常用于唤醒一个处于等待状态的
    进程或者使进程重新读取配置文件。
    www.AdvancedLinuxProgramming.com  43
    系统调用sigaction 用于指定信号的处理方式。函数的第一个参数是信号的值。之后两
    个参数是两个指向sigaction 结构的指针;第一个指向了将被设置的处理方式,第二个用于
    保存先前的处理方式。这两个sigaction结构中最重要的都是sa_handler域。它可以是下面
    三个值:
    · SIG_DFL,指定默认的信号处理方式
    · SIG_IGN,指定该信号将被忽略
    · 一个指向信号处理函数的指针。这个函数应该接受信号值作为唯一参数,
    且没有返回值。
    因为信号处理是异步进行的,当信号处理函数被调用的时候,主程序可能处在非常脆弱
    的状态,并且这个状态会一直保持到信号处理函数结束。因此,应该尽量避免在信号处理函
    数中使用输入输出功能、绝大多数库函数和系统调用
    信号处理函数应该做尽可能少的工作以响应信号的到达,然后返回到主程序中继续运行
    (或者结束进程)。多数情况下,所进行的工作只是记录信号的到达。而主程序则定期检查
    是否有信号到达,并且针对当时情况作出相应的处理。
    信号处理函数也可能被其它信号的到达所打断。虽然这种情况听起来非常罕见,一旦出
    现,程序将非常难以确定问题并进行调试。(这是竞争状态的一个例子。在第四章“线程”
    第4.4 节“同步及临界段”中进行了讨论。)因此,对于你的信号处理函数进行哪些工作一
    定要进行慎重的考虑。
    甚至于对全局变量赋值可能也是不安全的,因为一个赋值操作可能由两个或更多机器指
    令完成,而在这些指令执行期间可能会有第二个信号到达,致使被修改的全局变量处于不完
    整的状态。如果你需要从信号处理函数中设置全局标志以记录信号的到达,这个标志必须是
    特殊类型sig_atomic_t的实例。Linux保证对于这个类型变量的赋值操作只需要一条机器指
    令,因此不用担心可能在中途被打断。在Linux系统中,sig_atomic_t就是基本的int类型;
    事实上,对int或者更小的整型变量以及指针赋值的操作都是原子操作。不过,如果你希望
    所写的程序可以向任何标准UNIX系统移植,则应将所有全局变量设为sig_atomic_t类型。
    如下所示,代码列表3.5中的简单程序中,我们利用信号处理函数统计程序在运行期接
    收到SIGUSR1信号的次数。SIGUSR1信号是一个为应用程序保留的信号。

    如下所示,代码列表3.5中的简单程序中,我们利用信号处理函数统计程序在运行期接
    收到SIGUSR1信号的次数。SIGUSR1信号是一个为应用程序保留的信号。
    代码列表3.5 (sigusr1.c)使用信号处理函数
    #include <signal.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    sig_atomic_t sigusr1_count = 0;   //信号处理函数中赋值的全局变量  注意类型
    void handle (int signal_number) //信号处理函数
    {
    ++sigusr1_count;
    }
    int main ()
    {
    struct sigaction sa;
    memset (&sa, 0, sizeof (sa));
    sa.sa_handler = &handler;
    sigaction (SIGUSR1, &sa, NULL); //定义了被处理handle  不保存先前处理方式  如果需要 何时需要  如何保存?????? 
    /* 这里可以执行一些长时间的工作。*/
    /* ... */
    printf ("SIGUSR1 was raised %d times\n", sigusr1_count);
    return 0;
    }

  • 相关阅读:
    Linux 三剑客之SED
    搭建Docker环境
    Docker rabbitmq
    Docker Redis 集群
    Docker Mysql
    lerna 大前端项目代码重用解决方案
    将create-react-app从javascript迁移到typescript
    使用 React hooks 优雅解决 mp3 的播放 和 暂停
    React 代码 Import Svg as ReactComponent 失败
    vue3 自定义 hooks 优雅处理异步调用 ajax
  • 原文地址:https://www.cnblogs.com/michile/p/2890514.html
Copyright © 2011-2022 走看看