牛骨文教育服务平台(让学习变的简单)
博文笔记

信号

创建时间:2010-10-05 投稿人: 浏览次数:726

信号

一、主要函数:signal();alarm();pause();setitimer();sigprocmask();sigaction();

二、

kill -l 列出当前支持的信号

不存在编号为0 的信号

普通信号不排队,实时信号排队( 但一般我们用不着)

 

  异种信号允许嵌套,即一个未完也可嵌入另一个;

 

  同种信号不允许嵌套,同种信号不排队,所以为了防止信号丢失,信号处理一定要快。

1 、signal

对信号的处理有三种方式:

1) 捕捉信号,signal(SIGINT,sig_handler);   void sig_handler(int s);

2) 忽略信号,signal(SIGINT,SIG_IGN);

3) 执行系统默认动作,signal(SIGINT,SIG_DFL);

2 、/*setitimer() 可以定时在微秒级,产生SIGALRM 信号*/

3 、

1)pause() 每两秒钟就被唤醒一次

 

2) 有信号传递则会被唤醒

 

3) 它会使调用它的进程阻塞

4 、三种方法收僵尸:

1 )用sigaction 的SA_NOCLDWAIT 让子进程退出时不产生僵尸

2 )当很多僵尸时,用for (i = 0; i < CHILDNUM; i++) {

 

        wait(NULL);

 

    } 这种方法来收僵尸是不好的

3 )while (waitpid(-1, NULL, WNOHANG));

5 、

1) 如果不对SIGALRM 信号作处理的话,该信号会使程序退出。

 

2)alarm() 的返回值是上一次没有完成的秒数。

6 、

1) 与信号集sigset_t 类型有关, 五个信号集处理函数:sigXXXXset,sigismember

 

2)sigpending() 返回当前已挂上但没传进去的一个信号集

 

3)sigprocmask 主要有三个参数:SIG_BLOCK,SIG_UNBLOCK,SIG_SETMASK;

 

7 、

sigaction 常用的几个参数:SA_INTERRUPT, SA_RESTART,SA_NOCLDWAIT

 

SA_INTERRUPT: 被这个信号打断的系统调用不会自动重启。

 

SA_RESTART :  被这个信号打断的系统调用会自动重启。

 

SA_NOCLDWAIT :若sigaction 的第一个参数为SIGCHLD, 则当调用进程的子进程终止时,不创建僵尸。

 

 

三、例程

1 、

/*signal.c*/

 

#include <stdio.h>

 

#include <signal.h>

 

void sig_handler(int s)

 

{

 

    if (s == SIGINT) {

 

        printf("Hello world!/n");

 

    } else if (s == SIGQUIT)

 

        printf("hello!/n");

 

}

 

int main(void)

 

{

 

    signal(SIGINT, sig_handler);

 

    signal(SIGQUIT, sig_handler);

 

    while (1) {

 

//      printf("hello world!/n");

 

        sleep(1);

 

    }

 

}

 

/*signal 信号处理函数. 如果想忽略一个信号, 如:signal(SIGINT,SIG_IGN)*/

2 、

/*setitimer.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/time.h>

#define BUFSIZE 2

void alarm_handler(int s)
{

}

int main(void)
{
    int fd, ret;
    char buf[BUFSIZE];
    struct itimerval cur;

    cur.it_value.tv_sec = 0;//给定时器装初值,it_value刚开始不能为0?
    cur.it_value.tv_usec = 1;
    cur.it_interval.tv_sec = 0;
    cur.it_interval.tv_usec = 50000;
    
    signal(SIGALRM, alarm_handler);
    setitimer(ITIMER_REAL, &cur, NULL);//相当于单片机的定时/计数器

    fd = open("/etc/services", O_RDONLY);
    if (fd == -1) {
        perror("open");
        exit(1);
    }

    while (1) {
        ret = read(fd, buf, BUFSIZE);
        if (ret == 0)
            break;
        write(1, buf, ret);
        pause();
    }

    close(fd);
    exit(0);
}
/*setitimer()可以定时在微秒级,产生SIGALRM信号*/

3 、

/*sigaction.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <signal.h>

 

#include <errno.h>

 

#include <fcntl.h>

 

#include <unistd.h>


 

void int_handler(int s)

 

{

 

}

 

int main(void)

 

{

 

    int ret;

 

    char buf[32];

 

    struct sigaction act;

 


 

    act.sa_handler = int_handler;

 

    sigemptyset(&act.sa_mask);

 

    act.sa_flags = SA_INTERRUPT;

 

//  act.sa_flags = SA_RESTART;

 

    sigaction(SIGINT, &act, NULL);

 

    sigaction(SIGQUIT, &act, NULL);

 

//  signal(SIGINT, int_handler);

 

    while (1) {

 

        ret = read(0, buf, 32);

 

        if (ret == -1) {

 

            if (errno == EINTR) {

 

                perror("read");

 

                continue;

 

            }

 

            perror("read");

 

            break;

 

        }

 

    }

 

    return 0;

 

}

 

/*sigaction 常用的几个参数:SA_INTERRUPT, SA_RESTART,SA_NOCLDWAIT

 

  SA_INTERRUPT: 被这个信号打断的系统调用不会自动重启。

 

  SA_RESTART :  被这个信号打断的系统调用会自动重启。

 

  SA_NOCLDWAIT :若sigaction 的第一个参数为SIGCHLD, 则当调用进程的子进程终止时,不创建僵尸。

 

  */

4 、

/*sigprocmask.c*//*有些时候,我们暂时不希望受到某些信号的干挠,暂且将其屏蔽*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main(void)
{
    sigset_t cur, old, pending;
    
    sigemptyset(&cur);
    sigaddset(&cur, SIGINT);
    sigaddset(&cur, SIGQUIT);
    sigaddset(&cur, SIGALRM);

    alarm(1);

    while (1) {
        sigprocmask(SIG_BLOCK, &cur, &old);
        printf("A/n");
        sleep(5);
        printf("B/n");
        sigpending(&pending);
        if (sigismember(&pending, SIGINT))
            printf("sigint is here!/n");
        if (sigismember(&pending, SIGQUIT))
            printf("sigquit is here!/n");
        if (sigismember(&pending, SIGALRM))
            printf("sigalrm is here!/n");
        sigprocmask(SIG_SETMASK, &old, NULL);//解除mask后,pending上已挂有的就会起作用
        sleep(1);
    }
    
}
/*1、与信号集sigset_t类型有关,五个信号集处理函数:sigXXXXset,sigismember
  2、sigpending()返回当前已挂上但没传进去的一个信号集
  3、sigprocmask主要有三个参数:SIG_BLOCK,SIG_UNBLOCK,SIG_SETMASK;
  */

5 、

/*alarm.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <unistd.h>

 

#include <fcntl.h>

 

#include <signal.h>

 

void sig_handler(int s)

 

{

 

    printf("alram!/n");

 

}

 

int main(void)

 

{

 

    int ret;

 

    alarm(10);

 

    sleep(5);

 

    ret = alarm(3);

 

    printf("ret=%d/n", ret);   

 

    signal(SIGALRM, sig_handler);

 

 

    while (1)

 

        sleep(1);

 

#if 0

 

    char buf[32];

 

    while (1) {

 

        printf("Input content!(It will exit! after"             " 10 second): ");

 

        fflush(stdout);

 

        read(0, buf, 32);

 

    }

 

#endif

 

}

 

/*1 、如果不对SIGALRM 信号作处理的话,该信号会使程序退出。

 

  2 、alarm() 的返回值是上一次没有完成的秒数。*/

6 、

/*divide.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

int main(void)

 

{

 

    int a = 100;

 

    int b = 0;

 

    int c = a / b;

 

    printf("sucess!/n");

 

    exit(0);

 

}

 

/* 除以0 会产生异常,程序直接退出*/

7 、

/*zombie.c*//* 三种收僵尸的方法*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <unistd.h>

 

#include <signal.h>

 

#include <sys/wait.h>

 

#include <unistd.h>

 

#include <sys/types.h>

 

#define CHILDNUM 10000

 

void destroy_zombie(int s)

 

{

 

    while (waitpid(-1, NULL, WNOHANG));

 

}

 

int main(void)

 

{

 

    int i;

 

    pid_t pid;

 

    struct sigaction act;

 

    act.sa_handler = destroy_zombie;

 

    sigemptyset(&act.sa_mask);

 

    //act.sa_flags = SA_NOCLDWAIT;

 

    act.sa_flags = SA_RESTART;

 

    sigaction(SIGCHLD, &act, NULL);

 


 

    for (i = 0; i < CHILDNUM; i++) {

 

        pid = fork();

 

        if (pid == 0) {

 

            exit(0);

 

        }

 

    }

 

#if 0  

 

    for (i = 0; i < CHILDNUM; i++) {

 

        wait(NULL);

 

    }

 

#endif

 

    while (1) {

 

//      printf("Hello!/n");

 

        sleep(1);

 

    }

 

}

 

/*1 、用sigaction 的SA_NOCLDWAIT 让子进程退出时不产生僵尸*/

 

/*2 、当很多僵尸时,用for (i = 0; i < CHILDNUM; i++) {

 

        wait(NULL);

 

    } 这种方法来收僵尸是不好的*/

 

/*3 、while (waitpid(-1, NULL, WNOHANG));*/

 

8 、

/*pause.c*/

 

#include <stdio.h>

 

#include <signal.h>

 

void sig_handler(int s)

 

{

 

    alarm(2);

 

}

 

int main(void)

 

{

 

    signal(SIGALRM, sig_handler);

 

    alarm(2);

 

    while (1) {

 

        printf("I am sleeping..../n");

 

        pause();

 

    }

 

}

 

/*1 、pause() 每两秒钟就被唤醒一次

 

  2 、有信号传递则会被唤醒

 

  3 、它会使调用它的进程阻塞

 

*/

9 、

/*sigifque.c*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <signal.h>

 

static int cnt = 0;

 

void sig_handler(int s)

 

{

 

    printf("hello:%d/n", cnt++);

 

    sleep(5);

 

    return;

 

}

 

int main(void)

 

{

 

    signal(SIGINT, sig_handler);

 

    while (1)

 

        sleep(1);

 

    return 0;

 

}

 

/* 在sleep(5) 内,若来多个SIGINT ,则会丢失,因为普通信号是不排队的*/

10 、

/*order.c*//* 信号是否排队*/

 

#include <stdio.h>

 

#include <signal.h>

 

static int cnt = 0;

 

void sig_handler(int s)

 

{

 

//  if (s == SIGINT) {

 

        printf("Hello world!:%d/n", cnt++);

 

        sleep(5);

 

//  } else if (s == SIGQUIT)

 

//      printf("hello!:%d/n", cnt++);

 

}

 

int main(void)

 

{

 

    signal(SIGINT, sig_handler);

 

    signal(SIGQUIT, sig_handler);

 

    while (1) {

 

        sleep(1);

 

    }

 

}

 

/*1 、sig_handler 的参数s 所传入的值对应所发生的信号

 

  2 、这个程序说明:

 

  异种信号允许嵌套,那一个未完也可嵌入另一个;

 

  同种信号不允许嵌套,同种信号不排队,所以为了防止信号丢失,信号处理一定要快。

 

  */

11 、

#include <stdio.h>

 

#include <stdlib.h>

 

#include <signal.h>

 

#include <string.h>


 

void alram_handler(int s)

 

{

 

    printf("Do homework!!!!/n");

 

}

 

int main(void)

 

{

 

    char buf[32];

 

    memset(buf, 0, 32);

 

    struct sigaction act;

 

    act.sa_handler = alram_handler;

 

    sigemptyset(&act.sa_mask);

 

    act.sa_flags = SA_RESTART;

 

    alarm(5);

 

    sigaction(SIGALRM, &act, NULL);

 

 

    int ret = read(0, buf, 31);

 

    printf("read:%s/n", buf);

 

    exit(0);

 

}

 

/* SA_RESTART 使read 的不阻塞*/

12 、

/* 模拟流量控制*/

 

#include <stdio.h>

 

#include <stdlib.h>

 

#include <signal.h>

 

#include <fcntl.h>

 

#include <unistd.h>

 

#define BUFSIZE 15

 

static int count = 0;

 

void alarm_handler(int s)

 

{

 

    count += BUFSIZE;// 每三秒只能读15 个?

 

    alarm(3);

 

//  printf("need read amount:%d/n", count);

 

}

 

int main(void)

 

{

 

    int ret, fd;

 

    char buf[BUFSIZE];

 

    fd = open("/etc/services", O_RDONLY);

 

    if (fd == -1) {

 

        perror("open");

 

        exit(1);

 

    }

 

    alarm(3);

 

    signal(SIGALRM, alarm_handler);

 

    while (1) {

 

        if (count == 0)

 

            pause();// 刚开始等待闹钟把它唤醒, 醒了之后count=15 了

 

        ret = read(0, buf, BUFSIZE);

 

        if (ret == 0)

 

            break;

 

        write(1, buf, ret);

 

        count -= ret;

 

    }

 

 

    close(fd);

 

    exit(0);

 

}

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。