ubuntu gdb 多线程调试步骤
来源:互联网 发布:java点菜系统项目案例 编辑:程序博客网 时间:2024/06/09 10:52
注:实验代码来自于网络,在原代码中只增加了一些打印代码。
本文仅作复习笔记之用,以备日后查阅。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
//#include <openssl/ssl.h>
//#include <openssl/err.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <pthread.h>
#include <assert.h>
//#include "oci_api.h"
#define MAXBUF 1024
#define MAXEPOLLSIZE 100
/*
setnonblocking ?C ???þ???Ϊ????????ʽ
*/
int setnonblocking(int sockfd)
{
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)
{
return -1;
}
return 0;
}
/*
pthread_handle_message ?C ?̴߳??? socket ?ϵ???Ϣ?շ?
*/
void* pthread_handle_message(int* sock_fd)
{
char recvbuf[MAXBUF + 1];
char sendbuf[MAXBUF+1];
int ret;
int new_fd;
struct sockaddr_in client_addr;
socklen_t cli_len=sizeof(client_addr);
new_fd=*sock_fd;
/* ??ʼ????ÿ????l???ϵ??????շ? */
bzero(recvbuf, MAXBUF + 1);
bzero(sendbuf, MAXBUF + 1);
/* ???տͻ??˵???Ϣ */
ret = recvfrom(new_fd, recvbuf, MAXBUF, 0, (struct sockaddr *)&client_addr, &cli_len);
if (ret > 0){
printf("socket: %d \n recv from : %s : %d \n message: %s \n ??%d bytes \n",
new_fd, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), recvbuf, ret);
/*
char *s1="insert";
char *s2="select";
char *s3="delete";
if(!strncmp(s1,recvbuf,6))
oci_insert(recvbuf,sendbuf);
else if(!strncmp(s2,recvbuf,6))
oci_select(recvbuf,sendbuf);
else if(!strncmp(s3,recvbuf,6))
oci_delete(recvbuf,sendbuf);
else
sprintf(sendbuf,"input sql is error!/n");
ret = sendto(new_fd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&client_addr, cli_len);
if(ret<0)
printf("??Ϣ????ʧ?ܣ???????????%d????????Ϣ??'%s'/n", errno, strerror(errno));
*/
}
else
{
printf("received failed! error code %d ??message : %s \n",
errno, strerror(errno));
}
/* ????ÿ????l???ϵ??????շ????? */
//printf("pthread exit!");
fflush(stdout);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
int listener, kdpfd, nfds, n, curfds;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
unsigned int myport;
struct epoll_event ev;
struct epoll_event events[MAXEPOLLSIZE];
struct rlimit rt;
myport = 1234;
printf("port setting 1234 success \n");
pthread_t thread;
pthread_attr_t attr;
/* ????ÿ???????????�??????ļ??? */
rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
{
perror("setrlimit");
exit(1);
}
else
{
printf("setting success \n");
}
printf("setting success \n");
/* ???? socket ???? */
if ((listener = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("socket create failed ??");
exit(1);
}
else
{
printf("socket create success /n");
}
printf("3 setting success \n");
/*????socket???ԣ??˿ڿ???????*/
int opt=SO_REUSEADDR;
setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
setnonblocking(listener);
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
/*
my_addr.sin_addr.s_addr = INADDR_ANY;
*/
my_addr.sin_addr.s_addr = inet_addr("192.168.34.52");
printf("4 setting success \n");
/*
printf("socket : %s \n", inet_ntoa((my_addr.sin_addr));
*/
printf("socket : %s \n", inet_ntoa(my_addr.sin_addr));
if (bind(listener, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1)
{
printf("socket : %s \n", inet_ntoa(my_addr.sin_addr));
perror("bind error! \n");
exit(1);
}
else
{
printf("IP and port bind success \n");
printf("port: %d \n",ntohs(my_addr.sin_port));
}
/* ???? epoll ???????Ѽ??? socket ???뵽 epoll ?????? */
kdpfd = epoll_create(MAXEPOLLSIZE);
len = sizeof(struct sockaddr_in);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = listener;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0)
{
fprintf(stderr, "epoll set insertion error: fd=%d \n", listener);
return -1;
}
else
{
printf("111112223333listen socket added in epoll success \n");
}
while (1)
{
/* ?ȴ????¼????? */
printf("6666666listen socket added in epoll success \n");
printf("7777777 kdpfd values: %d \n",kdpfd);
nfds = epoll_wait(kdpfd, events, 10,-1 );
printf("nfds values: %d ",nfds);
if (nfds == -1)
{
perror("epoll_wait \n");
break;
}
printf(" epoll wait ok \n");
/* ?????????¼? */
for (n = 0; n < nfds; ++n)
{
if (events[n].data.fd == listener)
{
/*??ʼ??????ֵ??????ΪĬ??ֵ*/
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
/* ?????߳?Ϊ????????*/
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if(pthread_create(&thread,&attr,(void*)pthread_handle_message,(void*)&(events[n].data.fd)))
{
perror("pthread_creat error!");
exit(-1);
}
}
}
}
close(listener);
return 0;
}
查看目录里的内容:
说明:编译udpepoll.c文件时,必须要加”-g“ 选项,要不后面无法用gdb调试。
root@ubuntu:/home/lin/epoll/udp# ls
udpepoll.c up
”up“为编译后的文件,通过gdb加载调试:
root@ubuntu:/home/lin/epoll/udp# gdb up
GNU gdb (Ubuntu/Linaro 7.4-2012.02-0ubuntu2) 7.4-2012.02
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/lin/epoll/udp/up...done.
(gdb) l 214
209 printf("6666666listen socket added in epoll success \n");
210
211 printf("7777777 kdpfd values: %d \n",kdpfd);
212 nfds = epoll_wait(kdpfd, events, 10,-1 );
213 printf("nfds values: %d ",nfds);
214 if (nfds == -1)
215 {
216 perror("epoll_wait \n");
217 break;
218 }
查看断点信息:
(gdb) info b
No breakpoints or watchpoints.
上面显示无断点,所以在代码”udpepoll.c“文件中的 214行设置断点:
(gdb) b 214
Breakpoint 1 at 0x8048fea: file udpepoll.c, line 214.
(gdb) c
The program is not being run.
执行程序:
(gdb) r
Starting program: /home/lin/epoll/udp/up
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
port setting 1234 success
setting success
setting success
socket create success /n3 setting success
4 setting success
socket : 192.168.34.52
IP and port bind success
port: 1234
111112223333listen socket added in epoll success
6666666listen socket added in epoll success
7777777 kdpfd values: 8
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/lin/epoll/udp/up
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
port setting 1234 success
setting success
setting success
socket create success /n3 setting success
4 setting success
socket : 192.168.34.52
IP and port bind success
port: 1234
111112223333listen socket added in epoll success
6666666listen socket added in epoll success
Breakpoint 1, main (argc=1, argv=0xbffff264) at udpepoll.c:211
211 printf("7777777 kdpfd values: %d \n",kdpfd);
(gdb) n
7777777 kdpfd values: 8
212 nfds = epoll_wait(kdpfd, events, 10,-1 );
(gdb)
213 printf("nfds values: %d ",nfds);
(gdb)
214 if (nfds == -1)
(gdb)
221 printf(" epoll wait ok \n");
(gdb)
nfds values: 1 epoll wait ok
223 for (n = 0; n < nfds; ++n)
(gdb)
225 if (events[n].data.fd == listener)
(gdb)
228 pthread_attr_init(&attr);
(gdb)
229 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
(gdb)
233 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
(gdb)
236 if(pthread_create(&thread,&attr,(void*)pthread_handle_message,(void*)&(events[n].data.fd)))
查看线程信息:
(gdb) info threads
Id Target Id Frame
* 1 Thread 0xb7e076c0 (LWP 23445) "up" main (argc=1, argv=0xbffff264) at udpepoll.c:236
(gdb) n
[New Thread 0xb7e06b40 (LWP 23450)]
223 for (n = 0; n < nfds; ++n)
(gdb)
244 }
还是查看线程信息:
(gdb) info threads
Id Target Id Frame
2 Thread 0xb7e06b40 (LWP 23450) "up" 0xb7ef3ab8 in clone () from /lib/i386-linux-gnu/libc.so.6
* 1 Thread 0xb7e076c0 (LWP 23445) "up" main (argc=1, argv=0xbffff264) at udpepoll.c:244
上面查到当前有两个线程,看最前面的序号,”*1“ 是代表当前线程,而我们要进入线程2 里进行调试,因此需要切换线程。
如下:
(gdb) thread 2
[Switching to thread 2 (Thread 0xb7e06b40 (LWP 23450))]
#0 0xb7ef3ab8 in clone () from /lib/i386-linux-gnu/libc.so.6
再查看线程信息:
(gdb) info threads
Id Target Id Frame
* 2 Thread 0xb7e06b40 (LWP 23450) "up" 0xb7ef3ab8 in clone () from /lib/i386-linux-gnu/libc.so.6
1 Thread 0xb7e076c0 (LWP 23445) "up" main (argc=1, argv=0xbffff264) at udpepoll.c:244
单步执行:
(gdb) n
Single stepping until exit from function clone,
which has no line number information.
0xb7fb4c80 in start_thread () from /lib/i386-linux-gnu/libpthread.so.0
(gdb)
Single stepping until exit from function start_thread,
which has no line number information.
Breakpoint 2, pthread_handle_message (sock_fd=0xbfffec98) at udpepoll.c:51
51 socklen_t cli_len=sizeof(client_addr);
(gdb)
54 new_fd=*sock_fd;
注意:如下设置
(gdb) set scheduler-locking on
说明,多线程时,线程是同时运行的,要保证始终在本线程内调试,需做上述的操作。
(gdb) n
58 bzero(recvbuf, MAXBUF + 1);
(gdb)
59 bzero(sendbuf, MAXBUF + 1);
(gdb)
63 ret = recvfrom(new_fd, recvbuf, MAXBUF, 0, (struct sockaddr *)&client_addr, &cli_len);
查看变量值:
(gdb) p ret
$4 = 0
(gdb) n
64 if (ret > 0){
查看变量值:
(gdb) p ret
$5 = 10
查看从客户端接收到是内容:
保存在recvbuf变量内。
(gdb) p recvbuf
$6 = "1122334488", '\000' <repeats 1014 times>
(gdb)
说明:
上面的操作过程,有些步骤重复,主要该程序是服务器端程序,需要客户端连接后,并发送数据。而实验过程中忘记了从客户端向服务器端发送数据包,当完成客户端操作后,服务器调试时未从新操作,因此有了重复步骤。
客户端使用网络上的调试工具:
- ubuntu gdb 多线程调试步骤
- Ubuntu中gdb调试步骤
- gdb调试步骤
- Android gdb 调试步骤
- 使用gdb调试多线程
- GDB多线程调试
- gdb多线程调试1
- gdb多线程调试2
- gdb 调试多线程
- gdb调试多线程
- GDB多线程调试
- gdb调试多线程程序
- GDB 多线程调试
- linux GDB 调试多线程
- GDB 多线程调试
- GDB多线程调试
- gdb调试多线程
- gdb多线程调试转
- 通俗易懂的介绍匈牙利算法
- Java实现定时任务的三种方法
- 轮廓提取
- Spring AOP 前切入点及多参数问题
- linux下的并发处理
- ubuntu gdb 多线程调试步骤
- 自己动手搭建免费VoIP服务器
- 源码安装yum
- android 网络判断工具类(APN+WIFI)
- 仿QQ布局实例
- 销售部年终总结酒店服务员年终总结
- njupt-1134-Christmas
- 笔记87--android坐标
- mm: iommu: An API to unify IOMMU, CPU and device memory management