多线程ping程序出现“段错误”,求解

hjwmzh 2014-07-10 08:39:49
本程序主要实现同时测量到多个地址的延时值,用多线程实现。本程序在ipv4和ipv6环境下均适用,但主要目的是在ipv6环境下测时延。以下显示代码是程序的核心部分,但运行有错误,求高手相助!
//initial 初始化
//send 发包
//recv 收包
//proc 处理包,即取包中的数据,计算延时并显示
void *initialsendrecvproc( struct addrinfo *ai )
{//为方便查找错误,本函数进行了简化,去掉了循环
//只发一个ping包,然后接收该ping包的返回包
//最后计算这两个包的时间差,并输出该时间差值
int size;
int nsent;
char recvbuf[BUFSIZE];
char controlbuf[BUFSIZE];
struct msghdr msg;
struct iovec iov;
ssize_t n;
struct timeval tval;

struct proto *pr;

if (ai->ai_family == AF_INET) { //ipv4
pr = &proto_v4;
#ifdef IPV6
} else if (ai->ai_family == AF_INET6) { //ipv6
pr = &proto_v6;
if (IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr)))
err_quit("cannot ping IPv4-mapped IPv6 address");
#endif
} else
err_quit("unknown address family %d", ai->ai_family);

pr->sasend = ai->ai_addr;
pr->sarecv = Calloc(1, ai->ai_addrlen);
pr->salen = ai->ai_addrlen;

sockfd = Socket(pr->sasend->sa_family, SOCK_RAW, pr->icmpproto); //使用原始套接字
setuid(getuid());
if (pr->finit)
(*pr->finit)( );

nsent = 0;
size = 60 * 1024;
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));//设置套接字选项

iov.iov_base = recvbuf;
iov.iov_len = sizeof(recvbuf);
msg.msg_name = pr->sarecv;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = controlbuf;

send_v6(pr, &nsent); //发一个包
msg.msg_namelen = pr->salen;
msg.msg_controllen = sizeof(controlbuf);

n = recvmsg(sockfd, &msg, 0);//收上面刚发的包
Gettimeofday(&tval, NULL);//得到当前时间
proc_v6(recvbuf, n, &msg, &tval, pr);//处理包,计算延时并显示

//标记1 printf(“hj\n”);
pthread_exit(NULL);
}

int main(int argc, char **argv)
{
int i;
struct addrinfo *ai;
char *h;

//ipaddress是一个纯文本文件,为排错方便,文件里只包含两行字符串
//第一行是”www.google.com” 第二行是”www.kame.net”
if ((fp1 = fopen("ipaddress","r")) == NULL)
{
printf("cannot open infile\n");
exit(0);
}

while(!feof(fp1))
{
fscanf(fp1,"%s",host); //host的定义语句为 char host[100]
ai = Host_serv(host, NULL, 0, 0);

h = Sock_ntop_host(ai->ai_addr, ai->ai_addrlen);
printf("PING %s (%s): %d data bytes\n", ai->ai_canonname ? ai->ai_canonname : h, h, datalen);

memset(&thread, 0, sizeof(thread));
if (( pthread_create(&thread, NULL, initialsendrecvproc(ai), NULL)) != 0)
{
printf("thread %d create fail!\n", i++);
}
else
{
printf("thread %d create success!\n", i++);
}
//标记2 printf(“hj\n”);
sleep(1);
//标记3 printf(“hj\n”);
}

}
程序想达到的效果是启两个线程,分别测试到www.google.com和www.kame.net 的延时,但以上程序执行的结果如下:
[ root@ipv6measure hj]# gcc dxcpingipv6.c –o dxcpingipv6 –lpthread –lunp –g
[ root@ipv6measure hj]# chmod u+s dxcpingipv6
[ root@ipv6measure hj]# ./dxcpingipv6
PING www.google.com (2404:6800:4005:801::1013): 56 data bytes
64 bytes from 2404:6800:4005:801::1013: seq=0, hlim=49, rtt=287.707 ms
[ root@ipv6measure hj]#
也就是说第一个线程启动成功了,但第一个线程执行完了以后,整个程序就结束了。Main线程不再继续往下执行了,第二个线程也没有被创建。
我在标记1处添加了一行printf(“hj\n”);结果程序运行结果如下
[ root@ipv6measure hj]# ./dxcpingipv6
PING www.google.com (2404:6800:4005:805::1011): 56 data bytes
64 bytes from 2404:6800:4005:805::1011: seq=0, hlim=49, rtt=294.230 ms
hj
[ root@ipv6measure hj]#
这说明线程函数initialsendrecvproc(ai)能正常执行结束,那为什么第一个线程执行完了以后,整个程序就结束了?main线程为什么不再继续往下执行了?求高手指点!

