进程概述
当下常见 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)