gdb调试多进程

代码

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <error.h>
#define SIZE 1024
int main()
{
    int shmid ;
    char *shmaddr ;
    struct shmid_ds buf ;
    int flag = 0 ;
    int pid ;
    //获取共享内存区域的id即shmid
    shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT|0600 );//0600 = SHM_R|SHM_W
    if ( shmid < 0 )
    {
        perror("get shm ipc_id error");
        return -1 ;
    }
    pid = fork();
    if ( pid == 0 )
    {
        //根据shmid把共享内存区域映射到调用进程的地址空间中去,这样,进程就可以方便地对共享区域进行访问操作。
        shmaddr = (char *)shmat(shmid, NULL, 0) ;

        if ( shmaddr == NULL )
        {
            perror("shmat addr error") ;
            return -1 ;
        }
        //把字符串拷贝到共享内存内
        printf("child process pid is %d\n",getpid());
        strcpy(shmaddr, "Hi, I am child process jy!\n") ;
        //用来解除进程对shmaddr所在的共享内存区域的映射
        shmdt(shmaddr);
        return 0;
    } 
    else if ( pid > 0) {
        sleep(10) ;
        //实现对共享内存区域的控制操作
        /* IPC_STAT use to get `ipc_perm' options.  */
        flag = shmctl(shmid, IPC_STAT, &buf) ;
        if ( flag == -1 )
        {
            perror("shmctl shm error") ;
            return -1 ;
        }
        printf("shm_segsz =%d bytes\n", buf.shm_segsz ) ;
        printf("parent pid=%d, shm_cpid = %d \n", getpid(), buf.shm_cpid ) ;
        printf("chlid pid=%d, shm_lpid = %d \n",pid , buf.shm_lpid ) ;
        shmaddr = (char *)shmat(shmid, NULL, 0 ) ;
        if ( shmaddr == NULL )
        {
            perror("shmat addr error") ;
            return -1;
        }
        printf("%s", shmaddr) ;
        shmdt(shmaddr) ;
        // #define IPC_RMID 0       /* Remove identifier.  */
        shmctl(shmid, IPC_RMID, NULL) ;
    }
    else{
        perror("fork error") ;
        shmctl(shmid, IPC_RMID, NULL) ;
    }
    return 0 ;
}

调试

www:/mnt/hgfs/Linux/testCPro # gdb sem
GNU gdb (GDB) SUSE (7.3-0.6.1)
Copyright (C) 2011 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 “x86_64-suse-linux”.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/
Reading symbols from /mnt/hgfs/Linux/testCPro/sem…done.
//设置detach-on-fork off后gdb就可以控制父进程和子进程
(gdb) set detach-on-fork off
//设置断点
(gdb) b main
(gdb) r
//单步跟踪到fork处
(gdb) n
22 pid = fork();
//执行fork后可以查看进程信息
(gdb) info inferiors
Num Description Executable
2 process 12084 /mnt/hgfs/Linux/testCPro/sem //子进程
* 1 process 12081 /mnt/hgfs/Linux/testCPro/sem //父进程
//可以通过命令inferior 2切换到子进程调试,当然也可以通过inferior 1进入父进程
(gdb) inferior 2
[Switching to inferior 2 [process 12084] (/mnt/hgfs/Linux/testCPro/sem)]
[Switching to thread 2 (process 12084)]
0 0x00007ffff7b0fcff in fork () from /lib64/libc.so.6
(gdb) p getpid()
$2 = 12084
//且换到父进程
(gdb) inferior 1
(gdb) p getpid()
$3 = 12081`

<think>好的,用户想了解如何使用GDB调试多进程程序,特别是设置调试进程的方法。首先,我需要回忆GDB处理多进程调试的相关命令和策略。记得GDB默认是跟踪父进程,子进程会继续运行不受控制,所以需要配置才能调试子进程。 接下来,应该分步骤说明不同的方法。首先想到的是`follow-fork-mode`,这个选项可以设置为父进程或子进程。需要详细解释如何设置,比如在启动GDB后使用`set follow-fork-mode child`来跟踪子进程,或者用`parent`保持默认。还要提到`show follow-fork-mode`来查看当前模式。 然后,另一个相关的是`detach-on-fork`,它决定在fork之后GDB是否保持对其他进程的控制。如果设置为off,GDB会同时控制父进程和子进程,这时候可能需要配合`inferior`命令来切换不同的进程。这部分需要举例说明,比如切换inferior编号,以及如何查看当前进程。 另外,用户可能需要附加到已运行的进程上,所以需要提到`attach`命令的用法,结合进程ID。还有在代码中插入断点或者`sleep`的方法,以便有时间附加到子进程。 还需要注意不同GDB版本的差异,比如某些命令可能在旧版本中不可用。此外,多线程和多进程的区别可能让用户混淆,需要明确说明这里是多进程的情况。 最后,总结常用方法,提醒用户根据具体情况选择跟踪模式或手动附加,并给出示例命令。确保步骤清晰,让用户能逐步操作,并验证是否有效。可能还要提醒检查GDB版本,或者如何处理常见问题,比如无法附加进程时的权限问题。</think>GDB调试多进程程序时,可通过以下方法设置调试目标进程: ===== 1. 基础设置 ===== 在GDB中通过命令控制fork后的跟踪目标: ```gdb (gdb) set follow-fork-mode parent|child # 设置跟踪父/子进程 (gdb) set detach-on-fork on|off # 控制是否分离未跟踪进程 ``` 示例场景: ```c // 示例代码片段 pid_t pid = fork(); if (pid == 0) { child_process(); // 子进程代码 } else { parent_process(); // 父进程代码 } ``` ===== 2. 多进程调试模式 ===== ◆ 模式1:跟踪单个进程 ```gdb # 默认跟踪父进程 (gdb) set follow-fork-mode parent (gdb) set detach-on-fork on # 或跟踪子进程 (gdb) set follow-fork-mode child ``` ◆ 模式2:同时调试多个进程 ```gdb (gdb) set detach-on-fork off # 保留所有fork的进程 (gdb) info inferiors # 查看进程列表 (gdb) inferior 2 # 切换到第二个进程 ``` ===== 3. 高级调试技巧 ===== ▶ 附加调试已有进程 ```bash # 在终端获取子进程PID ps -ef | grep [程序名] # 在GDB中附加 (gdb) attach <pid> ``` ▶ 代码层控制 ```c // 在子进程代码开始处添加调试桩 void child_process() { volatile int wait_gdb = 1; while(wait_gdb); // 在此处设置断点 //...实际代码... } ``` ===== 4. 验证设置 ===== 调试时使用以下命令确认状态: ```gdb (gdb) show follow-fork-mode # 显示当前跟踪模式 (gdb) info inferiors # 列出所有被控进程 (gdb) inferior # 显示当前调试的进程 ``` ===== 注意事项 ===== 1. Linux内核≥3.9需设置: ```bash echo 0 > /proc/sys/kernel/yama/ptrace_scope ``` 2. 建议使用GDB≥7.0版本 3. 多进程调试时注意断点设置位置(不同进程地址空间独立) 典型调试流程示例: ```gdb $ gdb ./multi_process_prog (gdb) b main (gdb) set detach-on-fork off (gdb) r # 程序fork后暂停 (gdb) info inferiors Num Description Executable 1 process 1234 multi_process_prog 2 process 5678 multi_process_prog (gdb) inferior 2 (gdb) b child_func (gdb) c ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值