第2章 Linux多进程开发 01~05 进程概述 进程状态转换 进程创建 父子进程虚拟地址空间情况 gdb多进程调试

进程概述

当下常见 CPU 为纳秒级,1秒可以执行大约 10 亿条指令
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

进程状态转换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

PPID 父进程的ID
PID进程ID
PGID进程组的ID(多个学生PID在一个教室PGID)
SID会话(多个教室PGID是个学校SID)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

kill -9 pid 强制杀死一个进程

在这里插入图片描述

init进程:操作系统启动的那个进程

在这里插入图片描述

进程创建

在这里插入图片描述

父子进程虚拟地址空间情况

读时共享,写时拷贝:

实际上,更准确来说,Linux 的 fork() 使用是通过写时拷贝 (copy- on-write) 实现。写时拷贝是一种可以推迟甚至避免拷贝数据的技术。内核此时并不复制整个进程的地址空间,而是让父子进程共享同一个地址空间。只用在需要写入的时候才会复制地址空间,从而使各个进行拥有各自的地址空间。也就是说,资源的复制是在需要写入的时候才会进行,在此之前,只有以只读方式共享。

注意:fork之后父子进程共享文件,fork产生的子进程与父进程相同的文件文件描述符指向相同的文件表,引用计数增加,共享文件偏移指针。

在这里插入图片描述

/*
    #include <sys/types.h>
    #include <unistd.h>

    pid_t fork(void);
        函数的作用:用于创建子进程。
        返回值:
            fork()的返回值会返回两次。一次是在父进程中,一次是在子进程中。
            在父进程中返回创建的子进程的ID,
            在子进程中返回0
            如何区分父进程和子进程:通过fork的返回值。
            在父进程中返回-1,表示创建子进程失败,并且设置errno

        父子进程之间的关系:
        区别:
            1.fork()函数的返回值不同
                父进程中: >0 返回的子进程的ID
                子进程中: =0
            2.pcb中的一些数据
                当前的进程的id pid
                当前的进程的父进程的id ppid
                信号集

        共同点:
            某些状态下:子进程刚被创建出来,还没有执行任何的写数据的操作
                - 用户区的数据
                - 文件描述符表:父进程有个文件描述符3(指向a.txt),子进程也有个文件描述符3(指向a.txt),子进程关闭文件描述符3,不会影响父进程。
        
        父子进程对变量是不是共享的?
            - 刚开始的时候,是一样的,共享的。如果修改了数据,不共享了。
            - 读时共享(子进程被创建,两个进程没有做任何的写的操作),写时拷贝。
        
*/

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main() {

    int num = 10;

    // 创建子进程
    pid_t pid = fork();

    // 判断是父进程还是子进程
    if(pid > 0) {
        // printf("pid : %d\n", pid);
        // 如果大于0,返回的是创建的子进程的进程号,当前是父进程
        printf("i am parent process, pid : %d, ppid : %d\n", getpid(), getppid());

        printf("parent num : %d\n", num);
        num += 10;
        printf("parent num += 10 : %d\n", num);


    } else if(pid == 0) {
        // 当前是子进程
        printf("i am child process, pid : %d, ppid : %d\n", getpid(),getppid());
       
        printf("child num : %d\n", num);
        num += 100;
        printf("child num += 100 : %d\n", num);
    }

    // for循环
    for(int i = 0; i < 3; i++) {
        printf("i : %d , pid : %d\n", i , getpid());
        sleep(1);
    }

    return 0;
}

gdb多进程调试

