Linux-信号处理
Linux-信号处理
信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。
每个信号都有一个名字,以SIG打头。常见的SIGINT( 终端终止符)、SIGABRT(异常终止,abort()产生)、SIGUSR1(用户定义的信号)等。
当信号产生,有三种方式处理该信号
- 忽略信号,两种信号(SIGKILL,SIGSTOP不能忽略)
- 捕捉信号,用户可以自己定义函数用于处理该信号。
- 执行系统默认动作,一般默认动作是终止进程
可以使用signal为信号指定信号处理函数,也可以使用sigaction。现在推荐使用sigaction。
- #include <signal.h> //信号头文件
- typedef void (*__sighandler_t) (int);
- __sighandler_t signal (int __sig, __sighandler_t __handler);
下面以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;
- }
如图所示,分配了一个内存空间,释放了0个内存空间。
但为SIGINT加上信号处理函数,在终止前,释放掉内存空间,就不会出现内存泄露了。效果如下所示:
评论暂时关闭