Chinaunix首页 | 论坛 | 博客
  • 博客访问: 300344
  • 博文数量: 35
  • 博客积分: 836
  • 博客等级: 准尉
  • 技术积分: 678
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-07 20:11
文章分类

全部博文(35)

文章存档

2013年(1)

2012年(24)

2011年(10)

分类: LINUX

2012-03-06 01:08:37

在很多的系统调用中,在错误返回时都会有一个EINTR的值。这个返回值的描述时在系统调用执行时,遇到发生信号。
今天写了个小程序来完成这个事,程序如下:
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <signal.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/ip.h>
  7. #include <netinet/in.h>
  8. void alarm_handler(int signo)
  9. {
  10.     printf ("here is the alarm\n");
  11.     alarm(1);
  12.     return ;
  13. }

  14. int main(int argc, char *argv[])
  15. {
  16.     int sockfd = -1;
  17.     int ret = 0;
  18.     struct sockaddr_in server_addr;
  19.     struct sockaddr_in client_addr;
  20.     socklen_t addr_len = 0;
  21.     struct sigaction sa;
  22.     
  23.     sa.sa_handler = alarm_handler;
  24.     sa.sa_flags = 0;
  25.     sigaction(SIGALRM, &sa, NULL);
  26.     alarm(1);
  27.     sockfd = socket(AF_INET, SOCK_STREAM, 0);
  28.     if (sockfd < 0)
  29.     {
  30.         perror("socket fail:");
  31.         goto out;
  32.     }
  33.     server_addr.sin_family = AF_INET;
  34.     server_addr.sin_addr.s_addr = 0;
  35.     server_addr.sin_port = 0x1234;
  36.     ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
  37.     if (ret < 0)
  38.     {
  39.         perror("bind fail:");
  40.         goto out;
  41.     }
  42.     ret = listen(sockfd, 100);
  43.     if (ret < 0)
  44.     {
  45.         perror("listen fail:");
  46.         goto out;
  47.     }
  48.     
  49.     ret = accept(sockfd, (struct sockaddr *)&client_addr, &addr_len);
  50.     if (ret < 0)
  51.     {
  52.         perror("accept fail:");
  53.         goto out;
  54.     }
  55. out:
  56.     if (sockfd >= 0)
  57.     {
  58.         close(sockfd);
  59.         sockfd = -1;
  60.     }
  61.     return 0;
  62. }
编译之后执行:
  1. here is the alarm
  2. accept fail:: Interrupted system call
约1秒中之后出现上述输出。终于构造了一个返回EINTR的调用。对于这个程序有几点说明:
  1. 需要使用sigaction而不是signal注册信号处理函数的原因是因为,signal默认的flag包含了SA_RESTART,这样造成了,accept中断后不会返回而是在signal处理函数之后继续执行。
  2. 使用alarm来定时产生一个中断
这个小程序也解决了自己的一个疑惑,之前使用signal时总是不成功,原因就是SA_RESTART。

阅读(2582) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~