Chinaunix首页 | 论坛 | 博客
  • 博客访问: 287921
  • 博文数量: 77
  • 博客积分: 1422
  • 博客等级: 上尉
  • 技术积分: 932
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-21 12:39
文章分类
文章存档

2011年(1)

2009年(3)

2008年(73)

我的朋友

分类:

2008-04-15 23:20:57

1.SIGALRM信号如果不处理,会使进程exit
2.在某些系统中,SIGALRM信号会默认中断系统调用(inturrupt),当然也有的系统,默认情况下是使系统调用被中断后自动重新开始(restart automatically)
3.基于以上两点,在设计程序时,如果用到alrm()函数,应该对其设置信号处理函数,并对系统的signal函数进行重新定义,请看traceroute程序部分代码
 

Sigfunc *
signal(int signo, Sigfunc *func)
{
    struct sigaction    act, oact;

    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (signo == SIGALRM) {
#ifdef    SA_INTERRUPT
        act.sa_flags |= SA_INTERRUPT;    /* SunOS 4.x */
#endif
    } else {
#ifdef    SA_RESTART
        act.sa_flags |= SA_RESTART;        /* SVR4, 44BSD */
#endif
    }
    if (sigaction(signo, &act, &oact) < 0)
        return(SIG_ERR);
    return(oact.sa_handler);
}

 

 

void
sig_alrm(int signo)
{
    printf("sig_alrm()\n");
    gotalarm = 1;    /* set flag to note that alarm occurred */
    return;            /* and interrupt the recvfrom() */
}

 

 

int
recv_v4(int seq, struct timeval *tv)
{
    int                hlen1, hlen2, icmplen, ret;
    socklen_t        len;
    ssize_t            n;
    struct ip        *ip, *hip;
    struct icmp        *icmp;
    struct udphdr    *udp;

    gotalarm = 0;
    alarm(3);
    for ( ; ; ) {
        if (gotalarm)
            return(-3);        /* alarm expired */
        len = pr->salen;
        n = recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, pr->sarecv, &len); //注意这里,会被alarm()中断,中断后不该让它重新开始
        if (n < 0) {
            if (errno == EINTR)
                continue;
            else
                err_sys("recvfrom error");
        }

        ip = (struct ip *) recvbuf;    /* start of IP header */
        hlen1 = ip->ip_hl << 2;        /* length of IP header */
    
        icmp = (struct icmp *) (recvbuf + hlen1); /* start of ICMP header */
        if ( (icmplen = n - hlen1) < 8)
            continue;                /* not enough to look at ICMP header */
    
        if (icmp->icmp_type == ICMP_TIMXCEED &&
            icmp->icmp_code == ICMP_TIMXCEED_INTRANS) {
            if (icmplen < 8 + sizeof(struct ip))
                continue;            /* not enough data to look at inner IP */

            hip = (struct ip *) (recvbuf + hlen1 + 8);
            hlen2 = hip->ip_hl << 2;
            if (icmplen < 8 + hlen2 + 4)
                continue;            /* not enough data to look at UDP ports */

            udp = (struct udphdr *) (recvbuf + hlen1 + 8 + hlen2);
             if (hip->ip_p == IPPROTO_UDP &&
                udp->uh_sport == htons(sport) &&
                udp->uh_dport == htons(dport + seq)) {
                ret = -2;        /* we hit an intermediate router */
                break;
            }

        } else if (icmp->icmp_type == ICMP_UNREACH) {
            if (icmplen < 8 + sizeof(struct ip))
                continue;            /* not enough data to look at inner IP */

            hip = (struct ip *) (recvbuf + hlen1 + 8);
            hlen2 = hip->ip_hl << 2;
            if (icmplen < 8 + hlen2 + 4)
                continue;            /* not enough data to look at UDP ports */

            udp = (struct udphdr *) (recvbuf + hlen1 + 8 + hlen2);
             if (hip->ip_p == IPPROTO_UDP &&
                udp->uh_sport == htons(sport) &&
                udp->uh_dport == htons(dport + seq)) {
                if (icmp->icmp_code == ICMP_UNREACH_PORT)
                    ret = -1;    /* have reached destination */
                else
                    ret = icmp->icmp_code;    /* 0, 1, 2, ... */
                break;
            }
        }
        if (verbose) {
            printf(" (from %s: type = %d, code = %d)\n",
                    Sock_ntop_host(pr->sarecv, pr->salen),
                    icmp->icmp_type, icmp->icmp_code);
        }
        /* Some other ICMP error, recvfrom() again */
    }
    alarm(0);                    /* done

}

 

 

    seq = 0;
    done = 0;
    for (ttl = 1; ttl <= max_ttl && done == 0; ttl++) {
        Setsockopt(sendfd, pr->ttllevel, pr->ttloptname, &ttl, sizeof(int));
        bzero(pr->salast, pr->salen);

        printf("%2d ", ttl);
        fflush(stdout);

        for (probe = 0; probe < nprobes; probe++) {
            rec = (struct rec *) sendbuf;
            rec->rec_seq = ++seq;
            rec->rec_ttl = ttl;
            Gettimeofday(&rec->rec_tv, NULL);

            sock_set_port(pr->sasend, pr->salen, htons(dport + seq));
            Sendto(sendfd, sendbuf, datalen, 0, pr->sasend, pr->salen);
            

            if ( (code = (*pr->recv)(seq, &tvrecv)) == -3)
                printf(" *");        /* timeout, no reply */
            else {
                char    str[NI_MAXHOST];

                if (sock_cmp_addr(pr->sarecv, pr->salast, pr->salen) != 0) {
                    if (getnameinfo(pr->sarecv, pr->salen, str, sizeof(str),
                                    NULL, 0, 0) == 0)
                        printf(" %s (%s)", str,
                                Sock_ntop_host(pr->sarecv, pr->salen));
                    else
                        printf(" %s",
                                Sock_ntop_host(pr->sarecv, pr->salen));
                    memcpy(pr->salast, pr->sarecv, pr->salen);
                }
                tv_sub(&tvrecv, &rec->rec_tv);
                rtt = tvrecv.tv_sec * 1000.0 + tvrecv.tv_usec / 1000.0;
                printf(" %.3f ms", rtt);

                if (code == -1)        /* port unreachable; at destination */
                    done++;
                else if (code >= 0)
                    printf(" (ICMP %s)", (*pr->icmpcode)(code));
            }
            fflush(stdout);
        }
        printf("\n");
    }

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