`
boisterous
  • 浏览: 63530 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类

信号量基础知识

阅读更多
linux 中信号相关的一个结构体 struct sigaction 主要在sigaction信号安装和sigqueue信号发送时会用到
该结构位于/usr/include/bits/sigaction.h
在里面可以找到该结构的描述 {我现在实现的系统是as 4 内核版本 2.6.9-5.EL}
/* Structure describing the action to be taken when a signal arrives.     */
struct sigaction
     {
       /* Signal handler.     */
#ifdef __USE_POSIX199309
       union  
         {
       /* Used if SA_SIGINFO is not set.     */
       __sighandler_t sa_handler;
       /* Used if SA_SIGINFO is set.     */
       void (*sa_sigaction) (int, siginfo_t *, void *);
         }
       __sigaction_handler;
# define sa_handler __sigaction_handler.sa_handler
# define sa_sigaction      __sigaction_handler.sa_sigaction
#else
       __sighandler_t sa_handler;
#endif

       /* Additional set of signals to be blocked.     */
       __sigset_t sa_mask;

       /* Special flags.     */
       int sa_flags;

       /* Restore handler.     */
       void (*sa_restorer) (void);
     };

在网上查了一些书料这个结构大概是这样的
其中,sa_restorer,已过时,POSIX不支持它,不应再被使用。
1、联合数据结构中的两个元素_sa_handler以及*_sa_sigaction指定信号关联函数,即用户指定的信号处理函数。除了可以是用户自定义的处理函数外,还可以为SIG_DFL(采用缺省的处理方式),也可以为SIG_IGN(忽略信号)。
2、由_sa_handler指定的处理函数只有一个参数,即信号值,所以信号不能传递除信号值之外的任何信息;由_sa_sigaction是指定的信号处理函数带有三个参数,是为实时信号而设的(当然同样支持非实时信号),它指定一个3参数信号处理函数。第一个参数为信号值,第三个参数没有使用(posix没有规范使用该参数的标准),第二个参数是指向siginfo_t结构的指针,结构中包含信号携带的数据值,参数所指向的结构如下:
在/usr/include/bits/siginfo.h中是这样定义的

typedef struct siginfo
{
     int si_signo;            /* Signal number.     */
     int si_errno;            /* If non-zero, an errno value associated with
                      this signal, as defined in <errno.h>.     */
     int si_code;             /* Signal code.     */

     union
     {
       int _pad[__SI_PAD_SIZE];

       /* kill().     */
       struct
       {
         __pid_t si_pid;          /* Sending process ID.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
       } _kill;

       /* POSIX.1b timers.     */
       struct
       {
         int si_tid;          /* Timer ID.     */
         int si_overrun;          /* Overrun count.     */
         sigval_t si_sigval;      /* Signal value.     */
       } _timer;

       /* POSIX.1b signals.     */
       struct
       {
         __pid_t si_pid;          /* Sending process ID.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
         sigval_t si_sigval;      /* Signal value.     */
       } _rt;

       /* SIGCHLD.     */
       struct
       {
         __pid_t si_pid;          /* Which child.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
         int si_status;           /* Exit value or signal.     */
         __clock_t si_utime;
         __clock_t si_stime;
       } _sigchld;

       /* SIGILL, SIGFPE, SIGSEGV, SIGBUS.     */
       struct
       {
         void *si_addr;           /* Faulting insn/memory ref.     */
       } _sigfault;

       /* SIGPOLL.     */
       struct
       {
         long int si_band;        /* Band event for SIGPOLL.     */
         int si_fd;
       } _sigpoll;
     } _sifields;
} siginfo_t;


是不是太复杂了,在网上有一个简洁版我搬过来用一下

siginfo_t {
                     int         si_signo;     /* 信号值,对所有信号有意义*/
                     int         si_errno;     /* errno值,对所有信号有意义*/
                     int         si_code;      /* 信号产生的原因,对所有信号有意义*/
union{      /* 联合数据结构,不同成员适应不同信号 */
//确保分配足够大的存储空间
int _pad[SI_PAD_SIZE];
//对SIGKILL有意义的结构
struct{
...
     }...
... ...
... ...
//对SIGILL, SIGFPE, SIGSEGV, SIGBUS有意义的结构
         struct{
...
     }...
... ...
     }
}



3、sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。缺省情况下当前信号本身被阻塞,防止信号的嵌套发送,除非指定SA_NODEFER或者SA_NOMASK标志位。

注:请注意sa_mask指定的信号阻塞的前提条件,是在由sigaction()安装信号的处理函数执行过程中由sa_mask指定的信号才被阻塞。

4、sa_flags中包含了许多标志位,包括刚刚提到的SA_NODEFER及SA_NOMASK标志位。另一个比较重要的标志位是SA_SIGINFO,当设定了该标志位时,表示信号附带的参数可以被传递到信号处理函数中,因此,应该为sigaction结构中的sa_sigaction指定处理函数,而不应该为sa_handler指定信号处理函数,否则,设置该标志变得毫无意义。即使为sa_sigaction指定了信号处理函数,如果不设置SA_SIGINFO,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误(Segmentation fault)。

注:很多文献在阐述该标志位时都认为,如果设置了该标志位,就必须定义三参数信号处理函数。实际不是这样的,验证方法很简单:自己实现一个单一参数信号处理函数,并在程序中设置该标志位,可以察看程序的运行结果。实际上,可以把该标志位看成信号是否传递参数的开关,如果设置该位,则传递参数;否则,不传递参数。


结构说的也差不多了,其实在我看到这些东西的时候给弄晕了好几回,简单的说几句就是
如果要在某信号产生时触发某些动作我们就可以安装信号

signal 用于安装不可靠信号     linux现在是用sigaction实现的
sigaction 用于安装可靠信号 当然他也可以安装不可靠信号 并且可以附带更多的信息

signal安装信号时只需传入2个参数 一个是信号的值     一个是信号发生时触发的函数,该函数接受一个整数
sigaction 安装时有3个参数 第一个参数是信号的值,第二个是sigaction结构 这个结构说明了信号发生时调用的函数和其它的一些信息,主要的成员是 sa_handler 指定的触发函数只带一个参数即信号的值 这和signal调用没什么区别,sa_sigaction指定的触发函数带有3个参数 第一个参数是信号的值,第二个参数是包函附加信息的结构siginfo,第三个参数为空 如果要传递附加信息给触发函数那么必须将传给sigaction的第二个参数sigaction结构的sa_flag设为SA_SIGINFO
上面说了那么多结构体和复杂的很的siginfo,其实siginfo我们在实际应用中并不需要去初始化他或者做什么,只是在信号触发时我们可以从这个结构体中提取一些信息

说了这么多我们可以小试牛刀了
自己写一个程序
[root@localhost clang]# cat f4.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>

void test(int n,struct siginfo *siginfo,void *myact)
{
         printf("signal number:%d\n",n);/** 打印出信号值 **/
         printf("siginfo signo:%d\n",siginfo->si_signo); /** siginfo结构里保存的信号值 **/
         printf("siginfo errno:%d\n",siginfo->si_errno); /** 打印出错误代码 **/
         printf("siginfo code:%d\n",siginfo->si_code);   /** 打印出出错原因 **/
}
int main(void)
{
         /** install signal use sigaction **/
         struct sigaction act;
         sigemptyset(&act.sa_mask);   /** 清空阻塞信号 **/
         act.sa_flags=SA_SIGINFO;     /** 设置SA_SIGINFO 表示传递附加信息到触发函数 **/
         act.sa_sigaction=test;
         if(sigaction(SIGINT,&act,NULL) < 0)
         {
                 printf("install signal error\n");
         }
         while(1)
         {
                 sleep(1);
                 printf("wait for the signal\n");
         }
}
[root@localhost clang]#
[root@localhost clang]# ./test
wait for the signal
wait for the signal
wait for the signal
wait for the signal
signal number:2
siginfo signo:2
siginfo errno:0
siginfo code:128
wait for the signal
wait for the signal
wait for the signal
signal number:2
siginfo signo:2
siginfo errno:0
siginfo code:128
wait for the signal

[2]+   Stopped                  ./test
[root@localhost clang]# kill %1

[1]-   Stopped                  vim f4.c
[root@localhost clang]#

可以看到当按下CTRL+C结束程序时信号将触发执行test函数
分享到:
评论

相关推荐

    分布式锁与信号量基础知识+编程技术+项目开发

    分布式锁与信号量,分布式锁与信号量基础知识+编程技术+项目开发;分布式锁与信号量,分布式锁与信号量基础知识+编程技术+项目开发;分布式锁与信号量,分布式锁与信号量基础知识+编程技术+项目开发;分布式锁与信号...

    LT-ARM214X学习板ucos任务间信号量通信实验

    这个实验适合对嵌入式系统有一定基础的开发者,通过实际操作,能加深对uC/OS和信号量通信的理解,提升多任务环境下的编程能力。如果你正在使用LT-ARM214X学习板,这个实验将是一个很好的学习资源,帮助你在实践中...

    The Little Book of Semaphores

    《The Little Book of Semaphores》不仅是一本关于信号量基础知识的书籍,更是深入探讨了信号量的实际应用场景和技术细节。通过学习本书,读者可以更好地理解和运用信号量这一强大的工具,有效解决进程间的同步问题...

    STM32CubeMX FreeRTOS学习[3]-计数信号量

    计数信号量(Counting Semaphores)是FreeRTOS操作系统中用于任务同步和资源管理的一种机制,它允许一个信号量在一段时间内持有多个计数。与二值信号量不同的是,计数信号量可以对多个事件或资源进行管理,从而避免...

    操作系统实验1用信号量来实现读者-写者问题

    在这个实验中,通过使用信号量来实现这种协调机制,重点在于理解和实践进程(或线程)及信号量的概念。 ### 二、信号量的概念与应用 **信号量**是一种用于解决进程间同步问题的数据结构。它可以用来控制多个进程对...

    信号量机制(pv操作)1

    以上是关于信号量机制(PV操作)的基础知识以及如何应用于解决经典同步问题的概述。这些概念在多线程编程和操作系统设计中至关重要,它们帮助确保并发进程之间的正确协调,防止数据竞争和死锁等问题。

    基于Linux的实现进程的信号量互斥申请

    1. **信号量的基本概念**:理解信号量的两种类型——二进制信号量(Binary Semaphore)和计数信号量(Counting Semaphore)。二进制信号量仅能取0或1,常用于互斥访问;计数信号量则可以有任意非负整数值,用于同步...

    OS_任务调度+信号量机制(工程文件).zip

    信号量分为两种类型:整型信号量和二进制信号量。整型信号量可以表示资源共享的数量,而二进制信号量仅用于表示资源是否存在。P(wait)操作用于申请资源,V(signal)操作用于释放资源。当资源不足时,P操作会导致...

    操作系统作业

    #### 一、进程同步与信号量基础知识 **知识点1:信号量机制** 信号量是一种常用的进程同步机制,用于解决进程间的互斥与同步问题。信号量可以分为以下两种类型: - **二元信号量**:通常用来实现互斥,其值只能是...

    电子科大操作系统课程报告信号量哲学家就餐,生产者消费者实验_信号量生产者消费者pv完整代码

    《电子科大操作系统课程报告:信号量在哲学家就餐与生产者消费者问题中的应用》 在计算机科学领域,操作系统课程中的经典实验常常涉及到进程的同步和互斥问题,其中信号量是解决这些问题的重要工具。本实验主要研究...

    信号量的应用关于读者优先还是写者优先的

    ### 信号量基础概念 信号量是操作系统中一种重要的同步机制,主要用于解决进程间的同步问题。信号量可以视为一个整型变量,用来记录对某种资源的访问权限。 #### 信号量结构定义 ```pascal type semaphore = ...

    信号量--笔记

    ### 信号量基础概念 信号量是计算机科学中一种用于控制多个进程对共享资源访问的同步机制。在多线程或多进程环境中,信号量能够确保某一时刻只有一个进程或线程可以访问共享资源,从而避免了资源冲突的问题。信号量...

    VxWorks入门实验课

    1. **信号量基础知识:** 信号量是实现进程同步的一种机制,用于管理多个任务之间的访问权限,确保共享资源不会被同时访问而导致数据不一致。 2. **信号量操作函数:** 在 VxWorks 中,信号量主要通过 `semMCreate()...

    【基础知识】什么是模拟信号

    模拟信号是电子电路和信息处理领域中一个非常重要的概念,它是与数字信号相对应的一种信号类型。...掌握模拟信号的特点以及它与数字信号之间的区别,对于从事相关领域的工程师和技术人员来说是十分必要的基础知识点。

    什么是分布式锁与信号量以及学习分布式锁与信号量的意义

    ### 什么是分布式锁与信号量 在探讨分布式锁与信号量之前,我们首先需要了解这两个概念的基本含义及其在分布式系统中的...在未来的技术发展过程中,这些基础知识将继续发挥重要作用,并为新技术的诞生奠定坚实的基础。

    linux 网络编程 进程通信 信号量

    本文将深入探讨Linux网络编程的关键概念、进程通信以及信号量的应用。 一、Linux网络编程基础 1. **套接字(Sockets)**:套接字是网络通信的基本接口,它允许应用程序在不同或同一机器上的进程间交换数据。在...

    信号量小书.........

    它不仅涵盖了基础概念,还深入探讨了如何利用信号量来解决实际问题。 ##### 1. 同步机制简介 - **互斥锁(Mutex)**:一种用于保护共享资源免受并发访问影响的基本同步机制。 - **信号量(Semaphore)**:用于控制...

    信号完整性基础知识

    ### 信号完整性基础知识详解 #### 一、信号完整性的概念及重要性 信号完整性是指信号在传输过程中的质量保持情况,特别是在高速数字电路设计中,它成为了一个非常关键的因素。随着通讯技术和计算机技术的快速发展...

Global site tag (gtag.js) - Google Analytics