精华内容
下载资源
问答
  • 蓝牙自行车转向灯 自行车的转向灯! 动机 每天上下班骑自行车上下班后,我决定我需要一种更好的方式来指示我的转弯。 伸出我的手臂可能很危险,特别是如果您在雨中下坡骑行时(在温哥华很常见)。...
  • 基于stm32蓝牙智能小车设计

    万次阅读 多人点赞 2019-01-02 16:46:31
    - Hardware flow control disabled (RTS and CTS signals) 硬件控制流 - Receive and transmit enabled 使能发送和接收 */ USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_Word...

    前言:

    本文描述了一个由STM32微处理器、步进电机、蓝牙,L298N等模块构成的。该系统采用STM32微处理器为核心,在MDK环境下进行编程,通知控制L298N模块IN1~IN4引脚的高低电平进而控制电机的转动方向,使小车产生不同的转动模式。控制小车的转动模式通过蓝牙模块来实现,利用手机蓝牙助手和蓝牙模块相通,进而控制小车的各种运转模式。 代码、蓝牙Android apk地址:https://github.com/daohewang/Bluetooth-intelligent-car
    在这里插入图片描述

    整体框架:

    下面的图把核心连接部分都画出来了(其他部分按要求接就可以了,Vcc接电源,GND接地即可),图画的有点丑,希望大家不要介意呀(>-<)
    在这里插入图片描述

    硬件设计:

    使用微控制器为STM32F103RC,其芯片引脚如图所示
    在这里插入图片描述

    1. 芯片上所连接的部分:
      PC10 -> IN1; PC11 -> IN2; PC12 -> IN3; PD2 -> IN4; 这里芯片上的GPIO口连接是随机的,可以根据自己的方便选择。不过这里要注意的是,IN1和IN2是控制左电机的,IN3和IN4是控制右电机。因为这里我用来驱动电机的是L298N。接线的话左电机接输出A端口,每个孔接一根线,如果要驱动两个左电机的话,也是一样接法,每个孔接一根电机线。右电机接输出B 。
      这里要注意的是驱动小车转动需要接外接电源,也就是图片上的12V供电部分。外接电源正极接到12v供电口上,负极接到供电GND上,还有要注意的一点就是还要将开发板上的地接到供电GND上,保证电源和开发板共地。
      如图所示:
      在这里插入图片描述

    L298N逻辑电平表

    在这里插入图片描述
    2. JDY 30蓝牙模块
    JDY-30 透传模块是基于蓝牙 2.1 协议标准,工作频段为 2.4GHZ 范围,具有信号强、数据传输快、性能稳定等特性。支持蓝牙 SPP 串口协议,内置 PCB 天线,支持 UART 接口,蓝牙 Class 2,数据传输比 BLE 蓝牙快、可达到几十 K 每秒以上的速率。如图3.2所示。
    在这里插入图片描述
    实物图:
    在这里插入图片描述
    引脚功能说明
    1 、 UART-TX 串口输出,接开发板上的UART-Rx,电平为 TTL 电平
    2 、 UART-RX 串口输入,接开发板上的UART-Tx,电平为 TTL 电平
    3 、 VCC 3.3V 电源
    4 、 GND 电源地

    Android蓝牙助手已经包含到代码代码里了,直接下载即可。使用手机APP蓝牙连接JDY–30蓝牙模块。如图所示

    在这里插入图片描述
    这里的蓝牙助手使用方法要情调一下,可能有些同学不太会,点击右上角的连接按钮,先让手机连上蓝牙模块,一般连上了蓝牙模块上的灯都不会闪烁。以此判断有没有连接上。接着就是编辑键盘的小车的运动方式了,按照下面的来设置就可以了。这里的数字是我代码设置好的,可以按照自己的要求填写。
    在这里插入图片描述

    软件设计:

    软件流程图:

    首先对前进,后退,左转,右转,停止进行宏定义,单片机接收到蓝牙串口的相应指令,然后在if语句中进行比较,如果有相对应的,触发相对应的宏定义。流程图如图所示。在串口USART1中接收到的数据进行比较,暂停、前进、后退、左转、右转、原地左转,原地右转。启动字符为 “0”,“1”,“2”,“3”,“4”,“5”,“6”。

    在这里插入图片描述

    代码部分:

    电机驱动代码

    1.motor.h

    #ifndef _MOTOR_H
    
    #define _MOTOR_H
    
    void MotorInit(void);
    
    void Turnleft(void);
    
    void Turnright(void);
    
    void Turnback(void);
    
    void Turnfront(void);
    
    void Stop(void);
    
    void Leftaround(void);
    
    void Rightaround(void);
    
    #endif 
    
    

    2. motor.c

    #include "STM32F10X.h"
    #include "motor.h"
    
    void MotorInit(void)
    {
    	
    	//初始化和使能单片机上的GPIO端口,保证可以正常给端口高低电平
    	GPIO_InitTypeDef GPIO_InitStructure;
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
    	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
    	GPIO_Init(GPIOC, &GPIO_InitStructure);
    	GPIO_SetBits(GPIOC, GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_6);
    //	MOTOR_APB_PERIPH_FUNG(MOTOr_APB_PORT , ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD , ENABLE);
    	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_2;
    	GPIO_Init(GPIOD, &GPIO_InitStructure);
    	GPIO_SetBits(GPIOD, GPIO_Pin_2);
    }
    
    
    //停止模式
    void Stop(void)
    {
    	GPIO_ResetBits(GPIOC,GPIO_Pin_10);
    	GPIO_ResetBits(GPIOC,GPIO_Pin_11);
    	GPIO_ResetBits(GPIOC,GPIO_Pin_12);
    	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
    }
    
    
    //左转模式 -> 左电机正转,右电机反转
    void Turnleft(void)
    {
    	GPIO_SetBits(GPIOC,GPIO_Pin_10); 
    	GPIO_ResetBits(GPIOC,GPIO_Pin_11);
    	GPIO_ResetBits(GPIOC,GPIO_Pin_12);
    	GPIO_SetBits(GPIOD,GPIO_Pin_2);
    	GPIO_SetBits(GPIOC,GPIO_Pin_6);
    }
    
    //右转模式 -> 左电机反转,右电机正转
    void Turnright(void)
    {
    	GPIO_ResetBits(GPIOC,GPIO_Pin_10);
    	GPIO_SetBits(GPIOC,GPIO_Pin_11);
    	GPIO_SetBits(GPIOC,GPIO_Pin_12);
    	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
    	GPIO_SetBits(GPIOC,GPIO_Pin_6);
    }
    
    //后退模式 -> 左电机反转,右电机反转
    void Turnback(void)
    {
    	
    	GPIO_ResetBits(GPIOC,GPIO_Pin_10);
    	GPIO_SetBits(GPIOC,GPIO_Pin_11);
    	GPIO_ResetBits(GPIOC,GPIO_Pin_12);
    	GPIO_SetBits(GPIOD,GPIO_Pin_2);
    	GPIO_SetBits(GPIOC,GPIO_Pin_8);
    	
    }
    
    //前进模式 -> 左电机正转,右电机正转
    void Turnfront(void)
    {
    	GPIO_SetBits(GPIOC,GPIO_Pin_10);
    	GPIO_ResetBits(GPIOC,GPIO_Pin_11);
    	GPIO_SetBits(GPIOC,GPIO_Pin_12); 
    	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
    	GPIO_SetBits(GPIOC,GPIO_Pin_7);
    }
    
    //以左电机为中心原地左转
    void Leftaround(void)
    {
    	GPIO_SetBits(GPIOC,GPIO_Pin_10);
    	GPIO_ResetBits(GPIOC,GPIO_Pin_11);
    	GPIO_SetBits(GPIOC,GPIO_Pin_12);
    	GPIO_SetBits(GPIOD,GPIO_Pin_2);
    	
    }
    
    //以右电机为中心原地右转
    void Rightaround(void)
    {
    	GPIO_SetBits(GPIOC,GPIO_Pin_10);
    	GPIO_SetBits(GPIOC,GPIO_Pin_11);
    	GPIO_SetBits(GPIOC,GPIO_Pin_12);
    	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
    	
    }
    
    
    

    3. main函数

    #include "MOTOR.h"
    #include "stm32f10x.h"         //官方库
    #include "stm32f10x_gpio.h"
    #include "stm32f10x_rcc.h"
    #include "stm32f10x_it.h"
    #include <stdio.h>
    
    
    /*
    
    #ifdef->endif的内容部分和PUTCHAR_PROTOTYPE{}的内容属于C语言的语法规则引入,
    所以头部必须引入#include<stdio.h>,这样子的话C语言的语法就可以完美引用
    
    */
    
    
    #ifdef __GNUC__
      /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
         set to 'Yes') calls __io_putchar() */
      #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    #else
      #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    #endif /* __GNUC__ */
    
    
    //中断服务函数  
    u8 i;
    u8 flag;  //定义一个标志位
    void USART1_IRQHandler(void)  
      
    {  
         if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)      //检查指定的 USART1 中断发生与否
          { 
    			USART_ClearITPendingBit(USART1, USART_IT_RXNE);   //清除 USART1 的中断待处理位
    			GPIO_ResetBits(GPIOC,GPIO_Pin_6);                 //设置LED灯作为中断发生与否的指示灯
    			i=  USART_ReceiveData(USART1);                    //返回 USART1 最近接收到的数据
    		//if语句的内容部分可以保证蓝牙接收到的flag数据是正确的,如果不加的话会导致接收不到正确的数据
    		  if(i=='0')
    				{                 
    					 flag=0;
    				}
    				
    			if(i=='1')
    				{
    					 flag=1;
    				}
    				
    			if(i=='2')
    			   {
    					 flag=2;
    				}
    			   
    			if(i=='3')
    			   {
    								 
    					flag=3;
    			   }
    			   
    			if(i=='4')
    			  {
    					flag=4;
    			  }
    			  
    			if(i=='5')
    			  {
    					flag=5;
    			  }
    			  
    			if(i=='6')
    			 {
    					flag=6;
    			 }
    
    		  }
    		  
    //		  USART_ClearITPendingBit(USART1, USART_IT_RXNE);
          }
    	  
    	  
    int main(void)
    {
    	
    	//利用中断进行蓝牙的收发
    	
    	  GPIO_InitTypeDef GPIO_InitStructure;
    	  USART_InitTypeDef USART_InitStructure;
          NVIC_InitTypeDef NVIC_InitStructure;
    
    	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
    // 	USART_DeInit(USART1);  //复位串口1
    //  USART1_TX   PA.9
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
        GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
       
        //USART1_RX	  PA.10
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
        GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA10     
    	
    	 
        /* USARTx configured as follow:
           - BaudRate = 9600 baud  波特率
           - Word Length = 8 Bits  数据长度
           - One Stop Bit          停止位
           - No parity             校验方式
           - Hardware flow control disabled (RTS and CTS signals) 硬件控制流
           - Receive and transmit enabled                         使能发送和接收
        */
    		USART_InitStructure.USART_BaudRate = 9600;
    		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    		USART_InitStructure.USART_StopBits = USART_StopBits_1;
    		USART_InitStructure.USART_Parity = USART_Parity_No;
    		USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    		USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    
    		USART_Init(USART1, &USART_InitStructure);
    		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
    
        //Usart1 NVIC 配置
          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
          NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    	  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
    	  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
    	  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    	  NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
          USART_Cmd(USART1, ENABLE);                    //使能串口 
    	  MotorInit();
    	  
    	  
    	  //蓝牙数据接收判断函数
    	  while(1)
    	  {
    		
    		  switch(flag)
                  {
    					case 0:  Stop();         break  ;
    					case 1:  Turnleft();     break  ;
    					case 2:  Turnright();    break  ;
    					case 3:  Turnback();     break  ;
    					case 4:  Turnfront();    break  ;
    					case 5:  Leftaround();   break  ;
    					case 6:  Rightaround();  break  ;
                        default: Stop();         break  ;                                                                                                
    	          }		  
    	  }
    	  
    }
    
    PUTCHAR_PROTOTYPE
    {
      /* Place your implementation of fputc here */
      /* e.g. write a character to the USART */
     USART_SendData(USART1, (uint8_t) ch);
    
      /* 循环等待直到发送结束*/
      while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
      {}
    
      return ch;
    }
    
    

    以上就是蓝牙智能小车的全部部分了,完整代码可以到我的GitHub上进行下载,下载地址:https://github.com/daohewang/Bluetooth-intelligent-car如果还有问题的话,欢迎下方留言咨询。

    展开全文
  • On your way to work wach morning you travel down a main traffic artery regulated by a number of traffic signals. On some mornings, you have noticed that all of the lights up ahead simultaneously turn ...

    On your way to work wach morning you travel down a main traffic artery regulated by a number of traffic signals. On some mornings, you have noticed that all of the lights up ahead simultaneously turn green in your direction. But on other mornings, it seems that a random combination of red, yellow, and green is facing you.
    After recently observing all of the lights ahead of you turn green simultaneously, you began to wonder how long after any one of them turns to yellow it would take before they all would be displaying green in your direction again. Write a program to figure out how long it will take such a set of traffic signals to all be displaying green again, given the cycle times for each traffic signal in the set.
    Input
    The input file will consist of an unknown number of traffic signal datasets. Each signal dataset will consist of one line of integers (separated by spaces) giving the total cycle time (in seconds) for each signal. The cycle time is the total time that a signal will stay green and yellow in one direction and red in the opposite direction. In this problem, you may assume that a green signal will turn yellow for the last 5 seconds of its cycle. If one set of signals was given as:
    30   25   35 30 \ 25 \ 35 30 25 35
    your program would need to recognize that there are three signals in the set, that the first signal lasts 30 seconds, that the second signal cycles every 25 seconds, and that the thirs signal takes 35 seconds to start a new cycle. Specifically, the first signal will be red for 30 seconds in one direction, then green for 25 seconds, then yellow for 5.
        Each set of signals will involve at least two and as many as 10 signals. Each signal will have a minimum cycle time of 10 seconds and a maximum cycle time of 90 seconds.
    Output
    Your output will consist of a summary line for each set of signals. Your program should assign an ID number to each set of signals, beginning with set 1. The output line will begin with the signal set ID number and state the number of minutes (≤ 60) and seconds (< 60) it will take from when all of the signals simultaneously turn green initially to the first time they will all be showing green again in your direction after any of them has turned yellow. Note that this time may or may not be a time when all of the signals in the set simultaneously change back to green — for this problem you need only indicate how long it will be before all signals in the set are once again simultaneously showing green in your direction after any of them has turned to yellow, even if this condition will only exist for a second or a very few seconds.
        If the signals will never simultaneously display green in your direction again within an hour, you should print a message that states that the signals in the set are not able to synchronize after one hour (note that an output of 60 minutes and 0 seconds should, however, be considered a successful synchronization).
        Look at the sample output below for the exact format.
    Sample Input
    30 25 35
    25 25 25 25 25
    15 30
    20 21 30 23 29 25 27 22
    19 20
    Sample Output
    Set 1 synchs again at 5 minute(s) and 0 second(s) after all turning green.
    Set 2 synchs again at 0 minute(s) and 50 second(s) after all turning green.
    Set 3 synchs again at 1 minute(s) and 0 second(s) after all turning green.
    Set 4 is unable to synch after one hour.
    Set 5 synchs again at 0 minute(s) and 40 second(s) after all turning green.

    问题链接UVA467 Synching Signals
    问题简述:给定n个红绿灯,给定每个红绿灯时间time。从0时刻开始红绿灯以2*t周期绿黄红交替,时间分别为time-5,5,time。问所这n个灯全部变为绿灯后,再次变为全部绿灯需要多少时间?如果时间超过1小时则输出unable to synch after one hour。
    问题分析:1小时内的计算,用暴力法来解决。
    程序说明:(略)
    参考链接:(略)
    题记:(略)

    AC的C++语言程序如下:

    /* UVA467 Synching Signals */
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    char s[1024];
    int n, time2[16];
    
    bool judge(int u)
    {
        for (int i = 0; i < n; i++) {
            int d = u % (2 * time2[i]);
            if (d >= time2[i] - 5) return false;
        }
        return true;
    }
    
    int main()
    {
        int caseno = 0;
        while (gets(s)) {
            n = 0;
            int num = 0;
            for (int i = 0; s[i]; i++) {
                if (isdigit(s[i]))
                    num = num * 10 + s[i] - '0';
                else {
                    time2[n++] = num;
                    num = 0;
                }
            }
            if (num) time2[n++] = num;
    
            int start = time2[0];
            for (int i = 1; i < n; i++) start = min(start, time2[i]);
            start -= 5;
    
            bool flag = false, sign = true;
            int ans;
            for (int u = start + 1; u <= 3600; u++)
                if (sign) {
                    if (judge(u)) sign = true;
                    else sign = false;
                } else {
                    if (judge(u)) {
                        ans = u;
                        flag = true;
                        break;
                    }
                }
    
            if (flag)
                printf("Set %d synchs again at %d minute(s) and %d second(s) after all turning green.\n", ++caseno, ans / 60, ans % 60);
            else
                printf("Set %d is unable to synch after one hour.\n", ++caseno);
    
        }
    
        return 0;
    }
    
    展开全文
  • 10-Signals

    2016-09-10 09:52:20
    Please indicate the source: http://blog.csdn.net/gaoxiangnumber1Welcome to my github: https://github.com/gaoxiangnumber110.1 Introduction...Signals are software interrupts. Signals provide a way of handl

    Please indicate the source: http://blog.csdn.net/gaoxiangnumber1

    Welcome to my github: https://github.com/gaoxiangnumber1

    10.1 Introduction

    • Signals are software interrupts. Signals provide a way of handling asynchronous events.

    10.2 Signal Concepts

    • Signal names all begin with “SIG” and they are all defined by positive integer constants(the signal number) in

    10.3 signal Function

    #include <signal.h>
    typedef void Sigfunc(int);
    Sigfunc *signal(int, Sigfunc *);
    Returns: previous disposition of signal if OK, SIG_ERR on error
    • Because the semantics of signal differ among implementations, we must use sigaction function instead. We provide an implementation of signal that uses sigaction in Section 10.14.
    • signo is the name of the signal from Figure 10.1.
    • The value of func is
      (a) SIG_IGN: tell the system to ignore the signal.(SIGKILL and SIGSTOP can’t be ignored.)
      (b) SIG_DFL: set the action associated with the signal to its default value.(final column in Figure 10.1)
      (c) The address of a function to be called when the signal occurs: we call the function either the signal handler or the signal-catching function.
    • The return value from signal is the pointer to the previous signal handler. Many systems call the signal handler with additional arguments.(Section 10.14.)
    • In
    #define SIG_ERR (void(*)())-1   // Error return.
    #define SIG_DFL (void(*)())0        // Default action.
    #define SIG_IGN (void(*)())1        // Ignore signal.
    • These constants can be used in place of the “pointer to a function that takes an integer argument and returns nothing”, the second argument to signal, and the return value from signal.

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    static void sig_usr(int signo)
    {
        if(signo == SIGUSR1)
        {
            printf("received SIGUSR1\n");
        }
        else if(signo == SIGUSR2)
        {
            printf("received SIGUSR2\n");
        }
        else
        {
            printf("received signal %d\n", signo);
            exit(1);
        }
    }
    
    int main()
    {
        if(signal(SIGUSR1, sig_usr) == SIG_ERR)
        {
            Exit("can't catch SIGUSR1");
        }
        if(signal(SIGUSR2, sig_usr) == SIG_ERR)
        {
            Exit("can't catch SIGUSR2");
        }
        for(;;)
        {
            pause();
        }
    
        exit(0);
    }
    • The signal handler catches either of the two user-defined signals and prints the signal number. pause(Section 10.10) suspends the calling process until a signal is received.
    • We invoke the program in the background and use the kill(1) command to send it signals.
    $ ./a.out &                #start process in background
    [1] 7216                #job-control shell prints job number and process ID
    $ kill -USR1 7216      #send SIGUSR1
    received SIGUSR1
    $ kill -USR2 7216      #send SIGUSR2
    received SIGUSR2
    $ kill 7216                #now send SIGTERM
    [1]+ Terminated     ./a.out
    • When we send the SIGTERM signal, the process is terminated, since it doesn’t catch the signal, and the default action for the signal is termination.

    Program Start-Up

    • When a program is executed, the status of all signals is either default or ignore. Normally, all signals are set to their default action, unless the process that calls exec is ignoring the signal. exec change the disposition of any signals being caught to their default action and leave the status of all other signals alone.
    • A signal that is being caught by a process that calls exec cannot be caught by the same function in the new program, since the address of the signal-catching function in the caller probably has no meaning in the new program file that is executed.
    • Example of this signal status behavior:
      With a shell that doesn’t support job control, when we execute a process in the background, the shell automatically sets the disposition of the interrupt and quit signals in the background process to be ignored. So, if we type the interrupt character, it doesn’t affect the background process. If this weren’t done and we typed the interrupt character, it would terminate the foreground process and all the background processes.
    • Many interactive programs that catch these two signals have following code. The process catches the signal only if the signal is not currently being ignored.
    void sig_int(int), sig_quit(int);
    if(signal(SIGINT, SIG_IGN) != SIG_IGN)
    {
        signal(SIGINT, sig_int);
    }
    if(signal(SIGQUIT, SIG_IGN) != SIG_IGN)
    {
        signal(SIGQUIT, sig_quit);
    }
    • These two calls show a limitation of signal function: we are not able to determine the current disposition of a signal without changing the disposition.

    Process Creation

    • When a process calls fork, the child inherits the parent’s signal dispositions. Since the child starts with a copy of the parent’s memory image, the address of a signal catching function has meaning in the child.

    10.4 Unreliable Signals

    • In earlier versions of UNIX, signals were unreliable: a signal could occur and the process would never know about it. A process could catch the signal or ignore it. Sometimes, we would like to tell the kernel to block a signal: don’t ignore it, remember if it occurs, and tell us later when we’re ready.
    • One problem with early versions was that the action for a signal was reset to its default each time the signal occurred. Following code describes these earlier systems concerns how to handle the interrupt signal.
    int sig_int();// my signal handling function
    ...
    signal(SIGINT, sig_int);// establish handler
    ...
    sig_int()
    {
        signal(SIGINT, sig_int);// reestablish handler for next time
        ...// process the signal ...
    }
    • The problem is that there is a window of time(after the signal has occurred, but before the call to signal in the signal handler) when the interrupt signal could occur another time. This second signal would cause the default action to occur, which for this signal terminates the process.
    • Another problem with earlier systems was that the process was unable to turn a signal off when it didn’t want the signal to occur. All the process could do was ignore the signal. There are times when we would like to tell the system “prevent the following signals from interrupting me, but remember if they do occur.” Example is shown by a piece of code that catches a signal and sets a flag for the process that indicates that the signal occurred:
    int sig_int();      // my signal handling function
    int sig_int_flag;   // set nonzero when signal occurs
    main()
    {
        signal(SIGINT, sig_int);    // establish handler
        ...
        while(sig_int_flag == 0)
            pause();                // go to sleep, waiting for signal
        ...
    }
    sig_int()
    {
        signal(SIGINT, sig_int);    // reestablish handler for next time
        sig_int_flag = 1;           // set flag for main loop to examine
    }
    • The process is calling the pause function to put it to sleep until a signal is caught. When the signal is caught, the signal handler sets the flag sig_int_flag to a nonzero value. The process is awakened by the kernel after the signal handler returns, the flag is nonzero, and does whatever it needs to do.
    • But there is a window of time when things can go wrong: If the signal occurs after the test of sig_int_flag but before the call to pause, the process could go to sleep forever(assuming that the signal is never generated again). This occurrence of the signal is lost.

    10.5 Interrupted System Calls

    • If a process caught a signal while the process was blocked in a slow system call, the system call was interrupted. The system call return an error and errno was set to EINTR. This was done under the assumption that since a signal occurred and the process caught it, there is chance that something has happened that should wake up the blocked system call. Note that it is a system call within the kernel that is interrupted when a signal is caught, not a function.
    • The system calls are divided into two categories: slow system calls and all others. The slow system calls are those that can block forever:
      1. Reads can block the caller forever if data isn’t present with certain file types(pipes, terminal devices, and network devices).
      2. Writes can block the caller forever if the data can’t be accepted immediately by these same file types.
      3. Opens on certain file types that block the caller until some condition occurs(such as a terminal device open waiting until an attached modem answers the phone).
      4. pause function(which by definition puts the calling process to sleep until a signal is caught) and wait function.
      5. Certain ioctl operations
      6. Some of the interprocess communication functions(Chapter 15).
    • Exception to slow system calls is anything related to disk I/O. Although a read or a write of a disk file can block the caller temporarily while the disk driver queues the request and then the request is executed, unless a hardware error occurs, the I/O operation always returns and unblocks the caller quickly.
    • Earlier POSIX gave implementations a choice of how to deal with reads and writes that have processed partial amounts of data.
      1. If read has received and transferred data to an application’s buffer, but has not yet received all that the application requested and is then interrupted, operating system could either fail the system call, with errno set to EINTR, or allow the system call to succeed, returning the partial amount of data received.
      2. If write is interrupted after transferring some of the data in an application’s buffer, operation system could either fail the system call, with errno set to EINTR, or allow the system call to succeed, returning the partial amount of data written.
    • POSIX.1 2001 version of the standard: return partial success.
    • Problem with interrupted system calls is that we must handle the error return. The typical code sequence(assuming a read operation and assuming that we want to restart the read even if it’s interrupted) would be
    again:
        if((n = read(fd, buf, BUFFSIZE)) < 0)
        {
            if(errno == EINTR)
                goto again; // an interrupted system call
            // handle other errors
        }
    • To prevent applications from having to handle interrupted system calls, 4.2BSD introduced the automatic restarting of certain interrupted system calls. The system calls that were automatically restarted are ioctl, read, readv, write, writev, wait, and waitpid. The first five functions are interrupted by a signal only if they are operating on a slow device; wait and waitpid are always interrupted when a signal is caught. Since this caused a problem for some applications that didn’t want the operation restarted if it was interrupted, 4.3BSD allowed the process to disable this feature on a per-signal basis.
    • POSIX.1 requires an implementation to restart system calls only when the SA_RESTART flag is in effect for the interrupting signal. Section 10.14: this flag is used with the sigaction function to allow applications to request that interrupted system calls be restarted.
    • Linux: When signal handlers are installed with the signal function, interrupted system calls will be restarted.
    • Figure 10.3 summarizes the signal functions and their semantics provided by the various implementations.

    • Figure 10.18 provide our own version of the signal function that automatically tries to restart interrupted system calls(other than for the SIGALRM signal). Figure 10.19 provide function signal_intr that tries to never do the restart.

    10.6 Reentrant Functions

    • When a signal that is being caught is handled by a process, the normal sequence of instructions being executed by the process is temporarily interrupted by the signal handler. The process then execute the instructions in the signal handler. If the signal handler returns(instead of calling exit or longjmp), then the normal sequence of instructions that the process was executing when the signal was caught continues executing.(This is similar to what happens when a hardware interrupt occurs.)
    • In signal handler, we can’t tell where the process was executing when the signal was caught. What if the process was in the middle of allocating memory on its heap using malloc, and we call malloc from the signal handler? What if the process was in the middle of a call to getpwnam(Section 6.2), that stores its result in a static location, and we call the same function from the signal handler?
    • malloc: havoc can result for the process, since malloc usually maintains a linked list of all its allocated areas, and it may have been in the middle of changing this list.
      getpwnam: the information returned to the normal caller can get overwritten with the information returned to the signal handler.
    • The functions that are guaranteed to be safe to call from within a signal handler are reentrant and are called async-signal safe. Besides being reentrant, they block any signals during operation if delivery of a signal might cause inconsistencies.

    • Figure 10.4 lists async-signal safe functions. Most functions that are not async-signal safe because
      (a) they are known to use static data structures.
      (b) they call malloc or free.
      (c) they are part of the standard I/O library.
    • Most standard I/O library use global data structures in a non-reentrant way. When we call printf from signal handlers, it is not guaranteed to produce the expected results, since the signal handler can interrupt a call to printf from our main program.
    • Even if we call a function listed in Figure 10.4 from a signal handler, there is only one errno variable per thread(Section 1.7), and we might modify its value. Consider a signal handler that is invoked right after main has set errno. If the signal handler calls read, this call can change the value of errno, wiping out the value that was just stored in main.
      So we should save and restore errno when calling async-signal safe functions from a signal handler.(A commonly caught signal is SIGCHLD, and its signal handler usually calls one of the wait functions. All the wait functions can change errno.)
    • longjmp(Section 7.10) and siglongjmp(Section 10.15) are not in Figure 10.4 because the signal may have occurred while the main routine was updating a data structure in a non-reentrant way. This data structure could be left half updated if we call siglongjmp instead of returning from the signal handler. If it is going to do such things as update global data structures, while catching signals that cause sigsetjmp to be executed, an application needs to block the signals while updating the data structures.

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <pwd.h>
    #include <signal.h>
    #include <unistd.h>
    #include <string.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    static void my_alarm(int signo)
    {
        printf("Enter signal handler:\n");
        struct passwd *rootptr;
        printf("AAAAA\n");
        if((rootptr = getpwnam("root")) == NULL)
        {
            Exit("getpwnam(root) error");
        }
        printf("BBBBB\n");
        alarm(1);
        printf("Leave signal handler:\n");
    }
    
    int main()
    {
        struct passwd *ptr;
        signal(SIGALRM, my_alarm);
        printf("signal success\n");
        alarm(1);
        for(int cnt = 0;;++cnt)
        {
            if(cnt % 10000 == 0)
            {
                printf("for(;;) %d\n", cnt);
            }
            if((ptr = getpwnam("xiang")) == NULL)
            {
                Exit("getpwnam error");
            }
            if(strcmp(ptr->pw_name, "xiang") != 0)
            {
                printf("return value corrupted! pw_name = %s\n", ptr->pw_name);
            }
        }
    
        exit(0);
    }
    //
    Output:
    signal success
    for(;;) 0
    for(;;) 10000
    for(;;) 20000
    for(;;) 30000
    for(;;) 40000
    for(;;) 50000
    for(;;) 60000
    for(;;) 70000
    for(;;) 80000
    for(;;) 90000
    for(;;) 100000
    for(;;) 110000
    for(;;) 120000
    for(;;) 130000
    for(;;) 140000
    for(;;) 150000
    for(;;) 160000
    Enter signal handler:
    AAAAA
    ^C
    */
    • Figure 10.5: A program that calls the non-reentrant function getpwnam from a signal handler that is called every second(use alarm(Section 10.10) to generate SIGALRM signal every second).
    • When this program was run, the results were random. Usually, the program would be terminated by a SIGSEGV signal when the signal handler returned after several iterations. An examination of the core file showed that the main function had called getpwnam, but that when getpwnam called free, the signal handler interrupted it and called getpwnam, which in turn called free. The data structures maintained by malloc and free had been corrupted when the signal handler(indirectly) called free while the main function was also calling free. Occasionally, the program would run for several seconds before crashing with a SIGSEGV error. When the main function did run correctly after the signal had been caught, the return value was sometimes corrupted and sometimes fine.

    10.7 SIGCLD Semantics

    • Whenever a process terminates or stops, SIGCHLD is sent to the parent. This signal is ignored by default, so the parent must catch this signal if it wants to be notified whenever a child’s status changes. The normal action in the signal-catching function is to call one of the wait functions to fetch the child’s process ID and termination status.
    • System V has a signal named SIGCLD. The semantics of this signal were different from other signals. Applications should use SIGCHLD signal, but many systems define SIGCLD to be the same as SIGCHLD for backward compatibility. If you maintain software that uses SIGCLD, you need to check your system’s manual page to see which semantics it follows.
    • The semantics of the BSD SIGCHLD signal are similar to those of all other signals. When the signal occurs, the status of a child has changed, and we need to call one of the wait functions to determine what has happened.
    • System V handled SIGCLD differently from other signals. SVR4-based systems continue this tradition if we set its disposition using either signal or sigset. This older handling of SIGCLD consists of the following behavior:
      1. If the process sets its disposition to SIG_IGN, children of the calling process will not generate zombie processes. On termination, the status of these child processes is discarded. If it subsequently calls one of the wait functions, the calling process will block until all its children have terminated, and then wait returns -1 with errno set to ECHILD.
        —The default disposition of this signal is to be ignored, but this default will not cause the preceding semantics to occur. Instead, we specifically have to set its disposition to SIG_IGN.
        —Linux: If either signal or sigset is called to set the disposition of SIGCHLD to be ignored, zombies are never generated. We can also set the SA_NOCLDWAIT flag(Figure 10.16) with sigaction to avoid zombies.
      2. If we set the disposition of SIGCLD to be caught, the kernel immediately checks whether any child processes are ready to be waited for and, if so, calls the SIGCLD handler.
    • Section 10.4: The first thing to do on entry to a signal handler is to call signal again, to reestablish the handler. This action is intended to minimize the window of time when the signal is reset back to its default and could get lost.

    • Figure 10.6: This program doesn’t work on System V platforms. The output is a continual string of SIGCLD received lines. Eventually, the process runs out of stack space and terminates abnormally.
      Linux doesn’t have this problem because it doesn’t call the SIGCHLD signal handler when a process arranges to catch SIGCHLD and child processes are ready to be waited for, even though SIGCLD and SIGCHLD are defined to be the same value.
    • Problem with this program is that the call to signal at the beginning of the signal handler invokes item 2: the kernel checks whether a child needs to be waited for(which is the case, since we’re processing a SIGCLD signal), so it generates another call to the signal handler. The signal handler calls signal, and the whole process starts over again.
    • Solution: move the call to signal after the call to wait. We call signal after fetching the child’s termination status; the signal is generated again by the kernel only if some other child has since terminated.
    • Since POSIX.1 doesn’t reset a signal’s disposition to its default when the signal occurs(assuming we’re using the POSIX.1 sigaction function to set its disposition), there is no need for us to establish a signal handler for SIGCHLD within that handler.
    • Linux:
    #define SIGCLD  SIGCHLD // Same as SIGCHLD.
    #define SIGCHLD 17          // Child status has changed(POSIX).

    10.8 Reliable-Signal Terminology and Semantics

    • A signal is generated for a process(or sent to a process) when the event that causes the signal occurs. The event could be a hardware exception, a software condition, a terminal-generated signal, or a call to the kill function. When the signal is generated, the kernel sets a flag in the process table.
    • A signal is delivered to a process when the action for a signal is taken. During the time between the generation of a signal and its delivery, the signal is said to be pending.
    • A process has the option of blocking the delivery of a signal. If a signal that is blocked is generated for a process, and if the action for that signal is default action or to catch the signal, then the signal remains pending for the process until the process
      (a) unblocks the signal or
      (b) changes the action to ignore the signal.
    • The system determines what to do with a blocked signal when the signal is delivered, not when it’s generated. This allows the process to change the action for the signal before it’s delivered. sigpending function(Section 10.13) can be called by a process to determine which signals are blocked and pending.
    • What happens if a blocked signal is generated more than once before the process unblocks the signal?
      POSIX.1 allows the system to deliver the signal either once or more than once. If the system delivers the signal more than once, we say that the signals are queued. Most UNIX systems do not queue signals unless they support the real-time extensions to POSIX.1.
    • What happens if more than one signal is ready to be delivered to a process?
      POSIX.1 does not specify the order in which the signals are delivered to the process. The Rationale for POSIX.1 suggests that signals related to the current state of the process be delivered before other signals.
    • Each process has a signal mask that defines the set of signals currently blocked from delivery to that process. We can think of this mask as having one bit for each possible signal. If the bit is on for a signal, that signal is currently blocked. A process can examine and change its current signal mask by calling sigprocmask(Section 10.12).
    • POSIX.1 defines sigset_t data type to hold a signal set. The signal mask is stored in one of these signal sets(Section 10.11).

    10.9 kill and raise Functions

    #include <sys/types.h>
    #include <signal.h>
    int kill(pid_t pid, int signo);
    
    #include <signal.h>
    int raise(int signo);
    Both return: 0 if OK, -1 on error
    • kill sends a signal to a process or a group of processes.
    • raise allows a process to send a signal to itself.
      raise(signo); is equivalent to kill(getpid(), signo);
    • 4 different conditions for pid to kill. pid
      1. > 0:
        The signal is sent to the process whose process ID is pid.
      2. = 0:
        The signal is sent to all processes whose process group ID equals the process group ID of the sender and for which the sender has permission to send the signal. All processes excludes an implementation-defined set of system processes. For most UNIX systems, this set of system processes includes the kernel processes and init(pid 1).
      3. < 0:
        The signal is sent to all processes whose process group ID equals the absolute value of pid and for which the sender has permission to send the signal. The set of all processes excludes certain system processes as before.
      4. == -1:
        The signal is sent to all processes on the system for which the sender has permission to send the signal. The set of processes excludes certain system processes.
    • A process needs permission to send a signal to another process. The superuser can send a signal to any process. For other users: real/effective user ID of sender has to equal real/effective user ID of receiver. If the implementation supports _POSIX_SAVED_IDS(as POSIX.1 now requires), saved set-user-ID of receiver is checked instead of its effective user ID.
    • One special case for the permission testing: if the signal being sent is SIGCONT, a process can send it to any other process in the same session.
    • POSIX.1 defines signal number 0 as the null signal. signo = 0: the normal error checking is performed by kill, but no signal is sent. This technique is used to determine if a process still exists. If we send the process the null signal and it doesn’t exist, kill returns -1 and errno is set to ESRCH.
    • Since UNIX recycle process IDs after some time, the existence of a process with a given process ID doesn’t necessarily mean that it’s the process that you think it is. Note that the test for process existence is not atomic: by the time that kill returns the answer to the caller, the process in question might have exited, so the answer is of limited value.
    • If the call to kill causes the signal to be generated for the calling process and if the signal is not blocked, either signo or some other pending, unblocked signal is delivered to the process before kill returns. Additional conditions occur with threads(Section 12.8).

    10.10 alarm and pause Functions

    #include <unistd.h>
    unsigned int alarm(unsigned int seconds);
    Returns: 0 or number of seconds until previously set alarm
    • alarm allows us to set a timer that will expire at a specified time in the future. When the timer expires, SIGALRM signal is generated. If we ignore or don’t catch this signal, its default action is to terminate the process.
    • seconds is the number of clock seconds in the future when the signal should be generated. When that time occurs, the signal is generated by the kernel, although additional time could elapse before the process gets control to handle the signal, because of processor scheduling delays.
    • There is only one alarm clock per process. When we call alarm, if a previously registered alarm clock has not expired, the number of seconds left for that alarm clock is the return value. That previously registered alarm clock is replaced by the new value. If new value is 0, the previous alarm clock is canceled.
    • If we want to catch SIGALRM, we must install its signal handler before calling alarm. If we call alarm first and sent SIGALRM before installing the signal handler, our process will terminate.
    #include <unistd.h>
    int pause(void);
    Returns: -1 with errno set to EINTR
    • pause suspends the calling process until a signal is caught. The only time pause returns is if a signal handler is executed and that handler returns. In this case, pause returns -1 with errno set to EINTR.
    • Using alarm and pause, we can put a process to sleep for a specified amount of time.

    • This implementation has three problems.
      1. If the caller already has an alarm set, that alarm is erased by the first call to alarm. Solution: We can correct this by looking at alarm’s return value. If the number of seconds until previously set alarm is:
        -1 < the argument. We should wait only until the existing alarm expires.
        -2 > the argument. Before returning we should reset this alarm to occur at its designated time in the future.
      2. We have modified the disposition for SIGALRM. If we’re writing a function for others to call, we should save the disposition when our function is called and restore it when we’re done.
        Solution: We can correct this by saving the return value from signal and resetting the disposition before our function returns.
      3. There is a race condition between the first call to alarm and the call to pause. On a busy system, it’s possible for the alarm to go off and the signal handler to be called before we call pause. If that happens, the caller is suspended forever in the call to pause(assuming other signal isn’t caught).
        Solution: Two ways to correct problem 3. One use setjmp and longjmp(Section 7.10), shown in Figure 10.8; the other use sigprocmask and sigsuspend(Section 10.19).

    • sleep2 avoids the race condition from Figure 10.7. Even if the pause is never executed, sleep2 returns when the SIGALRM occurs.
    • Another problem with sleep2 that involves its interaction with other signals. If the SIGALRM interrupts some other signal handler, then when we call longjmp, we abort the other signal handler. Figure 10.9 shows this scenario.

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    #include <setjmp.h>
    
    static jmp_buf env_alrm;
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    static void sig_alrm(int signo)
    {
        longjmp(env_alrm, 1);
    }
    
    unsigned int sleep2(unsigned int seconds)
    {
        if(signal(SIGALRM, sig_alrm) == SIG_ERR)
        {
            return seconds;
        }
        if(setjmp(env_alrm) == 0)
        {
            if(alarm(seconds) != 0)
            {
                Exit("alarm() error");
            }
            pause();
        }
        return alarm(0);
    }
    
    static void sig_int(int signo)
    {
        printf("\nsig_int starting\n");
        volatile int sum;
        for(int num1 = 0; num1 < 30000000; ++num1)
        {
            for(int num2 = 0; num2 < 40000000; ++num2)
            {
                sum += num1 * num2;
            }
        }
        printf("sig_int finished\n");
    }
    
    int main()
    {
        unsigned int unslept;
        if(signal(SIGINT, sig_int) == SIG_ERR)
        {
            Exit("signal(SIGINT) error");
        }
        unslept = sleep2(5);
        printf("sleep2 returned: %u\n", unslept);
        exit(0);
    }
    • The loop in the SIGINT handler was written so that it executes for longer than 5 seconds(longer than the argument to sleep2). The integer k is declared as volatile to prevent an optimizing compiler from discarding the loop.
    $ ./a.out 
    ^C                  #we type the interrupt character
    sig_int starting
    sleep2 returned: 0
    • The longjmp from sleep2 aborted the other signal handler(sig_int) even though it wasn’t finished.
    • We can use alarm to put an upper time limit on operations that can block.

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    static void sig_alrm(int signo){}
    
    int main()
    {
        char line[100];
        if(signal(SIGALRM, sig_alrm) == SIG_ERR)
        {
            Exit("signal(SIGALRM) error");
        }
        alarm(10);
        if(read(STDIN_FILENO, line, 100) < 0)
        {
            Exit("read error");
        }
        alarm(0);
    
        exit(0);
    }
    • This program has two problems.
      1. A race condition between the first call to alarm and the call to read. If the kernel blocks the process between these two function calls for longer than the alarm period, the read could block forever.
      2. If system calls are automatically restarted, the read is not interrupted when the SIGALRM signal handler returns. In this case, the timeout does nothing.
    • Redo the preceding example using longjmp, we don’t worry about whether a slow system call is interrupted.

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    #include <setjmp.h>
    
    static jmp_buf env_alrm;
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    static void sig_alrm(int signo)
    {
        longjmp(env_alrm, 1);
    }
    
    int main()
    {
        char line[100];
        if(signal(SIGALRM, sig_alrm) == SIG_ERR)
        {
            Exit("signal(SIGALRM) error");
        }
        if(setjmp(env_alrm) != 0)
        {
            Exit("read timeout");
        }
        alarm(10);
        if(read(STDIN_FILENO, line, 100) < 0)
        {
            Exit("read error");
        }
        alarm(0);
    
        exit(0);
    }
    • Realize that we still have the problem of interactions with other signal handlers, as in Figure 10.8.
    • If we want to set a time limit on an I/O operation, we need to use longjmp, while recognizing its possible interaction with other signal handlers. Another option is to use the select or poll functions, described in Sections 14.4.1 and 14.4.2.

    10.11 Signal Sets

    • POSIX.1 defines the data type sigset_t to contain a signal set and the following five functions to manipulate signal sets.
    #define _GNU_SOURCE
    #include <signal.h>
    int sigemptyset(sigset_t *set);
    int sigfillset(sigset_t *set);
    int sigaddset(sigset_t *set, int signo);
    int sigdelset(sigset_t *set, int signo);
    All four return: 0 if OK, -1 on error
    
    int sigismember(const sigset_t *set, int signo);
    Returns: 1 if true, 0 if false, -1 on error
    • sigemptyset initializes the signal set pointed to by set so that all signals are excluded.
    • sigfillset initializes the signal set so that all signals are included.
    • All applications have to call sigemptyset/sigfillset once for each signal set before using it, because we cannot assume that the C initialization for external and static variables(0) corresponds to the implementation of signal sets on a given system. Once we have initialized a signal set, we can add and delete specific signals in the set.
    • sigaddset adds a single signal to an existing set.
    • sigdelset removes a single signal from a set.

    Implementation

    • If the implementation has fewer signals than bits in an integer, a signal set can be implemented using one bit per signal. For the remainder of this section, assume that an implementation has 31 signals and 32-bit integers. sigemptyset zeros the integer, sigfillset turns on all the bits in the integer. These two functions can be implemented as macros in
    #define sigemptyset(ptr)    (*(ptr) = 0)
    #define sigfillset(ptr)     (*(ptr) = ~(sigset_t)0, 0)
    • Since sigfillset must return 0, in addition to setting all the bits on in the signal set, we use comma operator, which returns the value after the comma as the value of the expression.
    • sigaddset turns on a single bit and sigdelset turns off a single bit; sigismember tests a certain bit. Since no signal is ever numbered 0, we subtract 1 from the signal number to obtain the bit to manipulate. Figure 10.12 shows implementations.

    10.12 sigprocmask Function

    #include <signal.h>
    int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
    Returns: 0 if OK, -1 on error
    • Signal mask of a process is the set of signals currently blocked from delivery to that process. A process can examine its signal mask, change its signal mask, or perform both operations in one step by calling sigprocmask.
      1. If oset != NULL: the current signal mask for the process is returned through oset.
      2. If set = NULL: signal mask of the process is not changed, and how is ignored.
      3. If set != NULL: how(Figure 10.13) indicates how the current signal mask is modified.

    • SIGKILL and SIGSTOP can’t be blocked.
    • After calling sigprocmask, if any unblocked signals are pending, at least one of these signals is delivered to the process before sigprocmask returns.
    • sigprocmask is defined only for single-threaded processes. Separate function to manipulate thread’s signal mask in a multithreaded process is in Section 12.8.

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <signal.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    void pr_mask(const char *str)
    {
        sigset_t sigset;
        int errno_save;
    
        errno_save = errno;// we can be called by signal handlers
        if(sigprocmask(0, NULL, &sigset) < 0)
        {
            Exit("sigprocmask error");
        }
        else
        {
            printf("%s", str);
            if(sigismember(&sigset, SIGINT))
                printf(" SIGINT");
            if(sigismember(&sigset, SIGQUIT))
                printf(" SIGQUIT");
            if(sigismember(&sigset, SIGUSR1))
                printf(" SIGUSR1");
            if(sigismember(&sigset, SIGALRM))
                printf(" SIGALRM");
            // remaining signals can go here
            printf("\n");
        }
        errno = errno_save;// restore errno
    }
    • Figure 10.14 shows a function that prints the names of the signals in the signal mask of the calling process. We use this function in Figure 10.20 and Figure 10.22.

    10.13 sigpending Function

    #include <signal.h>
    int sigpending(sigset_t *set);
    Returns: 0 if OK, -1 on error
    • sigpending returns the set of signals(through set) that are blocked from delivery and currently pending for the calling process.

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    static void sig_quit(int signo)
    {
        printf("Catch SIGQUIT\n");
        if(signal(SIGQUIT, SIG_DFL) == SIG_ERR)
        {
            Exit("can't reset SIGQUIT");
        }
        printf("Set SIGQUIT handler = SIG_DFL success\n");
    }
    
    int main()
    {
        sigset_t newmask, oldmask, pendmask;
        if(signal(SIGQUIT, sig_quit))
        {
            Exit("Can't catch SIGQUIT");
        }
        printf("Set SIGQUIT handler = sig_quit success\n");
    
        sigemptyset(&newmask);
        sigaddset(&newmask, SIGQUIT);
        if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
        {
            Exit("SIG_BLOCK error");
        }
        printf("SetBlock SIGQUIT success\n");
    
        printf("Begin sleep\n");
        sleep(5);
        printf("End sleep\n");
    
        if(sigpending(&pendmask) < 0)
        {
            Exit("sigpending error");
        }
        if(sigismember(&pendmask, SIGQUIT))
        {
            printf("\nSIGQUIT pending\n");
        }
        else
        {
            printf("\nNo SIGQUIT pending\n");
        }
    
        if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        {
            Exit("SIG_SETMASK error");
        }
        printf("Unblock SIGQUIT success\n");
    
        printf("Begin sleep\n");
        sleep(5);
        printf("End sleep\n");
        exit(0);
    }
    • The process blocks SIGQUIT, saving its current signal mask to restore later, and then goes to sleep for 5 seconds. Any occurrence of the quit signal during this period is blocked and won’t be delivered until the signal is unblocked. At the end of sleep, we check whether the signal is pending and unblock the signal.
    • We save old mask when we block the signal. To unblock the signal, we did a SIG_SETMASK of the old mask. Alternatively, we could SIG_UNBLOCK only the signal that we had blocked. But if we write a function that can be called by others and if we need to block a signal in our function, we can’t use SIG_UNBLOCK to unblock the signal, we have to use SIG_SETMASK and restore the signal mask to its prior value, because it’s possible that the caller had blocked this signal before calling our function.
    • If we generate the quit signal during this sleep period, the signal is now pending and unblocked, so it is delivered before sigprocmask returns(the printf in the signal handler is output before the printf that follows the call to sigprocmask).
    • The process then goes to sleep for another 5 seconds. If we generate the quit signal during this sleep period, the signal should terminate the process, since we reset the handling of the signal to its default when we caught it.
    $ ./a.out
    ^\                          #generate signal once(before 5 seconds are up)
    SIGQUIT pending         #after return from sleep
    caught SIGQUIT              #in signal handler
    SIGQUIT unblocked           #after return from sigprocmask
    ^\Quit(core dump)           #generate signal again
    $ ./a.out
    ^\^\^\^\^\^\^\^\^\^\            #generate signal 10 times(before 5 seconds are up)
    SIGQUIT pending
    caught SIGQUIT              #signal is generated only once
    SIGQUIT unblocked
    ^\Quit(core dump)           #generate signal again
    • The message Quit(core dump) is printed by the shell when it sees that its child terminated abnormally.
    • When we run the program the second time, we generate the quit signal ten times while the process is asleep, but the signal is delivered only once to the process when it’s unblocked. This demonstrates that signals are not queued on this system.

    10.14 sigaction Function

    #define _GNU_SOURCE
    #include <signal.h>
    int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);
    Returns: 0 if OK, -1 on error
    • sigaction allows us to examine or modify(or both) the action associated with a signal.
    • signo is the signal number whose action we are examining or modifying.
    • If act != NULL: we are modifying the action.
    • If oact != NULL: the system returns the previous action for the signal through oact.
    struct sigaction
    {
        void    (*sa_handler)(int); // addr of signal handler, or SIG_IGN, or SIG_DFL
        sigset_t    sa_mask;            // additional signals to block
        int     sa_flags;           // signal options, Figure 10.16
        void    (*sa_sigaction)(int, siginfo_t *, void *);  // alternate handler
    };
    • When changing the action for a signal, if sa_handler contains the address of a signal-catching function, then sa_mask specifies a set of signals that are added to the signal mask of the process before the signal-catching function is called. When the signal-catching function returns, the signal mask of the process is reset to its previous value. So, we are able to block certain signals whenever a signal handler is invoked.
    • The operating system includes the signal being delivered in the signal mask when the handler is invoked. We are guaranteed that whenever we are processing a given signal, another occurrence of the same signal is blocked until we’re finished processing the first occurrence. Section 10.8: additional occurrences of the same signal are usually not queued.
    • POSIX.1 requires that a signal handler remain installed until explicitly changed. Once we install an action for a given signal, that action remains installed until we explicitly change it by calling sigaction.
    • sa_flags of act specifies options for the handling of this signal. Figure 10.16 details the meaning of these options when set. The SUS column contains • if the flag is defined as part of POSIX.1, and XSI if it is defined as part of the XSI option.

    • sa_sigaction is an alternative signal handler used when the SA_SIGINFO flag is used with sigaction. Implementations might use the same storage for both the sa_sigaction field and the sa_handler field, so applications can use only one of these fields at a time.
    • Normally, the signal handler is called as
      void handler(int signo);
      but if the SA_SIGINFO flag is set, the signal handler is called as
      void handler(int signo, siginfo_t *info, void *context);
    • The siginfo structure contains information about why the signal was generated. All POSIX.1-compliant implementations must include at least the si_signo and si_code members. Additionally, implementations that are XSI compliant contain at least the following fields:
    struct siginfo
    {
        int         si_signo;   // signal number
        int         si_errno;   // if nonzero, errno value from errno.h
        int         si_code;        // additional info(depends on signal)
        pid_t       si_pid;     // sending process ID
        uid_t       si_uid;     // sending process real user ID
        void*       si_addr;        // address that caused the fault
        int         si_status;  // exit value or signal number
        union sigval    si_value;   // application-specific value
        // possibly other fields also
    };
    • The sigval union contains the following fields:
    int     sival_int;
    void*   sival_ptr;
    • Applications pass an integer value in si_value.sival_int or pass a pointer value in si_value.sival_ptr when delivering signals.
    • Figure 10.17 shows values of si_code for various signals, as defined by the Single UNIX Specification. Note that implementations may define additional code values.

    • If signal is SIGCHLD: si_pid, si_status, and si_uid fields will be set.
      If signal is SIGBUS, SIGILL, SIGFPE, or SIGSEGV: si_addr contains the address responsible for the fault, although the address might not be accurate.
    • si_errno field contains the error number corresponding to the condition that caused the signal to be generated, although its use is implementation defined.
    • The context argument to the signal handler is a typeless pointer that can be cast to a ucontext_t structure identifying the process context at the time of signal delivery.
    • This structure contains at least the following fields.
    ucontext_t* uc_link;            /* pointer to context resumed when this context returns */
    sigset_t        uc_sigmask;     /* signals blocked when this context is active */
    stack_t     uc_stack;       /* stack used by this context */
    mcontext_t  uc_mcontext;    /* machine-specific representation of saved context */
    • The uc_stack field describes the stack used by the current context. It contains at least the following members.
    void*   ss_sp;      /* stack base or pointer */
    size_t  ss_size;        /* stack size */
    int     ss_flags;   /* flags */
    • When an implementation supports the real-time signal extensions, signal handlers established with the SA_SIGINFO flag will result in signals being queued reliably. A separate range of reserved signal numbers is available for real-time application use. Applications can pass information along with the signal by using the sigqueue function(Section 10.20).

    Example —signal Function

    #define _GNU_SOURCE
    #include <stdlib.h>
    #include <stdio.h>
    #include <signal.h>
    
    typedef void Sigfunc(int);
    
    Sigfunc *signal(int signo, Sigfunc *func)
    {
        struct sigaction act, oact;
    
        act.sa_handler = func;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        if(signo == SIGALRM)
        {
            act.sa_flags |= SA_INTERRUPT;
        }
        else
        {
            act.sa_flags |= SA_RESTART;
        }
        if(sigaction(signo, &act, &oact) < 0)
        {
            return SIG_ERR;
        }
        return oact.sa_handler;
    }
    
    int main()
    {
        if(signal(SIGALRM, SIG_DFL) == SIG_ERR)
        {
            printf("signal error");
        }
    
        exit(0);
    }
    • We must use sigemptyset to initialize sa_mask member of the structure because we’re not guaranteed that act.sa_mask = 0 does the same thing.
    • We set the SA_RESTART flag for all signals other than SIGALRM(allow us to set a timeout for I/O operations(Figure 10.10)), so that any system call interrupted by these other signals will be automatically restarted.

    Example —signal_intr Function

    • Figure 10.19: signal that tries to prevent any interrupted system calls from being restarted.

    10.15 sigsetjmp and siglongjmp Functions

    • When a signal is caught, the signal-catching function is entered, with the current signal automatically being added to the signal mask of the process. This prevents subsequent occurrences of that signal from interrupting the signal handler. If we longjmp out of the signal handler, what happens to the signal mask for the process?
    • BSD: setjmp and longjmp save and restore the signal mask. Linux don’t do this, although it supports an option to provide BSD behavior.
    #include <setjmp.h>
    int sigsetjmp(sigjmp_buf env, int savemask);
    Returns: 0 if called directly, nonzero if returning from a call to siglongjmp
    void siglongjmp(sigjmp_buf env, int val);
    • If savemask != 0: sigsetjmp saves the current signal mask of the process in env. When siglongjmp is called, if env was saved by sigsetjmp with a nonzero savemask, then siglongjmp restores the saved signal mask.

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <signal.h>
    #include <setjmp.h>
    #include <unistd.h>
    #include <time.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    void pr_mask(const char *str)
    {
        sigset_t sigset;
        int errno_save;
    
        errno_save = errno;// we can be called by signal handlers
        if (sigprocmask(0, NULL, &sigset) < 0)
        {
            Exit("sigprocmask error");
        }
        else
        {
            printf("%s", str);
            if (sigismember(&sigset, SIGINT))
                printf(" SIGINT");
            if (sigismember(&sigset, SIGQUIT))
                printf(" SIGQUIT");
            if (sigismember(&sigset, SIGUSR1))
                printf(" SIGUSR1");
            if (sigismember(&sigset, SIGALRM))
                printf(" SIGALRM");
            // remaining signals can go here
            printf("\n");
        }
        errno = errno_save;// restore errno
    }
    
    static sigjmp_buf jmpbuf;
    static volatile sig_atomic_t canjump;
    
    static void sig_usr1(int signo)
    {
        time_t starttime;
        if(canjump == 0)
        {
            return;
        }
        pr_mask("starting sig_usr1: ");
        alarm(3);
        starttime = time(NULL);
        for(;;)
        {
            if(time(NULL) > starttime + 5)
            {
                break;
            }
        }
        pr_mask("finishing sig_usr1: ");
        canjump = 0;
        siglongjmp(jmpbuf, 1);
    }
    
    static void sig_alrm(int signo)
    {
        pr_mask("in sig_alrm: ");
    }
    
    int main()
    {
        if(signal(SIGUSR1, sig_usr1) == SIG_ERR)
        {
            Exit("signal(SIGUSR1) error");
        }
        if(signal(SIGALRM, sig_alrm) == SIG_ERR)
        {
            Exit("signal(SIGALRM) error");
        }
    
        pr_mask("starting main: ");
    
        if(sigsetjmp(jmpbuf, 1))
        {
            pr_mask("ending main: ");
            exit(0);
        }
        canjump = 1;
    
        for(;;)
        {
            pause();
        }
    
        exit(0);
    }
    • One technique that should be used whenever siglongjmp is called from a signal handler: We set the variable canjump to a nonzero value only after we’ve called sigsetjmp. This variable is examined in the signal handler, and siglongjmp is called only if the flag canjump is nonzero. This technique provides protection against the signal handler being called at some earlier or later time, when the jump buffer hasn’t been initialized by sigsetjmp. Providing this type of protection usually isn’t required with longjmp in normal C code. Since a signal can occur at any time, we need the added protection in a signal handler.
    • We use data type sig_atomic_t, which is the type of variable that can be written without being interrupted. A variable of this type should not extend across page boundaries on a system with virtual memory and can be accessed with a single machine instruction. We include the type qualifier volatile for these data types since the variable is being accessed by two different threads of control: the main function and the asynchronously executing signal handler. Figure 10.21 shows a timeline for this program.

    • We can divide Figure 10.21 into three parts: left part(main), center part(sig_usr1), and right part(sig_alrm).
    • While the process is executing in the left part, its signal mask is 0(no signals are blocked).
      While executing in the center part, its signal mask is SIGUSR1.
      While executing in the right part, its signal mask is SIGUSR1 | SIGALRM.
    $ ./a.out &                                #start process in background
    starting main:
    [1] 531                                 #the job-control shell prints its process ID
    $ kill -USR1 531                           #send the process SIGUSR1
    starting sig_usr1: SIGUSR1
    $ in sig_alrm: SIGUSR1 SIGALRM
    finishing sig_usr1: SIGUSR1
    ending main:
    #just press RETURN
    [1] + Done              ./a.out &
    • When a signal handler is invoked, the signal being caught is added to the current signal mask of the process. The original mask is restored when the signal handler returns. siglongjmp restores the signal mask that was saved by sigsetjmp.
    • If we change sigsetjmp/siglongjmp to setjmp/longjmp on Linux, the final line of output becomes ending main: SIGUSR1
      This means that the main function is executing with the SIGUSR1 signal blocked, after the call to setjmp.

    10.16 sigsuspend Function

    • What if we want to unblock a signal and then pause, waiting for the previously blocked signal to occur? Assuming that the signal is SIGINT, the incorrect way to do this is:
    sigset_t newmask, oldmask;
    
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGINT);
    
    /* block SIGINT and save current signal mask */
    if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
        err_sys("SIG_BLOCK error");
    
    /* critical region of code */
    
    /* restore signal mask, which unblocks SIGINT */
    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        err_sys("SIG_SETMASK error");
    
    /* window is open */
    
    pause(); /* wait for signal to occur */
    
    /* continue processing */
    • If the signal is sent to the process while it is blocked, the signal delivery will be deferred until the signal is unblocked. To the application, this can look as if the signal occurs between the unblocking and the pause. If this happens, or if the signal occurs between the unblocking and the pause, it is lost. Any occurrence of the signal in this window of time is lost, we might not see the signal again and the pause will block indefinitely.
    • We need a way to both restore the signal mask and put the process to sleep in a single atomic operation. This feature is provided by the sigsuspend function.
    #include <signal.h>
    int sigsuspend(const sigset_t *sigmask);
    Returns: -1 with errno set to EINTR
    • The signal mask of the process is set to the value pointed to by sigmask. Then the process is suspended until a signal is caught or until a signal occurs that terminates the process. If a signal is caught and the signal handler returns, sigsuspend returns, and the signal mask of the process is set to its value before the call to sigsuspend.
    • There is no successful return from this function. If it returns to the caller, it always returns -1 with errno set to EINTR(indicating an interrupted system call).

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <signal.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    void pr_mask(const char *str)
    {
        sigset_t sigset;
        int errno_save;
    
        errno_save = errno;// we can be called by signal handlers
        if (sigprocmask(0, NULL, &sigset) < 0)
        {
            Exit("sigprocmask error");
        }
        else
        {
            printf("%s", str);
            if (sigismember(&sigset, SIGINT))
                printf(" SIGINT");
            if (sigismember(&sigset, SIGQUIT))
                printf(" SIGQUIT");
            if (sigismember(&sigset, SIGUSR1))
                printf(" SIGUSR1");
            if (sigismember(&sigset, SIGALRM))
                printf(" SIGALRM");
            // remaining signals can go here
            printf("\n");
        }
        errno = errno_save;// restore errno
    }
    
    static void sig_int(int signo)
    {
        pr_mask("\nIn sig_int: ");
    }
    
    int main()
    {
        sigset_t newmask, oldmask, waitmask;
    
        pr_mask("main start: ");
    
        if(signal(SIGINT, sig_int) == SIG_ERR)
        {
            Exit("signal(SIGINT) error");
        }
        sigemptyset(&waitmask);
        sigaddset(&waitmask, SIGUSR1);
        sigemptyset(&newmask);
        sigaddset(&newmask, SIGINT);
    
        if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
        {
            Exit("SIG_BLOCK error");
        }
    
        pr_mask("In critical region: ");
    
        if(sigsuspend(&waitmask) != -1)
        {
            Exit("sigsuspend error");
        }
        pr_mask("After return from sigsuspend:");
    
        if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        {
            Exit("SIG_SETMASK error");
        }
    
        pr_mask("main exit: ");
        exit(0);
    }
    • Figure 10.22 shows the correct way to protect a critical region of code from a specific signal.
    $ ./a.out 
    main start: 
    In critical region: SIGINT
    ^C
    In sig_int: SIGINT SIGUSR1
    After return from sigsuspend: SIGINT
    main exit: 
    • We added SIGUSR1 to the mask installed when we called sigsuspend so that when the signal handler ran, we could tell that the mask had actually changed. We can see that when sigsuspend returns, it restores the signal mask to its value before the call.

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <errno.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    volatile sig_atomic_t quitflag;
    
    void pr_mask(const char *str)
    {
        sigset_t sigset;
        int errno_save;
    
        errno_save = errno;// we can be called by signal handlers
        if (sigprocmask(0, NULL, &sigset) < 0)
        {
            Exit("sigprocmask error");
        }
        else
        {
            printf("%s", str);
            if (sigismember(&sigset, SIGINT))
                printf(" SIGINT");
            if (sigismember(&sigset, SIGQUIT))
                printf(" SIGQUIT");
            if (sigismember(&sigset, SIGUSR1))
                printf(" SIGUSR1");
            if (sigismember(&sigset, SIGALRM))
                printf(" SIGALRM");
            // remaining signals can go here
            printf("\n");
        }
        errno = errno_save;// restore errno
    }
    
    static void sig_int(int signo)
    {
        if(signo == SIGINT)
        {
            pr_mask("\nSIGINT: interrupt: ");
        }
        else if(signo == SIGQUIT)
        {
            pr_mask("\nSIGQUIT: quitflag = 1; ");
            quitflag = 1;
        }
    }
    
    int main()
    {
        sigset_t newmask, oldmask, zeromask;
    
        if(signal(SIGINT, sig_int) == SIG_ERR)
        {
            Exit("signal(SIGINT) error");
        }
        if(signal(SIGQUIT, sig_int) == SIG_ERR)
        {
            Exit("signal(SIGQUIT) error");
        }
    
        sigemptyset(&zeromask);
        sigemptyset(&newmask);
        sigaddset(&newmask, SIGQUIT);
    
        pr_mask("main start: ");
    
        if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
        {
            Exit("SIG_BLOCK error");
        }
    
        pr_mask("After SIG_BLOCK: ");
    
        while(quitflag == 0)
        {
            pr_mask("while(quitflag == 0):");
            sigsuspend(&zeromask);
        }
        pr_mask("After while(quitflag == 0): ");
    
        if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        {
            Exit("SIG_SETMASK error");
        }
        pr_mask("After SIG_SETMASK, main exit: ");
    
        exit(0);
    }
    • Figure 10.23: use sigsuspend to wait for a signal handler to set a global variable. We catch both the interrupt signal and the quit signal, but want to wake up the main routine only when the quit signal is caught.
    $ ./a.out 
    main start: 
    After SIG_BLOCK:  SIGQUIT
    while(quitflag == 0): SIGQUIT
    ^C
    SIGINT: interrupt:  SIGINT
    while(quitflag == 0): SIGQUIT
    ^C
    SIGINT: interrupt:  SIGINT
    while(quitflag == 0): SIGQUIT
    ^C
    SIGINT: interrupt:  SIGINT
    while(quitflag == 0): SIGQUIT
    ^\
    SIGQUIT: quitflag = 1;  SIGQUIT
    After while(quitflag == 0):  SIGQUIT
    After SIG_SETMASK, main exit: 
    • Figure 10.24 shows how signals can be used to synchronize a parent and child, the five routines TELL_WAIT, TELL_PARENT, TELL_CHILD, WAIT_PARENT, and WAIT_CHILD from Section 8.9.

    • We use two user-defined signals: SIGUSR1 is sent by parent to child; SIGUSR2 is sent by child to parent.
    • The sigsuspend function is fine if we want to go to sleep while we’re waiting for a signal to occur, but what if we want to call other system functions while we’re waiting? This problem has no solution unless we use multiple threads and dedicate a separate thread to handling signals(Section 12.8).
    • Without threads, the best is to set a global variable in the signal handler when the signal occurs. For example, if we catch both SIGINT and SIGALRM and install the signal handlers using the signal_intr function, the signals will interrupt any slow system call that is blocked. The signals are most likely to occur when we’re blocked in a call to the read function waiting for input from a slow device(This is especially true for SIGALRM, since we set the alarm clock to prevent us from waiting forever for input.) The code to handle this looks similar to the following:
    if(intr_flag)       /* flag set by our SIGINT handler */
    {
        handle_intr();
    }
    if(alrm_flag)       /* flag set by our SIGALRM handler */
    {
        handle_alrm();
    }
    
    /* signals occurring in here are lost */
    
    while((n = read( ... )) < 0)
    {
        if(errno == EINTR)
        {
            if(alrm_flag)
            {
                handle_alrm();
            }
            else if(intr_flag)
            {
                handle_intr();
            }
        }
        else
        {
            /* some other error */
        }
    }
    else if(n == 0)
    {
        /* end of file */
    }
    else
    {
        /* process input */
    }
    • We test each of the global flags before calling read and again if read returns an interrupted system call error. The problem occurs if either signal is caught between the first two if statements and the subsequent call to read. Signals occurring in here are lost. The signal handlers are called, and they set the appropriate global variable, but the read never returns(unless some data is ready to be read).
    • What we would like to be able to do is the following sequence of steps, in order.
      1. Block SIGINT and SIGALRM.
      2. Test the two global variables to see whether either signal has occurred and, if so, handle the condition.
      3. Call read(or any other system function) and unblock the two signals, as an atomic operation. The sigsuspend function helps us only if step 3 is a pause operation.

    10.17 abort Function

    #include <stdlib.h>
    void abort(void);
    This function never returns
    • abort sends SIGABRT signal to the caller. Processes should not ignore this signal.
    • ISO C states that calling abort will deliver an unsuccessful termination notification to the host environment by calling raise(SIGABRT). ISO C requires that if the signal is caught and the signal handler returns, abort still doesn’t return to its caller. If this signal is caught, the only way the signal handler can’t return is if it calls exit, _exit, _Exit, longjmp, or siglongjmp. POSIX.1 specifies that abort overrides the blocking or ignoring of the signal by the process.
    • The intent to catch SIGABRT is to allow process to perform any cleanup that it wants to do before the process terminates. If the process doesn’t terminate itself from this signal handler, POSIX.1 states that, when the signal handler returns, abort terminates the process.
    • ISO C leaves it up to the implementation as to whether output streams are flushed and whether temporary files(Section 5.13) are deleted. POSIX.1 allows an implementation to call fclose on open standard I/O streams before terminating if the call to abort terminates the process.
    • For defensive programming, if we want standard I/O streams to be flushed, we specifically do it before calling abort(err_dump function in Appendix B).

    • Figure 10.25 shows an implementation of abort function as specified by POSIX.1.
    • We first see whether the default action will occur; if so, we flush all the standard I/O streams. This is not equivalent to calling fclose on all the open streams since fflush just flushes them and doesn’t close them; when the process terminates, the system closes all open files.
      If the process catches the signal and returns, we flush all the streams again, since the process could have generated more output.
    • The only condition we don’t handle is the case where the process catches the signal and calls _exit or _Exit. In this case, any unflushed standard I/O buffers in memory are discarded. We assume that caller that does this doesn’t want the buffers flushed.
    • Section 10.9: if calling kill causes the signal to be generated for the caller, and if the signal is not blocked(we guarantee in Figure 10.25), then the signal(or some other pending, unlocked signal) is delivered to the process before kill returns. We block all signals except SIGABRT, so we know that if the call to kill returns, the process caught the signal and the signal handler returned.

    10.18 system Function

    • system function in Section 8.13 did not do any signal handling. POSIX.1 requires that system ignore SIGINT and SIGQUIT and block SIGCHLD. Before showing a version that handles these signals correctly, let’s see why we need to worry about signal handling.

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include <signal.h>
    
    void Exit(char *string)
    {
        printf("%s\n", string);
        exit(1);
    }
    
    int System(const char *cmdstring)
    {
        pid_t pid;
        int status;
    
        if(cmdstring == NULL)
        {
            return 1;
        }
    
        if((pid = fork()) < 0)
        {
            status = -1;
        }
        else if(pid == 0)
        {
            execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
            _exit(127);
        }
        else
        {
            while(waitpid(pid, &status, 0) < 0)
            {
                if(errno != EINTR)
                {
                    status = -1;
                    break;
                }
            }
        }
        return status;
    }
    
    static void sig_int(int signo)
    {
        printf("Catch SIGINT\n");
    }
    
    static void sig_chld(int signo)
    {
        printf("Catch SIGCHLD\n");
    }
    
    int main()
    {
        if(signal(SIGINT, sig_int) == SIG_ERR)
        {
            Exit("signal(SIGINT) error");
        }
        if(signal(SIGCHLD, sig_chld) == SIG_ERR)
        {
            Exit("signal(SIGCHLD) error");
        }
        if(system("/bin/ed") < 0)
        {
            Exit("System() error");
        }
    
        exit(0);
    }
    • The program in Figure 10.26 uses system from Section 8.13 to invoke the ed(1) editor.(ed is an interactive program that catches the interrupt and quit signals. If we invoke ed from a shell and type the interrupt character, it catches the interrupt signal and prints a question mark. The ed program sets the disposition of quit signal so that it is ignored.) The program in Figure 10.26 catches both SIGINT and SIGCHLD. If we invoke the program, we get
    $ ./a.out
    a                           #append text to the editor’s buffer
    Here is one line of text
    .                           #period on a line by itself stops append mode
    1,$p                       #print first through last lines of buffer to see what’s there
    Here is one line of text
    w temp.foo                  #write the buffer to a file
    25                          #editor says it wrote 25 bytes
    q                           #and leave the editor
    caught SIGCHLD
    • When the editor terminates, the system sends the SIGCHLD signal to the parent(the a.out process). We catch it and return from the signal handler. But if it is catching the SIGCHLD signal, the parent should be doing so because it has created its own children, so that it knows when its children have terminated. The delivery of this signal in the parent should be blocked while the system function is executing. This is what POSIX.1 specifies. Otherwise, when the child created by system terminates, it would fool the caller of system into thinking that one of its own children terminated. The caller would then use one of the wait functions to get the termination status of the child, thereby preventing the system function from being able to obtain the child’s termination status for its return value.
    • If we run the program again, this time sending the editor an interrupt signal, we get
    $ ./a.out
    a                           #append text to the editor’s buffer
    hello, world
    .                           #period on a line by itself stops append mode
    1,$p                       #print first through last lines to see what’s there
    hello, world
    w temp.foo                  #write the buffer to a file
    13                          #editor says it wrote 13 bytes
    ^C                          #type the interrupt character
    ?                           #editor catches signal, prints question mark
    caught SIGINT               #and so does the parent process
    q                           #leave editor
    caught SIGCHLD
    • Section 9.6: Typing the interrupt character causes the interrupt signal to be sent to all the processes in the foreground process group. Figure 10.27 shows the arrangement of the processes when the editor is running.

    • SIGINT is sent to all three foreground processes, shell ignores it. As we can see from the output, both the a.out process and the editor catch the signal. But when we’re running system function, we shouldn’t have both the parent and the child catching the two terminal-generated signals: interrupt and quit. Instead, these two signals should be sent to the program that is running: the child. Since the caller of system gives up control while the program executes, waiting for it to finish, the caller of system should not receive these two terminal-generated signals. For this reason, POSIX.1 specifies that the system function should ignore these two signals while waiting for the command to complete.

    • If we link the program in Figure 10.26 with this system function, the resulting binary differs from the last(flawed) one in the following ways.
      1. No signal is sent to the calling process when we type the interrupt or quit character.
      2. When the ed command exits, SIGCHLD is not sent to the calling process. Instead, it is blocked until we unblock it in the last call to sigprocmask, after the system function retrieves the child’s termination status by calling waitpid.
    • POSIX.1 states that if wait or waitpid returns the status of a child process while SIGCHLD is pending, then SIGCHLD should not be delivered to the process unless the status of another child process is also available. Linux doesn’t do it. SIGCHLD remains pending after the system function calls waitpid; when the signal is unblocked, it is delivered to the caller. If we called wait in the sig_chld function in Figure 10.26, a Linux system would return -1 with errno set to ECHILD, since the system function already retrieved the termination status of the child.
    • Many older texts show the ignoring of the interrupt and quit signals as follows:
    if((pid = fork()) < 0)
    {
        err_sys("fork error");
    }
    else if (pid == 0)
    {
        /* child */
        execl(...);
        _exit(127);
    }
    /* parent */
    old_intr = signal(SIGINT, SIG_IGN);
    old_quit = signal(SIGQUIT, SIG_IGN);
    waitpid(pid, &status, 0)
    signal(SIGINT, old_intr);
    signal(SIGQUIT, old_quit);
    • The problem with this code is that we have no guarantee after the fork regarding whether the parent or child runs first. If the child runs first and the parent doesn’t run for some time after, an interrupt signal might be generated before the parent is able to change its disposition to be ignored. So, we change the disposition of the signals before the fork in Figure 10.28.
    • Note that we have to reset the dispositions of these two signals in the child before the call to execl. This allows execl to change their dispositions to the default, based on the caller’s dispositions(Section 8.10).

    Return Value from system

    • The return value from system is the termination status of the shell, which isn’t always the termination status of the command string.
    • Run the program in Figure 8.24 and send signals to the command that’s executing:
    $ tsys "sleep 30"                          #we press the interrupt key
    ^C normal termination, exit status = 130
    $ tsys "sleep 30"                          #we press the quit key
    ˆ\sh: 946 Quit
    normal termination, exit status = 131
    • When we terminate the sleep call with the interrupt signal, pr_exit(Figure 8.5) thinks that it terminated normally. The same thing happens when we kill the sleep call with the quit key. The Bourne shell has a poorly documented feature in which its termination status is 128 plus the signal number, when the command it was executing is terminated by a signal. We can see this with the shell interactively.
    $ sh                               #make sure we’re running the Bourne shell
    $ sh -c "sleep 30"
    ˆC                              #press the interrupt key
    $ echo $?                      #print termination status of last command
    130
    $ sh -c "sleep 30"
    ˆ\sh: 962 Quit - core dumped        #press the quit key
    $ echo $?                      #print termination status of last command
    131
    $ exit                         #leave Bourne shell
    • On the system being used, SIGINT = 2 and SIGQUIT = 3, giving us the shell’s termination statuses of 130 and 131.
    • This time we send a signal directly to the shell and see what is returned by system:

    • We can see that the return value from system reports an abnormal termination only when the shell itself terminates abnormally.
    • If we find our process executing sleep and send it a signal directly, so that the signal goes only to the individual process instead of the entire foreground process group, we will find that these shells behave like the Bourne shell and exit with a normal termination status of 128 plus the signal number.
    • When writing programs that use the system function, be sure to interpret the return value correctly. If you call fork, exec, and wait yourself, the termination status is not the same as if you call system.

    10.19 sleep, nanosleep, and clock_nanosleep Functions

    #include <unistd.h>
    unsigned int sleep(unsigned int seconds);
    Returns: 0 or number of unslept seconds
    • This function causes the calling process to be suspended until either
      1. The amount of wall clock time specified by seconds has elapsed.(return 0)
      2. A signal is caught by the process and the signal handler returns.(return number of unslept seconds)
    • As with an alarm signal, the actual return may occur at a time later than requested because of other system activity.
    • Although sleep can be implemented with alarm(Section 10.10), this isn’t required. If alarm is used, there can be interactions between the two functions. POSIX.1 standard leaves all these interactions unspecified.
      For example, if we do an alarm(10) and 3 wall clock seconds later do sleep(5), what happens?
      The sleep will return in 5 seconds(assuming that some other signal isn’t caught in the interim), but will another SIGALRM be generated 2 seconds later? These details depend on the implementation.
    • Linux implement sleep using nanosleep, which allows the implementation to be independent of signals and the alarm timer.

    • Figure 10.29 shows an implementation of POSIX.1 sleep. This function is a modification of Figure 10.7, which handles signals reliably, avoiding the race condition in the earlier implementation.
    • We don’t use any form of nonlocal branching(as in Figure 10.8 to avoid the race condition between alarm and pause), so there is no effect on other signal handlers that may be executing when the SIGALRM is handled.
    #include <time.h>
    int nanosleep(const struct timespec *reqtp, struct timespec *remtp);
    Returns: 0 if slept for requested time or -1 on error
    • nanosleep provides nanosecond-level granularity. It suspends the calling process until either the requested time has elapsed or the function is interrupted by a signal.
    • reqtp specifies the amount of time to sleep in seconds and nanoseconds. If the sleep interval is interrupted by a signal and the process doesn’t terminate, the timespec structure pointed to by remtp will be set to the amount of time left in the sleep interval. We can set this parameter to NULL if we are uninterested in the time unslept.
    • If the system doesn’t support nanosecond granularity, the requested time is rounded up. Because nanosleep doesn’t involve the generation of any signals, we can use it without worrying about interactions with other functions.
    #include <time.h>
    int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *reqtp, struct timespec *remtp);
    Returns: 0 if slept for requested time or error number on failure
    • With the introduction of multiple system clocks(Section 6.10), we can use clock_nanosleep to suspend the calling thread using a delay time relative to a particular clock.
    • clock_id specifies the clock against which the time delay is evaluated. Identifiers for clocks are listed in Figure 6.8

    • flags is used to control whether the delay is absolute or relative. flags =
      1. 0: sleep time is relative(i.e., how long we want to sleep).
      2. TIMER_ABSTIME: sleep time is absolute(i.e., we want to sleep until the clock reaches the specified time).
    • reqtp and remtp are the same as in nanosleep. When we use an absolute time, remtp is unused because it isn’t needed; we can reuse the same value for the reqtp argument for additional calls to clock_nanosleep until the clock reaches the specified absolute time value.
    • Except for error returns,
      clock_nanosleep(CLOCK_REALTIME, 0, reqtp, remtp);
      has the same effect as
      nanosleep(reqtp, remtp);
    • The problem with using a relative sleep is that some applications require precision with how long they sleep, and a relative sleep time can lead to sleeping longer than desired. For example, if an application wants to perform a task at regular intervals, it would have to get the current time, calculate the amount of time until the next time to execute the task, and then call nanosleep. Between the time that the current time is obtained and the call to nanosleep is made, processor scheduling and preemption can result in the relative sleep time extending past the desired interval. Using an absolute time improves the precision, even though a time-sharing process scheduler makes no guarantee that our task will execute immediately after our sleep time has ended.

    10.20 sigqueue Function

    • Section 10.8: Most UNIX systems don’t queue signals. With the real-time extensions to POSIX.1, some systems began adding support for queueing signals.
    • Generally a signal carries one bit of information: the signal itself. In addition to queueing signals, these extensions allow applications to pass more information along with the delivery(Section 10.14). This information is embedded in a siginfo structure. Along with system-provided information, applications can pass an integer or a pointer to a buffer containing more information to the signal handler.
    • To use queued signals we have to do the following:
      1. Specify the SA_SIGINFO flag when we install a signal handler using the sigaction function. If we don’t specify this flag, the signal will be posted, but it is left up to the implementation whether the signal is queued.
      2. Provide a signal handler in the sa_sigaction member of the sigaction structure instead of using the usual sa_handler field. Implementations might allow us to use the sa_handler field, but we won’t be able to obtain the extra information sent with the sigqueue function.
      3. Use the sigqueue function to send signals.
    #include <signal.h>
    int sigqueue(pid_t pid, int signo, const union sigval value)
    Returns: 0 if OK, -1 on error
    • sigqueue is similar to kill, except that we can only direct signals to a single process with sigqueue, and we can use the value argument to transmit either an integer or a pointer value to the signal handler.
    • Signals can’t be queued infinitely: SIGQUEUE_MAX limit from Figure 2.9 and Figure 2.11. When this limit is reached, sigqueue can fail with errno set to EAGAIN.
    • With the real-time signal enhancements, a separate set of signals was introduced for application use. These are the signal numbers between SIGRTMIN and SIGRTMAX, inclusive. Be aware that the default action for these signals is to terminate the process.

    • Figure 10.30 summarizes the way queued signals differ in behavior among the implementations covered in this text.

    10.21 Job-Control Signals

    • Of the signals in Figure 10.1, POSIX.1 considers six to be job-control signals:
      SIGCHLD Child process has stopped or terminated.
      SIGCONT Continue process, if stopped.
      SIGSTOP Stop signal(can’t be caught or ignored).
      SIGTSTP Interactive stop signal.
      SIGTTIN Read from controlling terminal by background process group member.
      SIGTTOU Write to controlling terminal by a background process group member.
    • Except for SIGCHLD, most programs don’t handle these signals: interactive shells usually do all the work required to handle them. When we type the suspend character(Control-Z), SIGTSTP is sent to all processes in the foreground process group. When we tell the shell to resume a job in the foreground or background, the shell sends all the processes in the job the SIGCONT signal. If SIGTTIN or SIGTTOU is delivered to a process, the process is stopped by default, and the job-control shell recognizes this and notifies us.
    • Exception is a process that is managing the terminal, the vi(1) editor, for example. It needs to know when the user wants to suspend it so that it can restore the terminal’s state to the way it was when vi was started. When it resumes in the foreground, the vi editor needs to set the terminal state back to the way it wants it, and it needs to redraw the terminal screen.
    • There are some interactions between the job-control signals. When any of the four stop signals(SIGTSTP, SIGSTOP, SIGTTIN, or SIGTTOU) is generated for a process, any pending SIGCONT signal for that process is discarded. When SIGCONT is generated for a process, any pending stop signals for that same process are discarded.
    • The default action for SIGCONT is to continue the process, if it is stopped; otherwise, the signal is ignored. Normally, we don’t have to do anything with this signal. When SIGCONT is generated for a process that is stopped, the process is continued, even if the signal is blocked or ignored.

    • The program in Figure 10.31 demonstrates the normal sequence of code used when a program handles job control. This program simply copies its standard input to its standard output, but comments are given in the signal handler for typical actions performed by a program that manages a screen.
    • When the program in Figure 10.31 starts, it arranges to catch the SIGTSTP signal only if the signal’s disposition is SIG_DFL. The reason is that when the program is started by a shell that doesn’t support job control(/bin/sh, for example), the signal’s disposition should be set to SIG_IGN. In fact, the shell doesn’t explicitly ignore this signal; init sets the disposition of the three job-control signals(SIGTSTP, SIGTTIN, and SIGTTOU) to SIG_IGN. This disposition is then inherited by all login shells. Only a job-control shell should reset the disposition of these three signals to SIG_DFL.
    • When we type the suspend character, the process receives the SIGTSTP signal and the signal handler is invoked. At this point, we would do any terminal-related processing: move the cursor to the lower-left corner, restore the terminal mode, and so on. We then send ourself the same signal, SIGTSTP, after resetting its disposition to its default(stop the process) and unblocking the signal. We have to unblock it since we’re currently handling that same signal, and the system blocks it automatically while it’s being caught. At this point, the system stops the process. It is continued only when it receives(usually from the job-control shell, in response to an interactive fg command) a SIGCONT signal. We don’t catch SIGCONT. Its default disposition is to continue the stopped process; when this happens, the program continues as though it returned from the kill function. When the program is continued, we reset the disposition for the SIGTSTP signal and do whatever terminal processing we want(we could redraw the screen, for example).

    10.22 Signal Names and Numbers

    • How to map between signal numbers and names? Linux provide the array
      extern char *sys_siglist[];
      The array index is the signal number, giving a pointer to the character string name of the signal.
    #include <signal.h>
    void psignal(int signo, const char *msg);
    • psignal print the character string corresponding to a signal number in a portable manner.
    • The string msg(which normally includes the name of the program) is output to the standard error, followed by a colon and a space, followed by a description of the signal, followed by a newline. If msg is NULL, then only the description is written to the standard error.
    #include <signal.h>
    void psiginfo(const siginfo_t *info, const char *msg);
    • If you have a siginfo structure from an alternative sigaction signal handler, you can print the signal information with the psiginfo function.
    • Although this function has access to more information than just the signal number, platforms vary in exactly what additional information is printed.
    • If you only need the string description of the signal and don’t necessarily want to write it to standard error(you might want to write it to a log file, for example), you can use the strsignal function.
    #include <string.h>
    char *strsignal(int signo);
    Returns: a pointer to a string describing the signal
    • Given a signal number, strsignal will return a string that describes the signal. This string can be used by applications to print error messages about signals received. Linux return a string indicating that the signal number is unrecognized if the signal number is invalid.

    10.23 Summary

    Please indicate the source: http://blog.csdn.net/gaoxiangnumber1

    Welcome to my github: https://github.com/gaoxiangnumber1

    展开全文
  • Are You Looking To Potentially EARN More Profits Every Week Simply By Watching And Copying A Live Professional Trader... With Binary Options Trading Signals, Trading Just Got Easy! If you have alread



    Are You Looking To Potentially EARN More Profits Every Week Simply By Watching And Copying A Live Professional Trader? With Binary Options Trading Signals, Trading Just Got Easy!

    If you have already tried your hand at trading binary options, you may already know how difficult it is to consistently win trades and stay profitable.

    Let me ask you a few questions...

    • Are you tired of buying systems that simply don't work or are too complicated or "custom fit" to certian markets?
    • Are you sick of backtesting and wasting money and time trying every new "holy grail indicator" that comes out?
    • Is your STRESS going through the roof as you wipe your account yet AGAIN?
    • Do you wish there was some way to turn it all around and begin the road to earning consistent profits every week?

    Listen, we we're in your shoes just a few years back...

    Stupid trading... made me want to go put my hand through a wall on one more than one occasion...

    But instead of spending the rest of the day replacing drywall, we went to work...

    ...

    Back into the trading laborary. Testing. Tweaking. Pulling out our hair. Too many stimulants. Not enough sleep.

    Trading was beating us like a boxing match gone terribly wrong, and it just wouldn't let up.

    And then I talked to my partner late one night...

    Like we always do, we were discussing what we were seeing in the markets, what was giving results and what was kicking our butts.

    ...

    He said...I replied...

    Then we both went "Holy Crap!"

    So we combined what I was doing with what he was doing...

    Then we traded and watched nervously from the edges of our keyboards for weeks...

    Then...

    It hit us right between the eyes, like a slug from a .44 magnum...

    ...

    It was clean, it was beautiful and it was working day after day.

    But could we replicate the results? Could we honestly make a living from this every week?

    ...

    Yea, it replicated, we were like a crazy alien virus taking over the broker's platform.

    Sure, there were some mishaps along the way. Sometimes you've got that crazy unexpected trade that goes against you 100 pips like a bottle rocket in the opposite direction. But often times that happens no matter what you do...

    So we pressed on, because we know this would be profitable overall now.

    We learned what trades could and couldn't take the HEAT. How to push it, where to push it and when to push it.

    And life was good. Trades started winning and winning and winning and we were consistently making good money.

    It was like a dream come true.

    ...

    However, as we continued, we had a new problem...well sort of...

    We felt the need to help others try and achieve the success we had in order to give them the chance to try and earn profits as well.

    So, in the natural progression of our endevaors, we decided to take it public. It's really a win / win solution for everyone! We share our professional trading skills with you live every trading day and you throw us a few bucks.

    Here's just some of the powerful 
    Binary Options Trading Signal benefits...

    Watch Over The Shoulder Of A Pro!

    Watch a live stream of our professional trader every day in HIGH QUALITY with full audio so you can learn as you trade!

    We Are Completely Transparent!

    What could possibly be more transparent than seeing us executing live trades every single day? Nothing!

    One Session Every Trading Day!

    Live streaming of the trading session begins at9:30 AM through 11:30 AM EST

    Watch Us Live Even From Your Phone!

    Even if you are on the go you can still follow the live stream via your compatible mobile phone live so you don't have to worry about missing out! (iPhone Users - Photon Browser)

    We Try And Win The Week!

    Our goal is to try and win the week, as you know no one can win every trade!

    There Are No PC Downloads Required!

    After you subscribe, don't fear there is nothing to download. You will be directed straight to the live stream!

    Earn Up To 85% On Every Trade!

    Using our select brokers you can earn up to 85% on your investment on every winning trade!

    Multiple Signals Sent Every Day!

    There are always multiple signals sent out every day, so if you miss one don't worry. We average 3-5 signals daily!

    Feel free to check out some recent performance records below which demonstrates the full potential of this service.


    This sounds great so far but... 
    how exactly does this work?

    Our signal service was built with simplicity in mind. With most of us being very visual human beings, what could be better than watching a live professional trader trade right in front of your very eyes?

    As you can see from the screenshot on the right (click it to enlarge it if you would like) you are able to essentially "look over the shoulder" of our professional trader and see exactly what he see's and copy him by placing the same trades he places on your own account if you feel comfortable.

    That's really all there is to it! There is nothing to download, nothing to remember except your login and password. All the hard work of technical and fundamental analysis is completely done for you!



    Real customer feedback – here's what others are saying about Binary Options Trading Signals…

    "Franco's signal service is the best signal service I participated in. The unique style and caring of Franco is a refreshing breeze in the signaling service world.

    I was able to study a lot about the different aspects of trading from a great guy that has been out there in the trenches for the last 10 years trading with real money. This service is not only about getting the money, it's about a community, learning and watching franco in real time doing his thing. Franco, thanks a lot for it."


    - Yoav - (France)


    "Finally, a trading room where you can actually trade with the moderator! Franco is an awesome trader. He shows the trades as he takes them so you can trade right along with him. No email or text alerts after the fact. He hides nothing. I'm so grateful I found this room and I can't see myself trading binary options without it. Thank you, Franco!"

    - Brenda C. - (Dallas, Texas)



    "Hi Franco, This is Joseph Ramirez (username Joebiola in the room, pronounced Joe bye-ola). 
    I have been a member of your group for about three months. 
    Two weeks ago I made my first withdrawal of profits made from your group, $17,000. This is through the holiday trading period which is spotty at best. And I can say, that I can still see lots of upside. I have had some bad days trying to figure out what works best for me. 
    So thank you. While the trading is good, really it's the ongoing learning in the room that is helping with my success. I have read, studied, etc but to have real-time dialogue with you is the most invaluable of all. 

    See you in the room! "
    - Joe Ramirez (JoeBiola)


    "I have been following your signals and I think that you are the most reliable and honest person who I met during my journey in binary options signals so far. I have learned from you very useful things which I use in my trading. I'm really happy that you're a dream come true and I'm (HAPPY) that I had the privilege to join you. You have my full support in your efforts and I believe that we (your followers) will create a wonderful and one of the best binary options signals community."

    - Samuel








    • Multiple Daily Signals – Where I can potentially make big profits from multiple daily trades!
    • Life Changing Techniques – Where I can not only see a professional trader, but learn about the markets.

    FatCow Plan

    65% Off FatCow-- Site and Store building tools plus LegenDairy Hosting Support!


    展开全文
  • all_off.Clicked.connect(&lp3, &Light::TurnOff()); all_off.Clicked.connect(&lp4, &Light::TurnOff());  参数类型 Signal和Slots也是可以带一个或多个指定类型的参数。库sigslot是建立在C++的templated...
  • Each OAM mode channel carries 10 wavelength-division multiplexing (WDM) signal channels in the C band, with each WDM channel in turn transmitting 16-GBaud quadrature phase-shift keying signal....
  • http://www.washington.edu/news/2013/06/04/wi-fi-signals-enable-gesture-recognition-throughout-entire-home/ ...Wi-Fi signals enable gesture recognition throughout entire home By Michelle Ma
  • 信号Signals--APUE第三版

    2021-11-21 21:40:20
    Signals 提供了一种处理异步事件的方式, 例如用户在中断键入ctrl + C 来终止一个程序. 我们即将描述的就是POSIX.1 标准化的reliable-signal routines . 10.2 Signal Concepts 信号概念 首先每个信号都有一个名字...
  • GPS signals (L1, L2, L5)

    千次阅读 2013-01-18 10:13:16
    GPS signals (L1, L2, L5) Global Positioning System (GPS) satellites broadcast radio signals to enable GPS receivers to determine location and synchronized time. GPS sign...
  • HardWareFirmwareDesign.pdf

    2015-03-14 14:34:29
    HardWareFirmwareDesign HP 高级硬件工程师编写
  • for example, programs that turn off echoing of terminal input should handle program error signals in order to turn echoing back on. The handler should end by specifying the default action for the ...
  • turn to help

    2016-09-29 15:19:00
    3 'A Sharp Condition for Exact Support Recovery of Sparse Signals with Orthogonal Matching Pursuit', Jinming Wen, Zhengchun Zhou, Jian Wang, Xiaohu Tang, and Qun Mo  doi:10.1109/ISIT.2016.7541722 ...
  • 探索qt的信号ref: ...If it wasn't for the particular implementation of signals that Qt has, it would be a quite wonderful libr...
  • //////////////////////////////////// 21:55 2013-5-29 Wednesday ...mit 6.003(signals & systems) the 6.003 abstraction(input -> system -> output) 22:12 2013-5-29 ZOH == Zero Order Holder ////////////
  • dhh basecamp February 4th, 2004 was an important day in the history of the recent Internet.... 翻译自: https://www.sitepoint.com/facebook-and-basecamp-turn-5-which-means-more-to-you/ dhh basecamp
  • Learn the Ins and Outs of Implementing Signals in theSolaris Operating EnvironmentAbstractSignals are a process event notification mechanism that has beenpart of the UNIX® system from the ea
  • Signals signal is software exception ! 看源码绝对是一种享受. Programmer view the source code , something like detective find the truth!  
  • Greentown raised 1.98 billion Chinese yuan ($290.2 million) in April through a trust, which in turn sold notes to Industrial & Commercial Bank of China Ltd., the country's largest bank by market ...
  • signals  into a  secret   cod e 17.giant=big 18. contempt: a  strong   feeling  of  disliking  and having no  respect  for someone or something 19.critical: bad or wrong; 20.defaced ...
  • Understanding & Measuring Video TV-RF SignalsBy Glen Kropuenske, CET, Sencore Application EngineerEditor’s Note: This is the last of a three-part article. Measuring TV-RF Signal
  • It can be used to resurrect old musical recordings, find enemy radio signals, and generate MRIs much more quickly. Here’s how it would work with a photograph. 1 Undersample A camera or other device ...
  • Qt文档----Signals and Slots

    千次阅读 2002-04-23 17:29:00
    译者注:Qt是一套跨平台的C++ GUI应用程序框架,最近非常流行。它的信号与插槽(Signals and Slots)机制与Windows的消息机制有...Signals and SlotsSignals and slots are used for communication between objects. The
  • They can also monitor road conditions by receiving radio signals sent out from orbiting satellites and greatly reduce your chances of getting stuck in traffic jams.   Text B Comprehension ...
  • Cozmo应用部分有7个项目示例。 1. 3d viewer 3d Viewer示例并可以远程遥控。 这是一个如何将3D查看器与程序配合使用的示例,3D查看器和控件将自动运行。 注意asyncio! import asyncio ... while Tr...
  • Qt&Vtk-017-EasyView

    2021-08-12 09:03:13
    // Set up action signals and slots connect(this->ui->actionOpenXMLFile, SIGNAL(triggered()), this, SLOT(slotOpenXMLFile())); connect(this->ui->actionExit, SIGNAL(triggered()), this, SLOT(slotExit()))...
  • Qt&Vtk-014-CustomLinkView

    2021-08-12 08:46:02
    // Set up action signals and slots connect(this->ui->actionOpenXMLFile, SIGNAL(triggered()), this, SLOT(slotOpenXMLFile())); connect(this->ui->actionExit, SIGNAL(triggered()), this, SLOT(slotExit()))...
  • 三、配置VDDEXT,使得VDDEXT输出使能,给Hall元器件供电 打开项目的config.icwp文件,选中“PMU”选项 2、配置VDDEXT选项,选中VDDEXT选项中的”Turn on”,开启VDDEXT输出功能。 3、配置好VDDEXT后的V(hall)输出...
  • 【QT】深入qt信号与槽实现原理

    万次阅读 2017-07-01 05:19:38
    接着,使用signals或Q_SIGNALS声明信号,如示例中的mousePressed,信号类似于成员函数,只不过其返回类型一般为void,但可以有参数,而且只有声明不需定义,使用private、protected或public slots或Q_SLOTS声明槽并...
  • print-fatal-signals= [KNL] debug: print fatal signals If enabled, warn about various signal handling related application anomalies: too many signals, too many POSIX.1 timers, fatal signals causing a ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,710
精华内容 1,484
关键字:

signalsturn