信号的基本操作

     kill 函数

#include <sys/types.h>
#include <signal.h>

/*
 * 功能:
 *  给指定进程发送信号
 * 参数:
 *   pid:
 *     pid > 0:
 *       将信号传送给进程 ID 为 pid 的进程
 *     pid = 0:
 *       将信号传送给当前进程所在进程组中的所有进程
 *     pid = -1:
 *       将信号传送给系统内所有的进程
 *     pid < -1:
 *       将信号传给指定进程组的所有进程。 这个进程组号等于 pid 的绝对值
 *   signum:信号的编号
 * return:
 *  成功:0
 *  失败:-1
 * 
 */
int kill(pid_t pid, int signum)

 父进程给子进程发送信号

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
    pid_t pid;
    pid = fork();

    if(pid < 0)
    {
        perror("fork");
    }

    if(0 == pid)
    {
        int i = 0;
        for(i = 0; i < 5;i++)
        {
            printf("in son process\n");
            sleep(1);
        }
    }
    else
    {
        printf("in father process\n");
        sleep(2);
        printf("kill sub process now\n");
        kill(pid, SIGINT);
    }

    return 0;
}

       打印:

  

    alarm 函数

#include <unistd.h>

/*
 *功能:
 *  在 seconds 秒后,向调用进程发送一个 SIGALRM 信号
 *  SIGALRM 信号的默认动作:终止调用 alarm 函数的进程
 * return:
 *   若以前没有设置过定时器,或设置的定时器已超时,返回 0
 *   否则返回定时器剩余的秒数,并重新设定定时器
 */
unsigned int alarm(unsigned int seconds)

 例子:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int seconds = 0;

    seconds = alarm(5);    
    printf("seconds = %d\n",seconds);

    sleep(2);

    seconds = alarm(5);
    printf("seconds = %d\n",seconds);

    while(1);

    return 0;
}

打印:

 

    raise 函数

#include <signal.h>

/*
 * 功能:
 *  给调用进程本身送一个信号
 * 参数:
 *   signum: 信号的编号
 * return:
 *   成功: 0
 *   失败: -1
 */
int raise(int signum);

   例子:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    printf("in raise function\n");

    sleep(2);
    raise(SIGALRM);

    sleep(10);

    return 0;
}

打印:

 

    abort 函数

#include <stdlib.h>

/*
 * 功能:
 *  向进程发送一个 SIGABRT 信号, 默认情况下进程会退出
 * 注意:
 *  即使 SIGABRT 信号被加入阻塞集,一旦进程调用了 abort 函数,进程也还是会被终止,且在终止前会刷新缓冲区,关文件描述符
 */
void abord(void);

   pause 函数

#include <unistd.h>

/*
 * 功能:
 *   将调用进程挂起直至捕捉到信号为止
 *   这个函数通常用于判断信号是否已到
 * return:
 *   直到捕获到信号,pause 函数才返回-1,且 errno 被设置成 EINTR
 */
int pause(void)
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("in pause function\n");

    pause();

    return 0;
}

打印:

 

    进程接收到信号后的处理方式

          执行系统默认动作
         忽略此信号
         执行自定义信号处理函数
              程序中可用函数 signal()改变信号的处理方式

#include <signal.h>

/*
 * 功能:
 *  注册信号处理函数(不可用于 SIGKILL、SIGSTOP 信号),即确定收到信号后处理函数的入口地址
 * 参数:
 *   signum:信号编号
 *   handler:
 *      忽略该信号: SIG_IGN
 *      执行系统默认动作: SIG_DFL
 *      自定义信号处理函数: 信号处理函数名
 * return:
 *    成功:返回函数地址,该地址为此信号上一次注册的信号处理函数的地址
 *    失败:返回 SIG_ERR
 */
typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

注册信号处理函数
 

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void signal_handler(int signo);

int main()
{
    printf("wait for SIGINT OR SIGQUIT\n");

    signal(SIGINT, signal_handler);
    signal(SIGQUIT, signal_handler);

    pause();
    pause();

    return 0;
}
void signal_handler(int signo)
{
    if(signo == SIGINT)
    {
        printf("recv SIGINT\n");
    }

    if(signo == SIGQUIT)
    {
        printf("recv SIGQUIT\n");
    }
}

打印:

   操作:ctrl+\    ctrl+c   ctrl + z

验证 signal 函数的返回值
 

#include <stdio.h>
#include <signal.h>
#inlcude <unistd.h>

typedef void (*sighandler_t)(int);

void fun1(int signo);
void fun2(int signo);

int main(int argc, char *argv[])
{
    sighandler_t previous = NULL;

    previous = signal(SIGINT, fun1);
    if(previous == NULL)
    {
        printf("return fun addr is NULL\n");
    }

    previous = signal(SIGINT, fun2);
    if(previous == fun1)
    {
        printf("return fun addr is fun1\n");
    }

    previous = signal(SIGQUIT,fun1);
    if(previous == NULL)
    {
        printf("return fun addr is NULL\n");
    }
    return 0;
}

void fun1(int signo)
{
    printf("in fun1\n");
}

void fun2(int signo)
{
    printf("in fun2\n");
}

       打印: