码迷,mamicode.com
首页 > 其他好文 > 详细

信号之signal函数的使用

时间:2015-07-19 01:20:03      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

typedef  void(*sighandler_t)(int)    =====》  xxx   就是  void xxx(int y)  的函数指针 入口地址 

sighandler_t signal(int signum,sighandler_t handler)  =====》void (*signal(int signum , (void *))(int)))(int)

handler就是函数的入口地址

/*

#include<signal.h>

作用:注册信号的行为

参数1:信号类型

参数2:信号行为:SIG_IGN(忽略这个信号) 或者SIG_DFL(默认) ,或者执行行为handler

说白点就是:当参数1 :signum来了,我就执行参数2 :执行这个行为handler

返回值:信号之前的行为

*/

eg:信号的行为是  func

sighandler_t signal(int signum,sighandler_t handler)  那么信号行为= void(*signal(int signum , void (*func)(int)))(int);//红色代表信号类型 粉色信号的行为,蓝色代表返回值是信号之前的行为。

 

因为C语言名空间管理不善,要用sighandler_t 必须要先typedef  void(*sighandler_t)(int),如果其他的头文件也用了sighandler_t,那么函数就冲突了 ,所以要用void(*signal(int signum , void (*func)(int)))(int);

signal()使用代码:

ps: ctrl+c == SIGINT 信号:终止一个进程

一:下面函数正常情况下会1s打印一个*,如果输入ctrl+c 那么程序终止。

//此函数用于测试ctrl+c  用于终止一个进程

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

int main()
{

    int i ;
    for(i = 0 ; i < 10 ; i++)//1s打印一个星号
    {
        write(1,"*",1);
        sleep(1);

    }
    exit(0);
}

 

二:下面函数正常情况下会1s打印一个“*”,如果输入ctrl+c 那么程序忽略SIGINT信号,继续打印“*”

//此函数使用ctrl+c 函数忽略这个信号,继续打印"*"

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

int main()
{

    int i ;
    signal(SIGINT,SIG_IGN);
    for(i = 0 ; i < 10 ; i++)//1s打印一个星号
    {
        write(1,"*",1);
        sleep(1);

    }
    exit(0);
}


三:将信号的行为设置为打印一个“!”替换默认行为终止一个进程

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

static void sig_handler(int s)
{
    write(1,"!",1);
}

int main()
{

    int i ;
    /*在程序未结束的情况下,信号来了才执行*/
    signal(SIGINT,sig_handler);//函数的入口地址:sig_handler
    for(i = 0 ; i < 10 ; i++)//1s打印一个星号
    {
        write(1,"*",1);
        sleep(1);
    }
    exit(0);
}

程序三问题:如果在程序执行的过程中,不断的使用ctrl+c, 会发现“*”还没有输出10次,程序就终止了:那么问题来了????什么问题呢?非常重要的知识点:信号会打断阻塞的系统调用

欢迎登场:信号会打断阻塞的系统调用

1.man 2 open      or      man 2 read   and so on

   //open  read 是系统调用的,对吧?

2.查看函数手册return value  ---->EINTR :这么说的: 当你打开一个比较慢的设备的时候,那么这个可能会被一个信号打断;

3.解决方法:当使用系统调用出错时,要判断是不是EINTR, 是:可以继续咯 ;不是: sorry,是真的错了,你就承认吧

四:实现文件copy  里面使用了系统调用函数 open so 。。。。。是不是应该加上EINTR信号的判断,以避免程序枉死! 

/*利用系统调用实现文件拷贝*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define BUFSIZE        1024    

int main(int argc,char **argv)
{
    int sfd,dfd;//原文件的fd ,目标文件的fd
    char buf[BUFSIZE];//存放copy的数据最大1024个字节
    int pos,len,ret;//位置,长度,返回值

    if(argc < 3)
    {
        fprintf(stderr,"Usage...\n");
        exit(1);
    }

    do
    {
        sfd = open(argv[1],O_RDONLY);
        if(sfd < 0)
        {
            if(errno != EINTR)//如果是假错(信号会打断阻塞的系统调用错误为EINTR)
            {
                perror("open()");
                exit(1);
            }
        }
    }while(sfd < 0);    

    do
    {
        dfd = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600);
        if(dfd < 0)
        {
            if(errno != EINTR)//如果是假错(信号会打断阻塞的系统调用错误为EINTR)
            {
                close(sfd);
                perror("open()");
                exit(1);
            }
        }
    }while(dfd < 0);

    while(1)
    {
        len = read(sfd,buf,BUFSIZE);
        if(len < 0)
        {
            if(errno == EINTR)
                continue;
            perror("read()");
            break;
        }
        if(len == 0)
            break;

        // len > 0

        pos = 0;

        while(len > 0)
        {
            ret = write(dfd,buf+pos,len);
            if(ret < 0)
            {
                if(errno == EINTR)
                    continue;
                perror("write()");
                exit(1);
            }
            pos += ret;
            len -= ret;
        }
    }

    close(dfd);
    close(sfd);

    exit(0);
}

 

标准信号肯定会丢失,实时信号不会丢失哈哈

号的不可靠:在程序三:signal函数只是规定了SIG_INT信号来  signal只是定义了执行行为,内核负责调用以及布置执行现场,但是如果信号在处理行为的同时来了一个相同的信号,那么这两次的执行现场可能不是在同一个位置,第一次的行为会被第二次的行为冲刷掉,说起来挺可悲的!

信号之signal函数的使用

标签:

原文地址:http://www.cnblogs.com/muzihuan/p/4657876.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!