Linux 多进程(一) (2)

此返回值是条件判断父子进程的依据:

#include<stdio.h> #include<unistd.h> #include<errno.h> int main() { int res_form_fork,mypid; mypid = getpid(); printf("before id:%d\n",mypid); res_form_fork = fork(); sleep(1); //打印创建子进程前后的pid和fork返回值 print("after pid is:%d fork():%d\n",getpid(),res_form_fork); return 0; } /* 结果: root@ziggy-virtual-machine:~/unix_linux/chapter8# gcc -o forkdemo forkdemo.c root@ziggy-virtual-machine:~/unix_linux/chapter8# ./forkdemo before id:1291 after pid is:1291 fork():1292 after pid is:1292 fork():0 */

以下代码会有八行输出,也就是总共7个进程

//分别是父进程,子1,子2,子3,子1.1,子1.1.1,子2.2 #include<stdio.h> #include<unistd.h> #include<errno.h> int main() { printf("pid is:%d\n",getpid()); fork(); fork(); fork(); //打印创建子进程前后的pid和fork返回值 printf("pid is:%d\n",getpid()); return 0; }

区分父子进程:根据返回值判断

#include<stdio.h> #include<unistd.h> #include<errno.h> int main() { printf("before pid is:%d\n",getpid()); int res = fork(); if(res==-1) { printf("error\n"); } else if(res==0) { printf("child pid is:%d\n",getpid()); } else { printf("parent pid is:%d\n",getpid()); } return 0; } /* root@ziggy-virtual-machine:~/unix_linux/chapter8# ./forkdemo.3 before pid is:1680 child pid is:1680 parent pid is:1681 */

子进程的PPID被设置为父进程的PID

原进程设置的信号处理函数对新进程不再起作用

数据的复制是写时复制,只有任一进程对数执行了写操作,复制才会发生

父进程中打开的文件描述符在子进程中默认打开,且引用计数+1,且父进程的用户根目录,当前工作目录,的引用计数都+1

可以看Linux高性能服务器编程第13章第一部分

#include<stdio.h> #include<unistd.h> // #include<sys int main() { pid_t pid; pid = fork(); if(pid>0){//parent printf("pid:%d\n",pid);//子进程进程号 printf("i am parent process,pid:%d,ppid:%d\n",getpid(),getppid()); }else if(pid==0){ printf("i am parent process,pid:%d,ppid:%d\n",getpid(),getppid()); } for(int i = 0;i<5;i++) { printf("i:%d\n",i); } return 0; }

image

再看一看:ps aux进程的信息

image

上面表示,终端是一个进程,而程序是终端的子进程

父子进程是交替运行的(CPU分配时间片)

在没有添加for循环的时候,子进程getppid()得到的返回值为1。

原因是此时父进程被杀死,子进程被init进程领养,可以在for循环中将子进程的存活时间设置得比父进程长,分别在父进程被杀死前后查看ppid,可以观察到这一变化。

fork的返回值pid为局部变量在栈空间

父进程存储在栈空间的返回值pid为子进程id,子进程返回的pid为0

父子进程相同的地方:

内核区复制一份,但是pid不同,用户区数据相同

测试局部变量:测试父子进程都拥有number后,互相之间是否影响(子进程拷贝一份局部变量)

#include<stdio.h> #include<unistd.h> int main() { int num = 10; pid_t pid = fork(); if(pid>0) { printf("parent num:%d\n",num); printf("parent num address:%p\n",&num); }else if(pid==0){ num+=10; printf("child num:%d\n",num); printf("child num address:%p\n",&num); } return 0; }

image

两个num互不影响,虚拟地址空间相同,但是映射在物理空间地址就不一样了

linux系统下每个进程都拥有自己的页表,父进程fork出新的子进程时,子进程拷贝一份父进程的页表,且父子进程将页表状态修改为写保护。当父进程或子进程发生写操作时将会发生缺页异常,缺页异常处理函数将会为子进程分配新的物理地址。

栈空间数据读时父子进程共享一块物理内存,写时复制,开辟一块新的内存

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzzxgd.html