我尝试对程序作了一点修改,把标记1和标记1下面一行”pthread_exit(NULL);”注释掉了,重新运行程序,结果如下
[ root@ipv6measure hj]# ./dxcpingipv6
PING www.google.com (2404:6800:4005:803::1014): 56 data bytes
64 bytes from 2404:6800:4005:803::1014: seq=0, hlim=49, rtt=295.691 ms
thread 0 create success!
段错误
[ root@ipv6measure hj]#
这说明第一个线程启动后,main线程开始继续往下执行了,但出现了”段错误”。
为确定”段错误”在哪一行产生的,我在标记2处加了一行printf(“hj\n”);结果程序运行结果如下
[ root@ipv6measure hj]# ./dxcpingipv6
PING www.google.com (2404:6800:4005:800::1010): 56 data bytes
64 bytes from 2404:6800:4005:800::1010: seq=0, hlim=49, rtt=279.224 ms
thread 0 create success!
hj
段错误
[ root@ipv6measure hj]#
也就是说程序能执行完标记2这一行,然后报”段错误”
我进一步修改,把标记2这一行注释掉,在标记3处加一行printf(“hj\n”);结果程序运行结果如下
[ root@ipv6measure hj]# ./dxcpingipv6
PING www.google.com (2404:6800:4005:803::1010): 56 data bytes
64 bytes from 2404:6800:4005:803::1010: seq=0, hlim=49, rtt=284.096 ms
thread 0 create success!
段错误
[ root@ipv6measure hj]#
这说明程序没有运行到标记3这一行就报”段错误”了!也就是说”段错误”出现在标记2行和标记3行之间,也就是sleep(1)这条语句处!但执行sleep(1)怎么会报”段错误”呢?求高手指点!
...全文
346 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_17527633 2014-07-11
  • 打赏
  • 举报
回复
谢谢分享啊啊
内容概要:本文系统研究了Picard迭代法在非线性常微分方程参数估计中的应用,深入阐述了该方法的数学原理及其在参数辨识中的收敛性与稳定性优势。通过构建最小化误差的目标函数,并结合数值积分技术,采用迭代方式逐步逼近系统的真实参数值,有效解决了非线性动态系统中因缺乏解析解而难以进行精确建模的问题。文中提供了完整的Matlab代码实现,涵盖模型定义、迭代求解、参数更新与结果可视化等关键环节,增强了方法的可操作性与工程实用性。研究通过典型非线性系统案例验证了算法的有效性,展示了其在科学计算与工程建模中的良好适应性与推广潜力。; 适合人群:具备常微分方程理论、数值分析基础及Matlab编程能力,从事系统建模、参数辨识、动力学仿真等相关方向的研究生、科研人员和工程技术开发者。; 使用场景及目标:①解决实际工程中非线性微分方程模型的未知参数估计问题;②深入理解Picard迭代法在科学计算中的实现机制与数值特性;③为学术论文复现、科研项目开发或课程设计提供可运行、易调试的技术方案与代码参考。; 阅读建议:建议读者结合文中的数学推导与Matlab代码逐行分析,重点关注迭代流程、目标函数构造与数值积分的耦合实现,通过修改模型结构或噪声条件进行扩展实验,以深化对算法鲁棒性与适用边界的理解。配套资源可通过指定公众号和网盘链接获取,推荐同步学习以加速科研进程。

23,224

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