gdb默认调试父进程,子进程的断点就不予理睬
在这里插入图片描述
设置gdb调试子进程,父进程的断点就不予理睬
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(gdb) set follow-fork-mode child
(gdb) show follow-fork-mode
Debugger response to a program call of fork or vfork is "child".
(gdb) l
1       #include <stdio.h>
2       #include <unistd.h>
3
4       int main() {
5
6           printf("begin\n");
7
8           if(fork() > 0) {
9
10              printf("我是父进程:pid = %d, ppid = %d\n", getpid(), getppid());
(gdb)
11
12              int i;
13              for(i = 0; i < 10; i++) {
14                  printf("i = %d\n", i);
15                  sleep(1);
16              }
17
18          } else {
19
20              printf("我是子进程:pid = %d, ppid = %d\n", getpid(), getppid());
(gdb)
21
22              int j;
23              for(j = 0; j < 10; j++) {
24                  printf("j = %d\n", j);
25                  sleep(1);
26              }
27
28          }
29
30          return 0;
(gdb) b 10
Breakpoint 1 at 0x7c8: file hello.c, line 10.
(gdb) b 20
Breakpoint 2 at 0x81e: file hello.c, line 20.
(gdb) ib
Undefined command: "ib".  Try "help".
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000007c8 in main at hello.c:10
2       breakpoint     keep y   0x000000000000081e in main at hello.c:20
(gdb) r
Starting program: /home/nowcoder/linux/lesson18/hello
begin
[New process 6569]
我是父进程:pid = 6565, ppid = 6551
i = 0
[Switching to process 6569]

Thread 2.1 "hello" hit Breakpoint 2, main () at hello.c:20
20              printf("我是子进程:pid = %d, ppid = %d\n", getpid(), getppid());
(gdb) i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
n
我是子进程:pid = 6569, ppid = 1
23              for(j = 0; j < 10; j++) {
(gdb) n
24                  printf("j = %d\n", j);
(gdb) n
j = 0
25                  sleep(1);
(gdb) n

(gdb) show detach-on-fork 
Whether gdb will detach the child of a fork is on.
(gdb) set detach-on-fork off
(gdb) show detach-on-fork 
Whether gdb will detach the child of a fork is off.
(gdb) l
1	#include <stdio.h>
2	#include <unistd.h>
3	
4	int main() {
5	
6	    printf("begin\n");
7	
8	    if(fork() > 0) {
9	
10	        printf("我是父进程:pid = %d, ppid = %d\n", getpid(), getppid());
(gdb) 
11	
12	        int i;
13	        for(i = 0; i < 10; i++) {
14	            printf("i = %d\n", i);
15	            sleep(1);
16	        }
17	
18	    } else {
19	
20	        printf("我是子进程:pid = %d, ppid = %d\n", getpid(), getppid());
(gdb) 
21	        
22	        int j;
23	        for(j = 0; j < 10; j++) {
24	            printf("j = %d\n", j);
25	            sleep(1);
26	        }
27	
28	    }
29	
30	    return 0;
(gdb) b 10
Breakpoint 1 at 0x120b: file hello.c, line 10.
(gdb) b 20
Breakpoint 2 at 0x1261: file hello.c, line 20.
(gdb) r
Starting program: /home/lq/C++/hello 
begin
[New inferior 2 (process 29767)]
Reading symbols from /home/lq/C++/hello...
Reading symbols from /usr/lib/debug/.build-id/18/78e6b475720c7c51969e69ab2d276fae6d1dee.debug...
Reading symbols from /usr/lib/debug/.build-id/45/87364908de169dec62ffa538170118c1c3a078.debug...

Thread 1.1 "hello" hit Breakpoint 1, main () at hello.c:10
10	        printf("我是父进程:pid = %d, ppid = %d\n", getpid(), getppid());
(gdb) n
我是父进程:pid = 29763, ppid = 29710
13	        for(i = 0; i < 10; i++) {
(gdb) n
14	            printf("i = %d\n", i);
(gdb) n
i = 0
15	            sleep(1);
(gdb) info inferiors 
  Num  Description       Executable        
* 1    process 29763     /home/lq/C++/hello 
  2    process 29767     /home/lq/C++/hello 
(gdb) inferior 2
[Switching to inferior 2 [process 29826] (/home/lq/C++/hello)]
[Switching to thread 2.1 (process 29826)]
#0  arch_fork (ctid=0x7ffff7fb4810)
    at ../sysdeps/unix/sysv/linux/arch-fork.h:49
49	../sysdeps/unix/sysv/linux/arch-fork.h: 没有那个文件或目录.
(gdb) n
53	in ../sysdeps/unix/sysv/linux/arch-fork.h
(gdb) n
__libc_fork () at ../sysdeps/nptl/fork.c:78
78	../sysdeps/nptl/fork.c: 没有那个文件或目录.
(gdb) n
83	in ../sysdeps/nptl/fork.c
(gdb) n
100	in ../sysdeps/nptl/fork.c
(gdb) n
102	in ../sysdeps/nptl/fork.c
(gdb) n
113	in ../sysdeps/nptl/fork.c
(gdb) n
126	in ../sysdeps/nptl/fork.c
(gdb) n
129	in ../sysdeps/nptl/fork.c
(gdb) n
main () at hello.c:8
8	    if(fork() > 0) {
(gdb) n

Thread 2.1 "hello" hit Breakpoint 2, main () at hello.c:20
20	        printf("我是子进程:pid = %d, ppid = %d\n", getpid(), getppid());
(gdb) n
我是子进程:pid = 29767, ppid = 29763
23	        for(j = 0; j < 10; j++) {
(gdb) n
24	            printf("j = %d\n", j);
(gdb) inf
inferior  info      
(gdb) inferior 1
[Switching to inferior 1 [process 29763] (/home/lq/C++/hello)]
[Switching to thread 1.1 (process 29763)]
#0  main () at hello.c:15
15	            sleep(1);
(gdb) info inferiors 
  Num  Description       Executable        
* 1    process 29763     /home/lq/C++/hello 
  2    process 29767     /home/lq/C++/hello 
(gdb) detach inferiors 2
Detaching from program: /home/lq/C++/hello, process 29767
[Inferior 2 (process 29767) detached]
j = 0
(gdb) j = 1
j = 2
j = 3
j = 4
j = 5
j = 6
j = 7
j = 8
j = 9
n
The program is not being run.
(gdb) n
The program is not being run.
(gdb) info inferiors 
  Num  Description       Executable        
  1    process 29763     /home/lq/C++/hello 
* 2    <null>            /home/lq/C++/hello 
(gdb) inferior 1
[Switching to inferior 1 [process 29763] (/home/lq/C++/hello)]
[Switching to thread 1.1 (process 29763)]
#0  main () at hello.c:15
15	            sleep(1);
(gdb) n
13	        for(i = 0; i < 10; i++) {
(gdb) 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值