linux GDB多进程调试 exec函数族

父子进程之间的关系:     

  区别:

    1.fork()函数的返回值不同

      父进程中: >0(栈内存)  返回的子进程ID

      子进程中: =0(栈内存)

    2.PCB中的一些数据不同

      当前进程的PID

      当前进程的父进程的ID  PPID

      信号集不同    

   共同点:

    某些状态下:子进程刚被创建出来,还没有执行任何的写数据的操作

      - 用户区的数据

      - 文件描述符表

  父子进程对变量是不是共享的?

    - 刚开始的时候,是一样的,共享的。如果修改了数据,就不共享了

    - 读时共享(子进程被创建,父子进程没有做任何写的操作),写时拷贝。

GDB多进程调试

使用 GDB调试的时候,GDB默认只能跟踪一个进程,可以在fork 函数调用之前,通过指令设置  GBD调试工具跟踪父进程或者是跟踪子进程,默认跟踪父进程。

设置调试父进程或者子进程: set follow-fork-mode [ parent(默认)  |  child]

设置调试模式:  set  detach-on-fork  [on | off]

默认为 on,表示调试当前进程的时候,其他的进程继续运行,如果为 off ,调试当前进程的时候,其他进程 被 GDB挂起

查看调试的进程:  info  inferiors

切换当前调试的进程:  inferior  id

使进程脱离 GDB 调试:  detach  inferiors  id      

exec函数族   

  exec 函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用过程的内容,换句话说,就是在调用进程内部执行一个可执行文件

  exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程  ID  等一些表面上的信息仍保持原样。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回  -1 ,从原程序的调用点接着往下执行。

  内核区不变,用户区调换为新程序的内容

***execl***

复制代码
 1 /*
 2     exec函数族:  man 3 execl 
 3     #include <unistd.h>
 4     标准C库:
 5     ***int execl(const char* path, const char* arg,.../-  (char *) NULL -/);***
 6         - 参数:
 7             - path:需要指定的执行的文件的路径或者名称
 8                 a.out(相对路径) |   /home/ubuntu/a.out(推荐使用绝对路径)
 9                 ./a.out  hello world
10             - arg:是执行可执行文件所需要的参数列表
11                 第一个参数一般没什么作用,为了方便,一般写的是执行的程序的名称
12                 从第二个参数开始往后,就是程序执行所需要的参数列表
13                 参数最后需要以 NULL 结束(哨兵)
14         - 返回值:
15             只有档调用失败,才会有返回值,返回 -1 并且设置 errno
16             如果调用成功,没有返回值
17     ***int execlp(const char* file, const char* arg,... /-  (char *) NULL -/ );***
18     int execle(const char* path, const char* arg,... /-  (char *) NULL, char* const envp[] -/ );
19     int execv(const char* path, char* const arg[]);
20     int execvp(const char* file, char* const arg[]);
21     int execvpe(const char* file, char* const arg[], char* const envp[]);
22     Linux/Unix:
23     int execve(const char* filename, char* const argv[], char* const envp[]);
24     l(list)         参数地址列表,以空指针结尾
25     v(vector)       存有各参数跌至的指针数组的地址
26     p(path)         按 PATH 环境遍历指定的目录搜索可执行文件
27     e(environment)  存有环境遍历字符串地址的指针数组的地址 
28 */
29 #include <unistd.h>
30 #include <stdio.h>
31 
32 int main()
33 {
34     //创建一个子进程,在子进程中执行exec函数族中的函数
35     __pid_t pid = fork();
36     if(pid > 0)
37     {
38         //父进程
39         printf("i am parent process, pid: %d\n",getpid());
40         sleep(1);
41     }
42     else if(pid == 0)
43     {
44         //子进程
45         //execl("hello","hello",NULL);//执行了hello可执行程序
46         execl("/usr/bin/ps","ps","aux",NULL);//执行  ps aux 命令
47         printf("i am child process, pid: %d\n",getpid());//不会执行
48         //which ps   找到ps指令的绝对路径
49     }
50     for(int i = 0; i < 3; i++)
51     {
52         printf("i = %d, pid = %d\n",i,getpid());
53     }
54     return 0;
55 }
复制代码

***execlp***

复制代码
 1 /*
 2     #include <unistd.h>
 3     int execlp(const char* file, const char* arg,... /-  (char *) NULL -/ );
 4         - 会到环境变量中查找指定的可执行文件,如果找到了就执行,找不到就执行不成功
 5         - 参数:
 6             - file:需要执行的可执行文件的文件名
 7                 a.out
 8                 ps
 9             - arg:是执行可执行文件所需要的参数列表
10                 第一个参数一般没什么作用,为了方便,一般写的是执行的程序的名称
11                 从第二个参数开始往后,就是程序执行所需要的参数列表
12                 参数最后需要以 NULL 结束(哨兵)
13         - 返回值:
14             只有档调用失败,才会有返回值,返回 -1 并且设置 errno
15             如果调用成功,没有返回值   
16     int execv(const char* path, char* const argv[]);
17         argv是需要的参数的一个字符串数组
18             char* argv[] = {"ps","aux",NULL};
19             execv("/bin/ps",argv);
20     
21     int execve(const char* filename, char* const argv[], char* const envp[]);
22         char* envp[] = {"/home/ubuntu","/home/aaa","home/bbb"};
23         按顺序找环境变量
24 */
25 #include <unistd.h>
26 #include <stdio.h>
27 
28 int main()
29 {
30     //env  查询环境变量
31     //创建一个子进程,在子进程中执行exec函数族中的函数
32     __pid_t pid = fork();
33     if(pid > 0)
34     {
35         //父进程
36         printf("i am parent process, pid: %d\n",getpid());
37         sleep(1);
38     }
39     else if(pid == 0)
40     {
41         //子进程
42         execlp("ps","ps","aux",NULL);//正常执行
43     }
44     for(int i = 0; i < 3; i++)
45     {
46         printf("i = %d, pid = %d\n",i,getpid());
47     }
48     return 0;
49 }
复制代码

posted on   廿陆  阅读(107)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示