【Linux系统化学习】进程的父子关系 | fork 进程

=========================================================================

个人主页点击直达:小白不是程序媛

Linux专栏:Linux系统化学习

=========================================================================

目录

前言:

父子进程

父子进程的引入

查看父子进程

查询进程的动态目录

更改进程的工作目录

fork创建进程

fork的引入

fork的使用

fork的原理

fork如何实现的?

为什么fork之前的代码不执行?

为什么要有两个返回值?


前言:

上篇文章我们谈到了进程,运行在内存的程序、被执行的指令都可以是一个进程;并且对Linux的进程有一定的认识,知道如何使用指令查看进程和第一个系统调用。进程还有很多的奥秘需要我们探索,让我们开始今天的学习吧!


父子进程

父子进程的引入

还是上篇文章的代码和指令,每个进程都PID,在属性列表前面的PPID为父进程的ID。

我们对自己写的可执行程序进行多次的运行和终止,会发现每次的进程ID都会变 ,而父进程ID始终不变。

经过查询我们可以知道这个父进程就是我们的命令行解释器(bash)

总结:

  • 启动进程本质就是创建进程,一般是通过父进程创建的(父子关系)
  • 我们命令行启动的进程都是bash的子进程

查看父子进程

新的进程创建时操作系统会给每个进程创建一个task_struct(PCB) ,里面存放着关于这个进程的各种信息、属性等;其中就包括PID和PPID是操作系统内部的数据 ,操作系统那片文章我们提到用户是无法拿到操作系统内部的数据的要通过系统调用才可以,Linux也给我们提供了相应的函数接口供我们使用。

  • 获取子进程ID:getpid()
  • 获取父进程ID:getppid()

通过man指令可以查询到这两个函数的使用方法。

复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 
  5 {
  6     printf("我是一个进程,我的PID为:%d;我的PPID为:%d\n",getpid(),getppid());                                                                                                     
  7     return 0;
  8 }

通过编写代码,函数调用获取我们的ID和PPID。

查询进程的动态目录

Linux操作系统下有一个有一个动态的目录结构存放着所有进程;可以通过每个进程的PID查询到这个目录

  • 指令: proc/PID

我们将整个进程的完整目录调出来

更改进程的工作目录

我们可以使用chdir()修改当前工作目录

复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 
  5 {
  6     chdir("/root");                                                                   
  7     while(1)
  8     {
  9     printf("我是一个进程,我的PID为:%d;我的PPID为:%d\n",getpid(),getppid());
 10     sleep(1);
 11     }
 12     return 0;
 13 }

fork创建进程

fork的引入

在Linux操作系统下有两种创建进程的方式

  • 命令行中直接启动进程(手动启动)
  • 通过代码来创建进程**(fork)**

我们一直在使用第一种方式创建进程,下面将通过演示fork来创建进程。

fork的使用

man fork 查看fork如何使用

复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 
  5 {
  6     printf("我是一个进程,我的PID为:%d;我的PPID为:%d\n",getpid(),getppid());
  7     fork();
  8 
  9     printf("我是一个进程,我的PID为:%d;我的PPID为:%d\n",getpid(),getppid());
 10     sleep(1);                                                                         
 11     return 0;
 12 }

运行我们编译好的程序我们发现同一条输出语句运行了两次。这是因为在fork之前只有一个进程,fork创建了一个进程,所以才会执行两次。

fork的原理

fork如何实现的?

fork是一个函数,函数可以设置返回值;当fork子进程成功时给父进程返回子进程的PID,给子进程返回0;fork子进程失败时返回-1;子进程创建成功后会将fork下面的代码拷贝一份,相当有两个进程执行同一份代码,因此会输出两条语句。

复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 
  5 {
  6     pid_t id =fork();
  7     if(id<0)
  8     {
  9          return 0;
 10     }
 11     else if ( id == 0 )
 12     {
 13         while(1)
 14         {
 15             printf("我是子进程,我的Pid为:%d,我的PPid为:%d\n",getpid(),getppid());
 16         }
 17         sleep(1);
 18     }
 19     else                                                                              
 20     {
 21 
 22         while(1)
 23         {
 24             printf("我是父进程,我的Pid为:%d,我的PPid为:%d\n",getpid(),getppid());
 25         }
 26         sleep(1);
 27     }
 28     return 0;
 29 }

为什么fork之前的代码不执行?

在学习C语言的时候我们知道,代码执行的时候会有一个指针执行一条语句,指针就会随着变化;执行到fork时候,指针也变化到fork语句;因此只能将fork之后的语句拷贝给另一个进程。

为什么要有两个返回值?

这和我们用户使用计算机的场景有关,就像我现在在同一个浏览器里一边在CSDN写着博客,一边还在查找相关的资料。浏览器这一个进程含有两个进程,两个进程做着不同的事情,甚至更多。但是当前我们只能让做相同的事情,执行同一份代码。在以后的学习中我们会通过返回值让他们执行不同的代码片段。


今天对Linux下父子进程和fork进程的介绍分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法。您三连的支持就是我前进的动力,感谢大家的支持!!!

相关推荐
一位摩羯座DBA30 分钟前
Redhat&Centos挂载镜像
linux·运维·centos
学习3人组31 分钟前
CentOS配置网络
linux·网络·centos
计算机毕设定制辅导-无忧学长1 小时前
西门子 PLC 与 Modbus 集成:S7-1500 RTU/TCP 配置指南(一)
服务器·数据库·tcp/ip
weixin_307779131 小时前
Hive集群之间迁移的Linux Shell脚本
大数据·linux·hive·bash·迁移学习
漫步企鹅2 小时前
【蓝牙】Linux Qt4查看已经配对的蓝牙信息
linux·qt·蓝牙·配对
码荼2 小时前
学习开发之hashmap
java·python·学习·哈希算法·个人开发·小白学开发·不花钱不花时间crud
cui_win2 小时前
【网络】Linux 内核优化实战 - net.core.flow_limit_table_len
linux·运维·网络
梦在深巷、2 小时前
MySQL/MariaDB数据库主从复制之基于二进制日志的方式
linux·数据库·mysql·mariadb
风清再凯2 小时前
自动化工具ansible,以及playbook剧本
运维·自动化·ansible
深圳安锐科技有限公司2 小时前
深圳安锐科技发布国内首款4G 索力仪!让斜拉桥索力自动化监测更精准高效
运维·安全·自动化·自动化监测·人工监测·桥梁监测·索力监测