Linux-信号处理

发表于:2012-7-03 10:27

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:lanyan822    来源:51Testing软件测试网采编

#
Linux
分享:

  信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。

  信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。

  每个信号都有一个名字,以SIG打头。常见的SIGINT( 终端终止符)、SIGABRT(异常终止,abort()产生)、SIGUSR1(用户定义的信号)等。

  当信号产生,有三种方式处理该信号

  1、忽略信号,两种信号(SIGKILL,SIGSTOP不能忽略)

  2、捕捉信号,用户可以自己定义函数用于处理该信号。

  3、执行系统默认动作,一般默认动作是终止进程

  在某些情况下,我们需要捕捉信号。比如说,之前编写的echo服务器,服务端按ctrl+c产生SIGINT信号,终止服务端程序。但是某些时候,我需要在终止程序前,做一些善后工作,如释放申请的内存空间,以免造成内存泄露。所以信号捕捉是有用的。

  可以使用signal为信号指定信号处理函数,也可以使用sigaction。现在推荐使用sigaction。

#include <signal.h> //信号头文件
typedef void (*__sighandler_t) (int);
__sighandler_t signal (int __sig, __sighandler_t __handler);

  signal有两个参数,一个是信号量,另一个是函数指针。

  下面以echo服务器,来说明如何自定义信号处理函数。

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h> //信号头文件

#define SERVERIP "192.168.0.23"
#define SERVERPORT 12345
#define MAXBUFFER 256

int serverFd=-1, connfd=-1;
char *readBuf=NULL;
/*
*功能:SIGINT自定义处理函数,用于释放申请的内存空间
*/
void handInt(int signo)
{
    printf("捕捉到SIGINT信号,服务端被终止,善后处理中...\n");
    if (readBuf != NULL)
    {
        free(readBuf);
        readBuf = NULL;
    }
    close(serverFd);
    close(connfd);
    exit(-1);
}

int main(int argc, char** argv)
{
    int ret;
    readBuf=(char *)malloc(MAXBUFFER);
    socklen_t len;
    struct sockaddr_in serveraddr,clientaddr;   
    char ip[40]={0};
    serverFd=socket(AF_INET,SOCK_STREAM,0);//创建socket
    if(serverFd < 0)
    {
        printf("socket error:%s\n",strerror(errno));
        exit(-1);
    }
    bzero(&serveraddr,sizeof(serveraddr));
    serveraddr.sin_family=AF_INET;
    serveraddr.sin_port=htons(SERVERPORT);
    inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr);//将c语言字节序转换为网络字节序

    if (signal(SIGINT, handInt) == SIG_ERR)//注册信号处理函数
    {
        printf("signal error: %s", strerror(errno));
        free(readBuf);
        exit(-1);
    }
    ret=bind(serverFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));//绑定IP和端口
    if(ret!=0)
    {
        close(serverFd);
        printf("bind error:%s\n",strerror(errno));
        exit(-1);
    }
    ret=listen(serverFd,5);//监听
    if(ret!=0)
    {
       close(serverFd);
       printf("listen error:%s\n",strerror(errno));
       exit(-1);
    }
    len=sizeof(clientaddr);
    bzero(&clientaddr,sizeof(clientaddr));
    while (1)
    {
        connfd = accept(serverFd, (struct sockaddr *) &clientaddr, &len);//接受客户端的连接
        printf("%s 连接到服务器 \n",inet_ntop(AF_INET,&clientaddr.sin_addr,ip,sizeof(ip)));
        if (serverFd < 0)
        {
            printf("accept error : %s\n", strerror(errno));
            continue;
        }
        while((ret=read(connfd,readBuf,MAXBUFFER)))//读客户端发送的数据        
        {
            write(connfd,readBuf,MAXBUFFER);//写回客户端
            bzero(readBuf,MAXBUFFER);
        }
        if(ret==0)
        {
            printf("客户端关闭连接\n");        
        }else
        {
            printf("read error:%s\n",strerror(errno));
        }
        close(connfd);
    }
    free(readBuf);
    close(serverFd);
    return 0;
}

21/212>
精选软件测试好文,快来阅读吧~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号