【linux进程通信】信号的使用

来源:互联网 发布:淘宝旗舰店买手机 编辑:程序博客网 时间:2024/05/21 18:49

关于信号:

信号的作用:
1,通知进程一些特定的事件
2,强迫进程执行他自己代码中间的对信号的处理程序

进程以三种方式对一个信号作出应答
1,显示忽略
2,执行信号相关的缺省操作

  • terminate 终止
  • Dump 终止并且保存信息用于调试
  • Ignore 忽略
  • Stop 停止,进程状态为 TASK_STOPPED
  • Continue 如果进程停止,就将状态置为 TASK_RUNNING

3,调用相应的信号处理函数捕获信号(信号处理函数必须是柯重入的)

信号的分类

常规信号 前1~31号 同种类型的常规信号不需要排队接收
实时信号 POSIX标准引入 32~64位信号,需要排队以便多个信号被接受

关于信号的操作流程
*以下均有API可供查阅

  • 产生信号
  • 传递信号
  • 执行信号的缺省操作
  • 捕获信号

小例子
关于signal的用法:
函数作用,类似sigaction,改变与信号相关的操作
@signum 捕获的信号量
@sighandler_t 信号的处理函数

  • SIG_IGN:忽略信号
  • SIG_DFL:恢复信号的默认行为
#include <stdio.h>#include <unistd.h>/*    ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序。    ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程。    ctrl-d 不是发送信号,而是表示一个特殊的二进制值,表示 EOF。    ctrl-\ 发送 SIGQUIT 信号给前台进程组中的所有进程,终止前台进程并生成 core 文件。  */void ouch(int sig){    printf("\nOUCH! - I got signal %d\n", sig);    //恢复终端中断信号SIGINT的默认行为    //(void) signal(SIGINT, SIG_DFL);}void refuse(int sig){    printf("no i do not quit ! \n");    signal(SIGTSTP, SIG_DFL);}int main(){    //改变终端中断信号SIGINT的默认行为,使之执行ouch函数    //而不是终止程序的执行   (void) signal(SIGINT, ouch);    //(void) signal(SIGQUIT,refuse); ctl——z 无法捕获到,不知道为什么    while(1)    {        printf("Hello World!\n");        sleep(1);    }    return 0;}

相关结构体

