如何使用gdbgdb怎么调试多进程程

多进程 gdb attach 问题 - 开源中国社区
当前访客身份:游客 [
当前位置:
2个进程,都运行时,gdb attach B进程,总是停在某个线程处,只有kill A进程或者将A进程暂停,才能附着上去。求助!!!!!!公司里面不能发图。。。。
共有0个答案
更多开发者职位上
有什么技术问题吗?
类似的话题上一篇:下一篇:酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。本帖标题:本帖地址:
帖子永久地址:&<button type="submit" class="pn" onclick="setCopy('GDB调试fork+exec创建的子进程的方法\n/thread--1.html', '帖子地址已经复制到剪贴板您可以用快捷键 Ctrl + V 粘贴到 QQ、MSN 里。')">推荐给好友
width:100%">
失夜Sakitama的回贴低调奢华有内涵
width:100%">
系统居然说我是在灌水,我有吗?
width:100%">
收藏了,怕楼主删了!
width:100%">
顶顶更健康!
width:100%">
好厉害啊!楼主怎么做到的
width:100%">
楼主你想太多了!
width:100%">
强,我和我的小伙伴们都惊呆了!
width:100%">
东方不败外加灭绝师太啊!
width:100%">
12345678910
打开手机扫一扫
Comsenz Inc. Design: Dean. DiscuzFans.Linux下多进程的调试_Linux编程_Linux公社-Linux系统门户网站
你好,游客
Linux下多进程的调试
来源:Linux社区&
作者:南张人
Linux下多进程的调试:
(1)follow-fork-mode
set follow-fork-mode [parent | child] &&&& fork之后选择调试父进程还是子进程
(parent: fork之后继续调试父进程;child: fork之后调试父进程。默认的是fork之后调试父进程)
set detach-on-fork [on | off] &&&& 指示gdb在fork之后是否断开某个进程的调试,或交由gdb控制
(on: 断开调试follow-fork-mode指定的进程;off: gdb将控制父进程和子进程,follow-fork-mode指定的进程将被调试,另一个进程置于暂停状态)
(2)attach pid
下gdb要使用attach pid权限是不够的,需要切换到root,或者你可以sudo chmod +s /usr/bin/gdb给gdb添加权限。
使用attach需要在父子进程代码最开始添加sleep()语句,让进程睡眠,之后在后台运行进程,通过ps获取子进程pid,最后attach pid进入调试子进程。
$./test && & & & & & //使进程test在后台运行
$ps -ef | grep test& & & & //查看进程pid
结果中类似下面的形式:
&&&&&&&&&&&&&&&& ./test& & & & //父进程
&&&&&&&&&&&&&&&& ./test& & & &
//子进程,这里的第一个数字就是子进程pid
$ gdb -q test
(gdb)attach 12346& & & &
//attach到子进程
添加的sleep()可以是类似这样的语句:
while(pause)& & & & //pause是一个标志变量
在gdb调试时你只需要set pause=0使条件不满足即可执行后续代码。
(3)gdb wrapper
当父进程fork出子进程,子进程会紧接着调用exec函数来执行新的代码,这时也可以用gdb wrapper。它的优点是不用添加额外代码。
Linux下将一个进程放到后台运行:
(1)./test &
(2)"./test" 之后按下 "ctrl+z" , 用"bg %num"返回的数字将该进程放到后台;
Linux下将进程拉回前台:
用"fg %num"
GDB调试程序用法
GDB+GDBserver无源码调试 动态链接库的技巧
使用hello-gl2建立ndk-GDB环境(有源码和无源码调试环境)
在Ubuntu上用GDB调试printf源码
Linux下用GDB调试可加载模块
Ubuntu下使用GDB断点Go程序
本文永久更新链接地址:
相关资讯 & & &
& (05月22日)
& (01月21日)
& (07月12日)
& (05月07日)
& (09/26/:51)
图片资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款nginx源码分析--使用GDB调试nginx - 推酷
nginx源码分析--使用GDB调试nginx
gdb是linux上调试应用程序的首选。在进行nginx的调试过程中,首先需要修改Makefile文件。
vi objs/Makefile
#增加 -O0 和 -g 选项; -O0代表不进行优化,-g代表调试模式
CFLAGS = &-pipe -W -Wall -Wpointer-arith -Wno-unused-parameter -g -O0
当然,也可以添加 -gstabs 代替 -O0 ,二者是等同的。上面这种方法是在 ./configure 之后的。如果想省事的话,可以执行如下操作,避免了后续对 Makefile 文件的修改。
CFLAGS=&-g -O0& ./configure
./configure
调试nginx总体来说有三种方法。
一、设置nginx为前台单进程模式
修改配置文件,增加如下两句:
#关闭守护进程,使之在前台运行
#关闭主进程,使只有一个进程
#关闭守护进程,使之在前台运行
master_process
#关闭主进程,使只有一个进程
这就可以了,启动调试。
说明:在这个过程中,因为nginx是前台运行,占用了键盘,因此gdb的命令无法输入。需要输入Ctrl+C,暂停nginx,然后设置断点等一系列操作,之后键入 c 则 nginx就会继续运行了。如下所示:
&http://www.gnu.org/software/gdb/bugs/&...
Reading symbols from /usr/local/nginx/sbin/nginx...done.
Starting program: /usr/local/nginx/sbin/nginx
[Thread debugging using libthread_db enabled]
Program received signal SIGINT, Interrupt.
0x00007ffff6f14513 in epoll_wait () from /lib/libc.so.6
(gdb) b ngx_http_finalize_request
Breakpoint 1 at 0x430be7: file src/http/ngx_http_request.c, line 1939.
Continuing.
http://www.gnu.org/software/gdb/bugs/
0x00007ffff6f14513
Breakpoint
Continuing.
二、设置nginx为后台单进程模式
修改配置文件为:
master_process
这样就打开了nginx后台运行的模式,启动gdb调试发现如下:
Reading symbols from /usr/local/nginx/sbin/nginx...done.
Starting program: /usr/local/nginx/sbin/nginx
[Thread debugging using libthread_db enabled]
Program exited normally.
难道进程真的退出了吗?没有,退出的只是nginx的父进程,而fork出来的进程gdb没有跟到,所以出现了这个情况。这种情况下,gdb是有自己的策略的。命令如下:(
其实这一点我还是比较困惑的!
(gdb) shell pidof nginx
(gdb) set follow-fork-mode child
#设置调试子进程,父进程不受影响(相对应的是parent)
(gdb) b ngx_http_upstream_cleanup
Breakpoint 1 at 0x43db0b: file src/http/ngx_http_upstream.c, line 2951.
follow-fork-mode
#设置调试子进程,父进程不受影响(相对应的是parent)
Breakpoint
三、设置nginx为后台多进程模式
这也是nginx的默认运行模式。在这种情况下,使用gdb的attach和detach指令。
首先查看nginx的work_process进程号是多少,然后直接attach调试就可以了。
Reading symbols from /usr/local/nginx/sbin/nginx...done.
Starting program: /usr/local/nginx/sbin/nginx
[Thread debugging using libthread_db enabled]
Program exited normally.
(gdb) shell pidof nginx
(gdb) attach 5775
Attaching to program: /usr/local/nginx/sbin/nginx, process 5775
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib/libpthread.so.0
#停止调试,使用detach即可
(gdb) detach
#停止调试,使用detach即可
gdb是linux上调试应用程序的首选。在进行nginx的调试过程中,首先需要修改Makefile文件。
vi objs/Makefile
#增加 -O0 和 -g 选项; -O0代表不进行优化,-g代表调试模式
CFLAGS = &-pipe -W -Wall -Wpointer-arith -Wno-unused-parameter -g -O0
当然,也可以添加 -gstabs 代替 -O0 ,二者是等同的。上面这种方法是在 ./configure 之后的。如果想省事的话,可以执行如下操作,避免了后续对 Makefile 文件的修改。
CFLAGS=&-g -O0& ./configure
./configure
调试nginx总体来说有三种方法。
一、设置nginx为前台单进程模式
修改配置文件,增加如下两句:
#关闭守护进程,使之在前台运行
#关闭主进程,使只有一个进程
#关闭守护进程,使之在前台运行
master_process
#关闭主进程,使只有一个进程
这就可以了,启动调试。
说明:在这个过程中,因为nginx是前台运行,占用了键盘,因此gdb的命令无法输入。需要输入Ctrl+C,暂停nginx,然后设置断点等一系列操作,之后键入 c 则 nginx就会继续运行了。如下所示:
&http://www.gnu.org/software/gdb/bugs/&...
Reading symbols from /usr/local/nginx/sbin/nginx...done.
Starting program: /usr/local/nginx/sbin/nginx
[Thread debugging using libthread_db enabled]
Program received signal SIGINT, Interrupt.
0x00007ffff6f14513 in epoll_wait () from /lib/libc.so.6
(gdb) b ngx_http_finalize_request
Breakpoint 1 at 0x430be7: file src/http/ngx_http_request.c, line 1939.
Continuing.
http://www.gnu.org/software/gdb/bugs/
0x00007ffff6f14513
Breakpoint
Continuing.
二、设置nginx为后台单进程模式
修改配置文件为:
master_process
这样就打开了nginx后台运行的模式,启动gdb调试发现如下:
Reading symbols from /usr/local/nginx/sbin/nginx...done.
Starting program: /usr/local/nginx/sbin/nginx
[Thread debugging using libthread_db enabled]
Program exited normally.
难道进程真的退出了吗?没有,退出的只是nginx的父进程,而fork出来的进程gdb没有跟到,所以出现了这个情况。这种情况下,gdb是有自己的策略的。命令如下:(
其实这一点我还是比较困惑的!
(gdb) shell pidof nginx
(gdb) set follow-fork-mode child
#设置调试子进程,父进程不受影响(相对应的是parent)
(gdb) b ngx_http_upstream_cleanup
Breakpoint 1 at 0x43db0b: file src/http/ngx_http_upstream.c, line 2951.
follow-fork-mode
#设置调试子进程,父进程不受影响(相对应的是parent)
Breakpoint
三、设置nginx为后台多进程模式
这也是nginx的默认运行模式。在这种情况下,使用gdb的attach和detach指令。
首先查看nginx的work_process进程号是多少,然后直接attach调试就可以了。
Reading symbols from /usr/local/nginx/sbin/nginx...done.
Starting program: /usr/local/nginx/sbin/nginx
[Thread debugging using libthread_db enabled]
Program exited normally.
(gdb) shell pidof nginx
(gdb) attach 5775
Attaching to program: /usr/local/nginx/sbin/nginx, process 5775
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib/libpthread.so.0
#停止调试,使用detach即可
(gdb) detach
#停止调试,使用detach即可
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致引言&Linus心灵鸡汤
  在*nix开发中有道卡叫gdb调试,不管你怎么搞. 它依然在那丝毫不会松动.今天致敬一个 活着的传奇&Linus Torvalds
  Unix 始于上个世纪60年代,在70年代得到了迅猛的发展,
这时候的李纳斯还躺在祖父公寓的摇篮里睡大觉,如果不是后来 Unix 王国自乱阵脚,
出现阵营分裂和法律纠纷,可能 Linux 系统根本都不会出现。真实的情况是,
Unix 浪费了大把的时间和机会,似乎就是为了等待这个大鼻子、头发纷乱的芬兰小子长大,然后一决高下。
  李纳斯赢得了自己的时间,他一刻不停的磨练自己的技艺,在清晨的微光中练习算法,
在赫尔辛基的雪山上编译代码,随时随地补充的粮草和武器。
二十一年之后,李纳斯抚着雪亮的刀锋上路了,他要去追寻属于程序员的最高荣耀。[
  I simply know better than you, that's why I'm your god.
&&&&                      - -& Linus Torvalds
前言& gdb&开始调试开始上手
1.&开启core,&采集程序崩溃的状态
  首先你跟着我做开启core崩溃状态采集.&可以通过&ulimit -c&查看&如果是0表示没有开启.&开启按照下面操作
vi /etc/profile
# No core files by default 0, unlimited is oo
ulimit -S -c unlimited & /dev/null 2&&1
source /etc/profile
上面shell&操作是&在 /etc/profile&最后一行添加&上面设置全局开启&core文件调试,大小不限.&最后&立即生效.
再跟着我做,&因为生成的core文件同名会覆盖.&这里为其加上一个&core命名规则,&让其变成&[core.pid]&格式.
vi /etc/sysctl.conf
# open, add core.pid
kernel.core_pattern = ./core_%t_%p_%ekernel.core_uses_pid = 1
sysctl -p /etc/sysctl.conf
在 /etc/sysctl.conf&文件中添加系统配置.&后面立即启用.&最后是下面状态表示core启用都搞好了.
(上面是ubuntu 15.10 环境中,&后面测试用的是centos 6.4)
2.&简单接触&GDB ,&开始调试&r&n&p
第一个演示代码&heoo.c
#include &stdio.h&
int g_var = 0;
static int _add(int a, int b) {
printf("_add callad, a:%d, b:%d\n", a, b);
return a+b;
int main(void) {
int n = 1;
printf("one n=%d, g_var=%d\n", n, g_var);
g_var += 20;
g_var -= 10;
n = _add(1, g_var);
printf("two n=%d, g_var=%d\n", n, g_var);
我们下面从图说起.(如果用视频说更好,文字和图意义在于查询方便.更简约)
第一个命令&gdb&heoo.out&表示&gdb加载&heoo.out&开始调试.&如果需要使用gdb调试的话编译的时候&gcc&需要加上 -g命令.
其中l命令表示&查看加载源码内容.&下面将演示如何加断点.
r&表示调试的程序开始运行.
p&命令表示&打印值.&n表示过程调试,&到下一步.&不管子过程如何都不进入. 直接一次跳过.
上面用的s&表示单步调试,&遇到子函数,会进入函数内部调试.
总结一下 .&l 查看源码 , b&加断点,&r&开始运行调试,&n&下一步,&s下一步但是会进入子函数.&p&输出数据.
到这里gdb&基本会用了.&是不是也很容易.&直白.&小代码可以随便调试了.
看到这里基础知识普及完毕了.&后面可以不看了.&有机会再看.&好那我们接着扯.
正文&第一部分&gdb其它开发中用的命令
  开始扯一点,&linux总是敲命令操作,&也很不安全.&有时候晕了.&写这样编译命令.
gcc -g -Wall -o heoo.c heoo.out
非常恐怖,&heoo.c&代码删除了.&heoo.out =&&heoo.c&先创建后生成失败退出.&原先的内容被抹掉了.&哈哈.&服务器开发,&经验不足,&熟练度不够.自己都怕自己.
1.&&gdb&其它常用命令用法&c&q&b&info
首先看&用到的调试文件&houge.c
#include &stdio.h&
#include &stdlib.h&
#include &time.h&
* arr 只能是数组
* 返回当前数组长度
#define LEN(arr) (sizeof(arr)/sizeof(*arr))
// 简单数组打印函数
static void _parrs(int a[], int len) {
int i = -1;
puts("当前数组内容值如下:");
while(++i & len)
printf("%d ", a[i]);
putchar('\n');
// 简单包装宏, arr必须是数组
#define PARRS(arr) \
_parrs(arr, LEN(arr))
#define _INT_OLD (23)
* 主函数,简单测试
* 测试 core文件,
* 测试 宏调试
* 测试 堆栈内存信息
int main(void) {
int a[_INT_OLD];
int* ptr = NULL;
// 来个随机数填充值吧
srand((unsigned)time(NULL));
for(i=0; i&LEN(a); ++i)
a[i] = rand()%222;
//全员加double, 包含一个错误方便测试
for(i=1; i&=LEN(a); ++i)
a[i] &&= 1;
// 为了错,强制错
同样需要仔细看下面图中使用的命令.&首先对前言部分加深一些.&看下面
这个图是前言的补充,&c跳过直到下一个断点处,&q表示程序退出.
在&houge.c&中我们开始调试.&一运行段错误,&出现了我们的&core.pid&文件
通过&gdb&houge.out core.27047&开始调试.&马上定位出来了错误原因.
2. 调试&内存堆栈信息
刚开始&print&a ,&在main中当做数组处理.打印的信息多.&后面在_add函数中,&a就是个形参数组地址.
主要看&info&args&&查看当前函数参数值
info&locals&看当前函数栈上值信息,&info registers&表示查看寄存器值.
后面查看内存信息&需要记得东西多一些.&先看图
x /23dw&a&意思是&&查看&从a地址开始 23个 4字节&有符号十进制数&输出.
关于x&更加详细见下面
用gdb查看内存格式:
x /nfu ptr
x 是 examine 的缩写
n表示要显示的内存单元的个数
f表示显示方式, 可取如下值
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。
u表示一个地址单元的长度
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
t(binary), f(float), a(address), i(instruction), c(char) and s(string).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes)
ptr 表示从那个地址开始
这个命令常用于监测内存变化.调试中特别常用.
3. gdb&设置条件断点
很简单&b 17&if&i == 8.&在17行设置一个断点,并且只有i==8的时候才会触发.
4. gdb&删除断点
gdb&删除有d&后面跟断点索引1,2,3..
clear&行数或名称.&删除哪一行断点.&看下面演示
到这里&介绍的gdb调试技巧基本都够用了.&感觉用图形ide,例如vs调试也就用到这些了.
估计gdb调试突破20min过去了.够用了. &后面可以不用看了.
正文&第二部分&gdb&多线程多进程调试
  到这里实战中用的机会少了,&也就老鸟会用上些.&这部分可以调试,不好调试.&一般一调估计小半天就走了.&好,那我们处理最后10min.
1. 首先对上面正文第一部分加深&gdb调试宏
首先看上面命令&
  macro&expand&宏(参数) =&&得到宏导出内容.
  info&macro&宏名 =&&宏定义内容
如果你需要用到上面gdb功能,&查看和导出宏的话.还需要gcc&支持,生成的时候加上 -ggdb3如下
gcc -Wall -ggdb3 -o houge.out houge.c
就可以使用了.&扩展一下&对于&gcc&编译的有个过程叫做&预编译&gcc -E -o *.i *.c.
这时候处理多数宏,直接展开,&也可以查看最后结果.&也算也是一个黑科技.
2.&开始多线程调试
首先看测试用例&dasheng.c
#include &stdio.h&
#include &stdlib.h&
#include &pthread.h&
// 声明一个都用的量
static int _
// 线程跑的函数
static void* _run(void* arg) {
int piyo = 10;
int n = *(int*)
//设置线程分离
pthread_detach(pthread_self());
for(i=0; i&n; ++i) {
printf("n=%d, i=%d\n", n, i);
printf("n=%d, piyo = %d, _old=%d\n", n, piyo, _old);
return NULL;
#define _INT_PTX (3)
int main(void) {
int i, rt,
pthread_t tx[_INT_PTX];
puts("main beign");
for(i=0; i&_INT_PTX; ++i) {
// &i 是有问题的, 但是这里为了测试, 可以乱搞
rt = pthread_create(tx+i, NULL, _run, &i);
if(rt & 0) {
printf("pthread_create create error! rt = %d, i=%d\n", rt, i);
//CPU忙等待
for(j=0; j&; ++j)
puts("end");
gcc -Wall -g -o dasheng.out dasheng.c -lpthread
那先看下面测试图
上面&info&threads&查看所有运行的线程信息. *表示当前调试的线程.
后面&l&_run&表示查看 _run附近代码.&当然还有&l&16&查看16行附近文件内容.
gdb多线程切换&测试如下
&thread 3表示切换到第三个线程,&info&threads&第一列id&就是&thread&切换的id.
上面测试线程&就算你切换到&thread 3.&其它线程还是在跑的.&我们用下面命令&只让待调试的线程跑.&其它线程阻塞.
set scheduler-locking on&&开始多线程单独调试.&不用了&设置&set scheduler-locking off&关闭.&又会回到你调试这个,&其它线程不阻塞.
总结&多线程调试常用就这三个实用命令
info&threads
set scheduler-locking on/off
分别是查看,切换,设置同步调试.到这里多线程调试基本完毕了.
3.&开始gdb&多进程调试
首先看&liaobude.c&测试代码
#include &stdio.h&
#include &stdlib.h&
#include &errno.h&
#include &unistd.h&
#include &sys/types.h&
#include &sys/wait.h&
// 声明一个都用的量
static int _
// 线程跑的函数
static void _run(int n) {
int piyo = 10;
for(i=0; i&n; ++i) {
printf("n=%d, i=%d\n", n, i);
printf("n=%d, piyo = %d, _old=%d\n", n, piyo, _old);
#define _INT_PTX (3)
int main(void) {
puts("main beign");
for(i=0; i&_INT_PTX; ++i) {
// &i 是有问题的, 但是这里为了测试, 可以乱搞
rt = fork();
if(rt & 0) {
printf("fork clone error! rt = %d, i=%d\n", rt, i);
if(rt == 0) {
exit(EXIT_FAILURE);
//等待子进程结束  for(;;) {    rt = waitpid(-1, NULL, WNOHANG);    if(rt&=0 || errno==EINTR)            }
puts("end");
// 这里继续等待
for(i=0; i&190; ++i){
printf("等待 有缘人[%d]!\n", i);
gcc -Wall -g -o liaobude.out liaobude.c
&其实对多进程调试,&先介绍一个&常用的, 调试正在运行的程序.&首先让&./liaobude.out&跑起来.
&再通过&ps -ef&找到需要调试的进程.&复制进程文件描述符pid.
这时候启动gdb.
attach&pid
gdb就把pid那个进程加载进来了.&加载的进程会阻塞到当前正在运行的地方.&直到使用命令控制.&这个功能还是非常猛的.
最后介绍 进程调试的有关命令(需要最新的gdb才会支持).&多进程的调试思路和多线程调试流程很相似.
GDB可以同时调试多个程序。
只需要设置follow-fork-mode(默认值:parent)和detach-on-fork(默认值:on)即可。
设置方法:set follow-fork-mode [parent|child]
set detach-on-fork [on|off]
查询正在调试的进程:info inferiors
切换调试的进程: inferior &infer number&
具体的意思有
set follow-fork-mode [parent|child]&& set detach-on-fork [on|off]
&parent&&&&&&&&&&&&&&& && on&&&&&&&&&&&&&& 只调试主进程(gdb默认)&child& &&& & &&& & & && && on&&&&&&&&&&&&&& 只调试子进程&parent&&&&&&&&&& && & && off&&&&&&&&&&&&& 同时调试两个进程,gdb跟主进程,子进程block在fork位置&child& &&&&&&&& & && & &&& off &&&&&&&&&&&& 同时调试两个进程,gdb跟子进程,主进程block在fork位置
更加详细的&gdb&多进程调试demo&可以参照&
使用方式和线程调试思路是一样的. 就是gdb&的命令换了字符.&工作中多进程调试遇到少.&
遇到了很少用gdb调试.&会用下面2种调试好办法
2)&写单元测试
3)&打日志检测日志,分析
到这里&gdb30分钟内容讲解完毕.&多试试写写练一练,&gdb基本突破没有问题.
  错误是难免的,&有问题可以随时交流.&拜~~,&周六下午愉快.&希望明天仍然是个好天气~~
阅读(...) 评论()}

我要回帖

更多关于 怎样使用gdb调试微信 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信