ubuntu gdb 多线程调试步骤

注:实验代码来自于网络,在原代码中只增加了一些打印代码。

 

本文仅作复习笔记之用,以备日后查阅。

 

#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“ 是代表当前线程,而我们要进入线程里进行调试,因此需要切换线程。

如下:

(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) 

 

说明:

上面的操作过程,有些步骤重复,主要该程序是服务器端程序,需要客户端连接后,并发送数据。而实验过程中忘记了从客户端向服务器端发送数据包,当完成客户端操作后,服务器调试时未从新操作,因此有了重复步骤。

 

客户端使用网络上的调试工具:


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章