struct task_struct {    volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */    void *stack;    atomic_t usage;    unsigned int flags; /* per process flags, defined below */    unsigned int ptrace;#ifdef CONFIG_SMP    struct llist_node wake_entry;    int on_cpu;#endif    int on_rq;    int prio, static_prio, normal_prio;    unsigned int rt_priority;    const struct sched_class *sched_class;    struct sched_entity se;    struct sched_rt_entity rt;#ifdef CONFIG_SCHED_HMP    struct ravg ravg;#endif#ifdef CONFIG_CGROUP_SCHED    struct task_group *sched_task_group;#endif#ifdef CONFIG_PREEMPT_NOTIFIERS    /* list of struct preempt_notifier: */    struct hlist_head preempt_notifiers;#endif    /*     * fpu_counter contains the number of consecutive context switches     * that the FPU is used. If this is over a threshold, the lazy fpu     * saving becomes unlazy to save the trap. This is an unsigned char     * so that after 256 times the counter wraps and the behavior turns     * lazy again; this to deal with bursty apps that only use FPU for     * a short time     */    unsigned char fpu_counter;#ifdef CONFIG_BLK_DEV_IO_TRACE    unsigned int btrace_seq;#endif    unsigned int policy;    int nr_cpus_allowed;    cpumask_t cpus_allowed;#ifdef CONFIG_PREEMPT_RCU    int rcu_read_lock_nesting;    char rcu_read_unlock_special;    struct list_head rcu_node_entry;#endif /* #ifdef CONFIG_PREEMPT_RCU */#ifdef CONFIG_TREE_PREEMPT_RCU    struct rcu_node *rcu_blocked_node;#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */#ifdef CONFIG_RCU_BOOST    struct rt_mutex *rcu_boost_mutex;#endif /* #ifdef CONFIG_RCU_BOOST */#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)    struct sched_info sched_info;#endif    struct list_head tasks;#ifdef CONFIG_SMP    struct plist_node pushable_tasks;#endif    struct mm_struct *mm, *active_mm;#ifdef CONFIG_COMPAT_BRK    unsigned brk_randomized:1;#endif#if defined(SPLIT_RSS_COUNTING)    struct task_rss_stat    rss_stat;#endif/* task state */    int exit_state;    int exit_code, exit_signal;    int pdeath_signal;  /*  The signal sent when the parent dies  */    unsigned int jobctl;    /* JOBCTL_*, siglock protected */    /* Used for emulating ABI behavior of previous Linux versions */    unsigned int personality;    unsigned did_exec:1;    unsigned in_execve:1;   /* Tell the LSMs that the process is doing an                 * execve */    unsigned in_iowait:1;    /* Revert to default priority/policy when forking */    unsigned sched_reset_on_fork:1;    unsigned sched_contributes_to_load:1;    unsigned long atomic_flags; /* Flags needing atomic access. */    pid_t pid;    pid_t tgid;#ifdef CONFIG_CC_STACKPROTECTOR    /* Canary value for the -fstack-protector gcc feature */    unsigned long stack_canary;#endif    /*     * pointers to (original) parent process, youngest child, younger sibling,     * older sibling, respectively.  (p->father can be replaced with     * p->real_parent->pid)     */    struct task_struct __rcu *real_parent; /* real parent process */    struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */    /*     * children/sibling forms the list of my natural children     */    struct list_head children;  /* list of my children */    struct list_head sibling;   /* linkage in my parent's children list */    struct task_struct *group_leader;   /* threadgroup leader */    /*     * ptraced is the list of tasks this task is using ptrace on.     * This includes both natural children and PTRACE_ATTACH targets.     * p->ptrace_entry is p's link on the p->parent->ptraced list.     */    struct list_head ptraced;    struct list_head ptrace_entry;    /* PID/PID hash table linkage. */    struct pid_link pids[PIDTYPE_MAX];    struct list_head thread_group;    struct list_head thread_node;    struct completion *vfork_done;      /* for vfork() */    int __user *set_child_tid;      /* CLONE_CHILD_SETTID */    int __user *clear_child_tid;        /* CLONE_CHILD_CLEARTID */    cputime_t utime, stime, utimescaled, stimescaled;    cputime_t gtime;    unsigned long long cpu_power;#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE    struct cputime prev_cputime;#endif#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN    seqlock_t vtime_seqlock;    unsigned long long vtime_snap;    enum {        VTIME_SLEEPING = 0,        VTIME_USER,        VTIME_SYS,    } vtime_snap_whence;#endif    unsigned long nvcsw, nivcsw; /* context switch counts */    struct timespec start_time;         /* monotonic time */    struct timespec real_start_time;    /* boot based time *//* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */    unsigned long min_flt, maj_flt;    struct task_cputime cputime_expires;    struct list_head cpu_timers[3];/* process credentials */    const struct cred __rcu *real_cred; /* objective and real subjective task                     * credentials (COW) */    const struct cred __rcu *cred;  /* effective (overridable) subjective task                     * credentials (COW) */    char comm[TASK_COMM_LEN]; /* executable name excluding path                     - access with [gs]et_task_comm (which lock                       it with task_lock())                     - initialized normally by setup_new_exec *//* file system info */    int link_count, total_link_count;#ifdef CONFIG_SYSVIPC/* ipc stuff */    struct sysv_sem sysvsem;#endif#ifdef CONFIG_DETECT_HUNG_TASK/* hung task detection */    unsigned long last_switch_count;#endif/* CPU-specific state of this task */    struct thread_struct thread;/* filesystem information */    struct fs_struct *fs;/* open file information */    struct files_struct *files;/* namespaces */    struct nsproxy *nsproxy;/* signal handlers */    struct signal_struct *signal;//进程信号描述符    struct sighand_struct *sighand; //信号处理程序描述符    sigset_t blocked, real_blocked;//被阻塞信号的掩码,临时掩码    sigset_t saved_sigmask; /* restored if set_restore_sigmask() was used */    struct sigpending pending; //存放私有挂起信号    unsigned long sas_ss_sp; //信号处理程序备用堆栈地址    size_t sas_ss_size; //堆栈大小    int (*notifier)(void *priv); //函数指针,设备驱动用这个函数阻塞进程的某些信号    void *notifier_data;//notifier 函数的参数    sigset_t *notifier_mask;//函数所阻塞信号的位掩码    struct callback_head *task_works;    struct audit_context *audit_context;#ifdef CONFIG_AUDITSYSCALL    kuid_t loginuid;    unsigned int sessionid;#endif    struct seccomp seccomp;/* Thread group tracking */    u32 parent_exec_id;    u32 self_exec_id;/* Protection of (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, * mempolicy */    spinlock_t alloc_lock;    /* Protection of the PI data structures: */    raw_spinlock_t pi_lock;#ifdef CONFIG_RT_MUTEXES    /* PI waiters blocked on a rt_mutex held by this task */    struct plist_head pi_waiters;    /* Deadlock detection and priority inheritance handling */    struct rt_mutex_waiter *pi_blocked_on;#endif#ifdef CONFIG_DEBUG_MUTEXES    /* mutex deadlock detection */    struct mutex_waiter *blocked_on;#endif#ifdef CONFIG_TRACE_IRQFLAGS    unsigned int irq_events;    unsigned long hardirq_enable_ip;    unsigned long hardirq_disable_ip;    unsigned int hardirq_enable_event;    unsigned int hardirq_disable_event;    int hardirqs_enabled;    int hardirq_context;    unsigned long softirq_disable_ip;    unsigned long softirq_enable_ip;    unsigned int softirq_disable_event;    unsigned int softirq_enable_event;    int softirqs_enabled;    int softirq_context;#endif#ifdef CONFIG_LOCKDEP# define MAX_LOCK_DEPTH 48UL    u64 curr_chain_key;    int lockdep_depth;    unsigned int lockdep_recursion;    struct held_lock held_locks[MAX_LOCK_DEPTH];    gfp_t lockdep_reclaim_gfp;#endif/* journalling filesystem info */    void *journal_info;/* stacked block device info */    struct bio_list *bio_list;#ifdef CONFIG_BLOCK/* stack plugging */    struct blk_plug *plug;#endif/* VM state */    struct reclaim_state *reclaim_state;    struct backing_dev_info *backing_dev_info;    struct io_context *io_context;    unsigned long ptrace_message;    siginfo_t *last_siginfo; /* For ptrace use.  */    struct task_io_accounting ioac;#if defined(CONFIG_TASK_XACCT)    u64 acct_rss_mem1;  /* accumulated rss usage */    u64 acct_vm_mem1;   /* accumulated virtual memory usage */    cputime_t acct_timexpd; /* stime + utime since last update */#endif#ifdef CONFIG_CPUSETS    nodemask_t mems_allowed;    /* Protected by alloc_lock */    seqcount_t mems_allowed_seq;    /* Seqence no to catch updates */    int cpuset_mem_spread_rotor;    int cpuset_slab_spread_rotor;#endif#ifdef CONFIG_CGROUPS    /* Control Group info protected by css_set_lock */    struct css_set __rcu *cgroups;    /* cg_list protected by css_set_lock and tsk->alloc_lock */    struct list_head cg_list;#endif#ifdef CONFIG_FUTEX    struct robust_list_head __user *robust_list;#ifdef CONFIG_COMPAT    struct compat_robust_list_head __user *compat_robust_list;#endif    struct list_head pi_state_list;    struct futex_pi_state *pi_state_cache;#endif#ifdef CONFIG_PERF_EVENTS    struct perf_event_context *perf_event_ctxp[perf_nr_task_contexts];    struct mutex perf_event_mutex;    struct list_head perf_event_list;#endif#ifdef CONFIG_NUMA    struct mempolicy *mempolicy;    /* Protected by alloc_lock */    short il_next;    short pref_node_fork;#endif#ifdef CONFIG_NUMA_BALANCING    int numa_scan_seq;    int numa_migrate_seq;    unsigned int numa_scan_period;    u64 node_stamp;         /* migration stamp  */    struct callback_head numa_work;#endif /* CONFIG_NUMA_BALANCING */    struct rcu_head rcu;    /*     * cache last used pipe for splice     */    struct pipe_inode_info *splice_pipe;    struct page_frag task_frag;#ifdef  CONFIG_TASK_DELAY_ACCT    struct task_delay_info *delays;#endif#ifdef CONFIG_FAULT_INJECTION    int make_it_fail;#endif    /*     * when (nr_dirtied >= nr_dirtied_pause), it's time to call     * balance_dirty_pages() for some dirty throttling pause     */    int nr_dirtied;    int nr_dirtied_pause;    unsigned long dirty_paused_when; /* start of a write-and-pause period */#ifdef CONFIG_LATENCYTOP    int latency_record_count;    struct latency_record latency_record[LT_SAVECOUNT];#endif    /*     * time slack values; these are used to round up poll() and     * select() etc timeout values. These are in nanoseconds.     */    unsigned long timer_slack_ns;    unsigned long default_timer_slack_ns;#ifdef CONFIG_FUNCTION_GRAPH_TRACER    /* Index of current stored address in ret_stack */    int curr_ret_stack;    /* Stack of return addresses for return function tracing */    struct ftrace_ret_stack *ret_stack;    /* time stamp for last schedule */    unsigned long long ftrace_timestamp;    /*     * Number of functions that haven't been traced     * because of depth overrun.     */    atomic_t trace_overrun;    /* Pause for the tracing */    atomic_t tracing_graph_pause;#endif#ifdef CONFIG_TRACING    /* state flags for use by tracers */    unsigned long trace;    /* bitmask and counter of trace recursion */    unsigned long trace_recursion;#endif /* CONFIG_TRACING */#ifdef CONFIG_MEMCG /* memcg uses this to do batch job */    struct memcg_batch_info {        int do_batch;   /* incremented when batch uncharge started */        struct mem_cgroup *memcg; /* target memcg of uncharge */        unsigned long nr_pages; /* uncharged usage */        unsigned long memsw_nr_pages; /* uncharged mem+swap usage */    } memcg_batch;    unsigned int memcg_kmem_skip_account;#endif#ifdef CONFIG_HAVE_HW_BREAKPOINT    atomic_t ptrace_bp_refcnt;#endif#ifdef CONFIG_UPROBES    struct uprobe_task *utask;#endif#if defined(CONFIG_BCACHE) || defined(CONFIG_BCACHE_MODULE)    unsigned int    sequential_io;    unsigned int    sequential_io_avg;#endif};

信号描述符 signal_struct

/* * NOTE! "signal_struct" does not have its own * locking, because a shared signal_struct always * implies a shared sighand_struct, so locking * sighand_struct is always a proper superset of * the locking of signal_struct. */struct signal_struct {    atomic_t        sigcnt;//使用计数器    atomic_t        live;//线程组中活动的进程数量    int         nr_threads;    struct list_head    thread_head;    wait_queue_head_t   wait_chldexit;  /* for wait4() *///在系统调用wait4中睡眠的进程等待队列    /* current thread group signal load-balancing target: */    struct task_struct  *curr_target;//接收信号的县城住中间最后一个进程的描述符    /* shared signal handling: */    struct sigpending   shared_pending;//共享挂起信号    /* thread group exit support */    int         group_exit_code; //线程组的进程终止码    /* overloaded:     * - notify group_exit_task when ->count is equal to notify_count     * - everyone except group_exit_task is stopped during signal delivery     *   of fatal signals, group_exit_task processes the signal.     */    int         notify_count;  //在杀死整个线程组的时候使用    struct task_struct  *group_exit_task;//在杀死整个线程组的时候使用    /* thread group stop support, overloads group_exit_code too */    int         group_stop_count; //在  停止 整个线程组的时候使用    unsigned int        flags; /* see SIGNAL_* flags below */    /*     * PR_SET_CHILD_SUBREAPER marks a process, like a service     * manager, to re-parent orphan (double-forking) child processes     * to this process instead of 'init'. The service manager is     * able to receive SIGCHLD signals and is able to investigate     * the process until it calls wait(). All children of this     * process will inherit a flag if they should look for a     * child_subreaper process at exit.     */    unsigned int        is_child_subreaper:1;    unsigned int        has_child_subreaper:1;    /* POSIX.1b Interval Timers */    int         posix_timer_id;    struct list_head    posix_timers;    /* ITIMER_REAL timer for the process */    struct hrtimer real_timer;    struct pid *leader_pid;    ktime_t it_real_incr;    /*     * ITIMER_PROF and ITIMER_VIRTUAL timers for the process, we use     * CPUCLOCK_PROF and CPUCLOCK_VIRT for indexing array as these     * values are defined to 0 and 1 respectively     */    struct cpu_itimer it[2];    /*     * Thread group totals for process CPU timers.     * See thread_group_cputimer(), et al, for details.     */    struct thread_group_cputimer cputimer;    /* Earliest-expiration cache. */    struct task_cputime cputime_expires;    struct list_head cpu_timers[3];    struct pid *tty_old_pgrp;    /* boolean value for session group leader */    int leader;    struct tty_struct *tty; /* NULL if no tty */#ifdef CONFIG_SCHED_AUTOGROUP    struct autogroup *autogroup;#endif    /*     * Cumulative resource counters for dead threads in the group,     * and for reaped dead child processes forked by this group.     * Live threads maintain their own counters and add to these     * in __exit_signal, except for the group leader.     */    cputime_t utime, stime, cutime, cstime;    cputime_t gtime;    cputime_t cgtime;#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE    struct cputime prev_cputime;#endif    unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;    unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;    unsigned long inblock, oublock, cinblock, coublock;    unsigned long maxrss, cmaxrss;    struct task_io_accounting ioac;    /*     * Cumulative ns of schedule CPU time fo dead threads in the     * group, not including a zombie group leader, (This only differs     * from jiffies_to_ns(utime + stime) if sched_clock uses something     * other than jiffies.)     */    unsigned long long sum_sched_runtime;    /*     * We don't bother to synchronize most readers of this at all,     * because there is no reader checking a limit that actually needs     * to get both rlim_cur and rlim_max atomically, and either one     * alone is a single word that can safely be read normally.     * getrlimit/setrlimit use task_lock(current->group_leader) to     * protect this instead of the siglock, because they really     * have no need to disable irqs.     */    struct rlimit rlim[RLIM_NLIMITS];#ifdef CONFIG_BSD_PROCESS_ACCT    struct pacct_struct pacct;  /* per-process accounting information */#endif#ifdef CONFIG_TASKSTATS    struct taskstats *stats;#endif#ifdef CONFIG_AUDIT    unsigned audit_tty;    unsigned audit_tty_log_passwd;    struct tty_audit_buf *tty_audit_buf;#endif#ifdef CONFIG_CGROUPS    /*     * group_rwsem prevents new tasks from entering the threadgroup and     * member tasks from exiting,a more specifically, setting of     * PF_EXITING.  fork and exit paths are protected with this rwsem     * using threadgroup_change_begin/end().  Users which require     * threadgroup to remain stable should use threadgroup_[un]lock()     * which also takes care of exec path.  Currently, cgroup is the     * only user.     */    struct rw_semaphore group_rwsem;#endif    oom_flags_t oom_flags;    short oom_score_adj;        /* OOM kill score adjustment */    short oom_score_adj_min;    /* OOM kill score adjustment min value.                     * Only settable by CAP_SYS_RESOURCE. */    struct mutex cred_guard_mutex;  /* guard against foreign influences on                     * credential calculations                     * (notably. ptrace) */};

信号处理程序描述符:

struct sighand_struct {    atomic_t        count; //计数器    struct k_sigaction  action[_NSIG];//在所传递的信号上执行操作的结构数组    spinlock_t      siglock;//保护信号描述符和信号处理函数的描述符的自旋锁    wait_queue_head_t   signalfd_wqh;};
原创粉丝点击