Linux-信号处理

上一篇 / 下一篇  2012-07-04 11:36:55 / 个人分类:Linux

51Testing软件测试网"p6DB]8B;}i

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

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

c%]7I'p5` vy(|w{3D051Testing软件测试网(F(Cm9?`2?f#k

  每个信号都有一个名字,以SIG打头。常见的SIGINT( 终端终止符)、SIGABRT(异常终止,abort()产生)、SIGUSR1(用户定义的信号)等。51Testing软件测试网TDoWm!{]r|

51Testing软件测试网&\+~NAfH

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

7vh ucJi%g[f0

/u.x6N0zB4~0  1、忽略信号,两种信号(SIGKILL,SIGSTOP不能忽略)

Cv Tig051Testing软件测试网FV.u7JQ\

  2、捕捉信号,用户可以自己定义函数用于处理该信号。51Testing软件测试网+l8v"K4s5{#}Rg

P"PJ1{(e+z T0  3、执行系统默认动作,一般默认动作是终止进程51Testing软件测试网;kU@W7t sEJ8H

51Testing软件测试网#Xb,_4^]%k

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

BA Td!z;I(ZG#J0

P.w4YR \*u&d0  可以使用signal为信号指定信号处理函数,也可以使用sigaction。现在推荐使用sigaction。51Testing软件测试网h%A Fzn { p5{

#include <signal.h> //信号头文件
fx[0[n6x }"SY)P9B0typedef void (*__sighandler_t) (int);
!s*Q|#u7Wq V0__sighandler_t signal (int __sig, __sighandler_t __handler);
51Testing软件测试网?L x,~+IAN

  signal有两个参数,一个是信号量,另一个是函数指针。51Testing软件测试网jfdpV(L Z?

:yx:@+sc!le&Q\-x!|0  下面以echo服务器,来说明如何自定义信号处理函数。51Testing软件测试网 Z"v]1t&apf-C

51Testing软件测试网[O;k@"X%AsZm

#include <stdio.h>51Testing软件测试网9^O$sF m"\q
#include <stdlib.h>
#uz5dwW${0Vx0#include <sys/socket.h>
2\Gu`uDa t0#include <string.h>51Testing软件测试网 v;T0V.Kq"eYo
#include <errno.h>
K#ieI9eT/U qc0#include <netinet/in.h>51Testing软件测试网S%RP^M1\
#include <arpa/inet.h>51Testing软件测试网p{:Y]x
#include <signal.h> //信号头文件

B{yw y7h0

K4OF*`B#}-P0#define SERVERIP "192.168.0.23"
6{3B En.f9G0#define SERVERPORT 1234551Testing软件测试网)@{&QKp D
#define MAXBUFFER 256
51Testing软件测试网k$V,|&a6QP8`(H

51Testing软件测试网Mw.ZQU8t6S:W!?

int serverFd=-1, connfd=-1;51Testing软件测试网k5K@9qP
char *readBuf=NULL;51Testing软件测试网i#E d C+M T
/*
e1f&G1HF0*功能:SIGINT自定义处理函数,用于释放申请的内存空间
YL/{ f"fU0*/
+sL@n$`7]$K0void handInt(int signo)
/Be(s kSI1t0{51Testing软件测试网4t?1l3t%x#AM#}!i-R
    printf("捕捉到SIGINT信号,服务端被终止,善后处理中...\n");51Testing软件测试网c~ {,E uP+H)S5W|
    if (readBuf != NULL)51Testing软件测试网1f-UL(U,CyI
    {
6R%gS*X%G"Hfl+X`0        free(readBuf);
7e,Q)T4Vxz0        readBuf = NULL;51Testing软件测试网,b:J"~Wpt
    }51Testing软件测试网q6r9x%E@OL w3U!?1e1T
    close(serverFd);51Testing软件测试网td(v%t)m6g"_c_n
    close(connfd);
&| w FPv8{ M-h:Q0    exit(-1);
Yvnc(LZ/E0}
51Testing软件测试网(TKSg p

51Testing软件测试网 g+c+@H W!\

int main(int argc, char** argv)51Testing软件测试网,q0h,_x(X#@C#{
{
\(BOb WI'}+y0    int ret;
op)fjJT:j'v0    readBuf=(char *)malloc(MAXBUFFER);51Testing软件测试网m9A W:pGm:C
    socklen_t len;
y&ncH.VfIk:^ x0    struct sockaddr_in serveraddr,clientaddr;   51Testing软件测试网%}tKr!m ^;oe
    char ip[40]={0};51Testing软件测试网*W \w i/pP:C
    serverFd=socket(AF_INET,SOCK_STREAM,0);//创建socket51Testing软件测试网9g-ZM+ug.p(?
    if(serverFd < 0)51Testing软件测试网/NK1g i5_@G8t wW
    {
:|m"h v@ewe0        printf("socket error:%s\n",strerror(errno));
zM-ISw0        exit(-1);51Testing软件测试网+n$`U7a0d/E#]-m1U
    }
H(eCC9X,]_0    bzero(&serveraddr,sizeof(serveraddr));51Testing软件测试网$H\/u"wM@
    serveraddr.sin_family=AF_INET;51Testing软件测试网5wfCc_)tP]
    serveraddr.sin_port=htons(SERVERPORT);
3Thg*B4k Y#U0    inet_pton(AF_INET,SERVERIP,&serveraddr.sin_addr);//将c语言字节序转换为网络字节序

&Fo*O[ yAE051Testing软件测试网dj4Ig'K7z

    if (signal(SIGINT, handInt) == SIG_ERR)//注册信号处理函数
|x i9t.G0j g0    {
&|3Ol.^Hu8G u az Z0        printf("signal error: %s", strerror(errno));
y1vz%j3Oe0        free(readBuf);51Testing软件测试网9[r9exJrs7HJ'_
        exit(-1);51Testing软件测试网 ?Q{zLY
    }51Testing软件测试网FW5K0AJ5_4O4o8F
    ret=bind(serverFd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));//绑定IP和端口51Testing软件测试网'lk!uXX*r
    if(ret!=0)51Testing软件测试网-D@'[.co$L9n} u-s
    {
"f3ab D?I0VB?Q0        close(serverFd);
hAe9W^h9X+`iZ0        printf("bind error:%s\n",strerror(errno));51Testing软件测试网(Wm t,}|:YT9gQ
        exit(-1);
+c*@}KjLm;@0    }51Testing软件测试网,\ k-z7qQ@9Pnt
    ret=listen(serverFd,5);//监听
&o3n-lsi L0L3p0    if(ret!=0)
?(zB ylB!c0    {
0Of2Nh,SL `\*N0       close(serverFd);
rI%ogH7XYn0       printf("listen error:%s\n",strerror(errno));
d!CBmq1S0       exit(-1);51Testing软件测试网mJ EZUkd\\O
    }51Testing软件测试网I2d.g9e!b6kIV {R
    len=sizeof(clientaddr);51Testing软件测试网:N2m;H/]9JC8@ F
    bzero(&clientaddr,sizeof(clientaddr));
8g,V{?"yrZ X0    while (1)51Testing软件测试网 hvVQHaG2L6R
    {
9u:TaIT0        connfd = accept(serverFd, (struct sockaddr *) &clientaddr, &len);//接受客户端的连接51Testing软件测试网%i,]P9n/r.c-})s
        printf("%s 连接到服务器 \n",inet_ntop(AF_INET,&clientaddr.sin_addr,ip,sizeof(ip)));
$g#W @-_1~ jC{$v0        if (serverFd < 0)51Testing软件测试网:I4ad v]%H;Qe(G
        {51Testing软件测试网 AKU:n sj
            printf("accept error : %s\n", strerror(errno));
d1dm&\$\0            continue;51Testing软件测试网-P X bjdr3rg
        }
ZSg-xOj:a:_0        while((ret=read(connfd,readBuf,MAXBUFFER)))//读客户端发送的数据        
7LSd'Bm0        {
P;K-s8t J0            write(connfd,readBuf,MAXBUFFER);//写回客户端51Testing软件测试网-cKP9a"zo9g!S1IR
            bzero(readBuf,MAXBUFFER);51Testing软件测试网7[8e!y-Z9fU#|
        }51Testing软件测试网~ {x'IU N*IoO`
        if(ret==0)51Testing软件测试网~ t%Ovq!Q
        {
t/F` `z-k5Y*R ~@ PJ0            printf("客户端关闭连接\n");        
*V*Sd D` H0Q I0        }else
D*_7PTWq0        {51Testing软件测试网 Tw1DG_ C7[ y!Jv
            printf("read error:%s\n",strerror(errno));51Testing软件测试网5^K'|c"M$z;O Q!MY
        }
ab7|&N Y d7~0        close(connfd);51Testing软件测试网1Z8G?c#L*Ld&L,E,_
    }51Testing软件测试网7Z_F}U0d`
    free(readBuf);
.Sey4[*TH\$O V}0    close(serverFd);51Testing软件测试网xW6S4a f{MIK
    return 0;51Testing软件测试网l Dfnl ^@(K
}
51Testing软件测试网Tz Hyn:j] \'V G(LMZ

_:Y8|M2rg&zv0  当没有捕捉SIGINT信号时,采用默认处理方式,终止程序。但是程序中用alloc分配了内存,程序终止前并没有释放。用valgrind 检测会出现内存泄露

_b [-]o C&p0

8l)K X hP&X$wN&\0

  如图所示,分配了一个内存空间,释放了0个内存空间。51Testing软件测试网(h @ Mt5a e

  但为SIGINT加上信号处理函数,在终止前,释放掉内存空间,就不会出现内存泄露了。效果如下所示:

ffk(PoL4cY$x$y0

:u2p p0XX7d ][z"kd0

TAG:

 

评分:0

我来说两句

Open Toolbar