进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程

这篇具有很好参考价值的文章主要介绍了进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

 在讲进程之前首先就是需要去回顾一下我们之前学的操作系统是干嘛的,首先操作系统是一个软件,它是对上提供一个良好高效,稳定的环境的,这是相对于用户来说的,对下是为了进行更好的软硬件管理的,所以操作系统是一个进行软硬件管理的软件。

实际上我们的硬盘,键盘和显示器这些是我们的硬件,但是操作系统是不能直接对我们的硬件进行控制,所以操作系统和我们的硬件中还有一层就是我们的驱动程序,那还有就是我们的用户是不能直接对我们的操作系统进行访问的,都会通过系统调用的方式来对我们的操作系统进行访问,这些都是我们来学习今天文章内容的前言部分,那下面开始我们对进程内容的了解。

进程的概念

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

进程简单点来了解我们可以就认为它就是一个可执行的程序,也就是磁盘里的文件,然后进行运行起来,那我们在学C语言的时候都知道我们的可执行文件先是在磁盘里的,我们运行的时候,是要把磁盘文件加载到内存当中的,然后我们的内存里存的是这个可执行文件的数据,也就是代码加上数据。

但是被加载到内存当中的程序对进程的描述是不完整的,下面我来画张图,也就能方便大家来了解进程了。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

先描述再组织

操作系统中里面可能一下子加载了很多的进程,就像我们的任务管理器是一样的,当我们打开任务管理器的时候我们就不难发现可以存在很多个进程,所以操作系统里面如果有大量的进程也是很正常的。所以讲一个程序加载到内存的时候,不仅仅是要把代码和数据加载到内存当中,同时也会产生一个结构体我们叫他为PCB(process control block),好像是叫这个。反正它是一个结构体,里面存放的是这个进程的属性加上下一个PCB结构体的指针,还有就是一个内存指针,指向的就是我们的内存里的代码和数据。

看下面的这个图

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

所以操作系统对进程的管理最后就是对链表的增删查改

最后就是我们讲了这么多,进程其实就是  

进程 == PCB结构体 + 代码和数据

这里也就是符合我们讲的先描述(结构体) 再组织(链表)

这里再给大家加个餐,我们之前说操作系统其实就是一款对软硬件进行管理的软件,我们也可以认为操作系统再我们电脑开机的时候也是存放在我们的磁盘当中的,我们认为它就是一个二进制的文件。

所以开机的时候我们发现我们的电脑不是马上开机的,而是等待一会然后进行开机的,那么这几秒的时间就是把操作系统的这个软件的数据拷贝到内存当中去的,然后我们的操作系统就会根据我们的进程来进行malloc出PCB的结构体,有几个进程就malloc几个PCB出来,最后再进行链接。

所以操作系统对进程的管理不是对我们的可执行程序进行管理,而是对我们的结构体PCB进行管理的

  

系统的接口

操作系统如果是想给我们提供服务的话,我们用户是不能直接对我们的操作系统进行访问的,原因呢就是如果我们改动我们操作系统中的数据和一些数据结构的化,我们的操作系统就不能给我们用户提供很好的服务,就比如操作系统其实就是我们的银行,如果我们要去存钱或者取钱的时候,难道银行是直接把小金库暴露给我们吗,我们是直接用银行电脑给我们的余额加上5个0的吗,那这样不就乱套了吗,所以我们如果想要访问我们的操作系统的时候,我们就需要利用好我们的系统调用接口或者标准库来对我们的操作系统进行访问,如果我们直接对操作系统进行访问的化就和我们直接去抢银行是没有区别的。

 进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

简单点我们就可以这样认为这个是操作系统的内核

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

总结:我们操作系统要运行我们的进程的时候,这个排队的过程就是让我们的PCB结构体进行排队,而不是内存中的代码和数据进行排队。

 理解一个概念:什么是动态运行?

我么可以理解为PCB在不同的队列中,进程就可以访问不同的空间。

进程的查看

引入话题

在我们考上大学的时候,我们的大学(监狱,不想上学)都会给新生一个编号

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器 也就是我们的学号,我们每个人都是有一个不一样的学号,那么进程也是这个样子的,所以我们需要了解的就是进程的标识符我们可以称作为pid。

pid : 在每一个进程中,都会存在唯一的标识符也就是我pid

我们可用用指令来查看进程的pid

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

这是一个Makefile里面写的代码,还有一个就是我们.c文件里写的代码,我们在我们的右边重新开一个,方便我们进行观察,这样我们的代码就跑起来,这个时候就是一个进程在跑,我们在左边可以执行指令来进行查看。

 ps ajx | head -1  && ps ajx | grep myprocess | grep -v grep
 

 grep -v grep 是不查看该条指令的进程,因为我们的指令其实就是一个可执行的文件,也是一个进程,所以执行这个就可以屏蔽该进程。

我们都知道,我们的代码在进行预处理,编译,汇编,还有链接之后就会形成可执行文件,我们可以用指令开查看我们的文件是不是可执行文件。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

file之和发现它是一个可执行的文件。

通过proc目录来查看进程信息

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

在 / 下的路径下有一个proc,我们也可以在这个里面来查看进程。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

我们上面引进的pid就可以用上了,pid是我们进程的唯一标识符,认识函数getpid,通过man手册进行查询

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器 这是获取pid的函数,我们上面的指令也可以查看pid

 ps ajx | head -1  && ps ajx | grep myprocess | grep -v grep

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

当我们进程在跑的时候,上面的这个pid也就是我们进程的标识符,我们也可以在代码里获取pid,来改写一下代码。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器 这里大家可能是会有疑问的,因为我上面的进程pid已经进行改变了,这是为什么呢???

因为我们每次执行我们的代码的时候,它就是创建出一个进程,所以pid当然是不一样的。

我们这个时候也就可以在proc的目录下查看一些到底是不是存在这个进程呢。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

proc下也是真的有这个目录的(哇,真的是你啊(好大声)) 。

我们也可以查看一些他们的属性,加上 -al就可以来看看细节了。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

我们只需要关注图中画红的部分就可以了。exe其实就是可执行文件,因为这些文件都是该进程下的,我们知道我们的进程 == 代码和数据 + 内核的数据结构,每个进程都有相对于的task_struct

也就是我们之前讲的PCB,PCB里是有它的属性的,这个是我们知道,所以exe相当于告知该进程对应的磁盘上哪个是可执行文件,也就是对应的磁盘文件。

那cwd就是当前的工作路径,这个和我们的pwd是同一个路径。

做个小实验

现在我们就来改改我们的代码,我们在C语言的时候是讲过fopen函数的时候,如果我们是以写的方式打开的化,没有这个文件的时候也是会创建出新的文件出来的,而且是在当前工作路径下创建的,我们可以来看看代码应该怎么进行修改呢,

 进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

我们的代码进行这样子修改后发现在当前的路径下也是创建出来新的文件了,所以cwd就是指的当前的工作的路径。

获取父进程的pid

前面也是讲过我们是如何获得进程的pid,但是我们也有办法来获得它的父进程的pid在执行下面的进程的时候,我们看到的ppid就父进程的pid

 ps ajx | head -1  && ps ajx | grep myprocess | grep -v grep

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

那也是有办法来查看我们的ppid,就是函数getppid,用man手册进行查询来看看。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

这个就是我们来查询ppid的函数,直接来尝试怎么使用。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

我们就可以查询到我们的父进程的pid,而且发现父进程每次重新启动的时候都是不变的,。 

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

发现每次的子进程的pid是改变了,但是父进程的pid是没有进行改变的

这是为什么呢,我们来尝试看看它的父进程是怎么个事。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

竟然就是我们的bash进程,那我们是不是可以猜测很多父进程的父进程他们都是-bash

答案是的 ,他们都是-bash的子进程

使用fork()函数创建子进程

fork函数就是专门创建子进程而生的!!!!!

我们可以用man手册进行查询。

FORK(2)                         Linux Programmer's Manual                        FORK(2)

NAME
       fork - create a child process

SYNOPSIS
       #include <unistd.h>

       pid_t fork(void);

DESCRIPTION
       fork()  creates  a  new  process  by  duplicating  the  calling process.  The new
       process, referred to as the child, is an exact duplicate of the calling  process,
       referred to as the parent, except for the following points:

       *  The child has its own unique process ID, and this PID does not match the ID of
          any existing process group (setpgid(2)).

       *  The child's parent process ID is the same as the parent's process ID.

       *  The child does not inherit its parent's memory locks (mlock(2), mlockall(2)).

       *  Process resource utilizations (getrusage(2)) and CPU time counters  (times(2))
          are reset to zero in the child.

       *  The child's set of pending signals is initially empty (sigpending(2)).

       *  The child does not inherit semaphore adjustments from its parent (semop(2)).

       *  The child does not inherit record locks from its parent (fcntl(2)).

       *  The  child  does  not  inherit timers from its parent (setitimer(2), alarm(2),
          timer_create(2)).

       *  The child does not inherit outstanding asynchronous I/O  operations  from  its
          parent  (aio_read(3),  aio_write(3)), nor does it inherit any asynchronous I/O
          contexts from its parent (see io_setup(2)).

       The process attributes in the preceding list are all specified  in  POSIX.1-2001.
       The  parent  and  child  also differ with respect to the following Linux-specific
 Manual page fork(2) line 1 (press h for help or q to quit)

凑个子树哈哈哈哈哈哈。

我们可以看到引入的头文件就是unistd这个头文件。

我们可以往下看,发现fork的返回值是有两个返回值的,这个意味着我们有两个返回值(好像什么都没说),我们可以在在代码里看看它是怎么返回两个值的,首先就是他们fork后面创建出子进程之和他们的代码是共享的(包括return0)

我们先写一个代码来看看到底是怎么实现的,

 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <unistd.h>
  4 //int main()
  5 //{
  6 //  while(1)
  7 //  {
  8 //    printf("I am process : pid %d  ppid %d\n",getpid(),getppid());
  9 //    sleep(1);
 10 //  }
 11 //}
 12 //
 13 //
 14 int main()
 15 {
 16   fork();
 17   printf("hello students\n");                                                          
 18 }
~

我们来看看效果是怎么样的呢。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

我去,竟然是打印了两次,那就更能确定一点的就是我们这里是存在连个进程的,不信我们可以使用查看进程的指令来看看,但是因为这个代码是一下子就结束了,那么我们的进程也被kill,所以我们是无法查看的,那在写一个其他的代码。

 进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器

代码

int main()
 21 {
 22   printf("I am process\n");
 23   sleep(3);
 24   pid_t p = fork();
 25   if(p ==0)
 26   {
 27     //child
 28     while(1)
 29     {
 30       printf("I am child process pid %d  ppid %d\n",getpid(),getppid());
 31       sleep(1);                                                                        
 32     }
 33   }
 34   else
 35   {
 36 
 37     while(1)
 38     {
 39       printf("I am parent process pid %d  ppid %d\n",getpid(),getppid());
 40       sleep(1);
 41     }
 42 
 43   }
 44 
 45   
 46 }

我们看效果和代码发现为什么它能有两个返回值,又能进行if的语句,也能执行fork的语句,如果单单是从语言角度去看的化就不是这个样子的,所以我们应该是来看fork函数,fork函数就是创建子进程的,我们可以理解为fork之后的代码是共享的,因为我们每个函数包括是main函数也是有返回值的,所i有有两个返回值,那返回值为0的时候就是child,如果返回值是>0的时候就是paernt的进程,这样的化就会产生两个进程。所以会产生的进程就是两个。

那么我们还有个问题就是fork函数之后,我们的操作系统是做了什么呢。

我们知道进程的组成就是task_struct +进程的代码和数据

我们可以认为子进程是继承了父进程的代码和数据的,但是还是要强调的是我们代码是继承的,但是数据得独立,这样也就能造成为什么我们的返回值是两个的原因。代码共享就会导致一定有两个返回值。

今天的分享就到这里了。我们下次再见。

进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程,linux,运维,服务器文章来源地址https://www.toymoban.com/news/detail-841802.html

到了这里,关于进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《Linux操作系统编程》 第六章 Linux中的进程监控: fork函数的使用,以及父子进程间的关系,掌握exec系列函数

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月11日
    浏览(37)
  • Linux 学习之路 - 进程篇 - PCB介绍1-标识符

    目录 一、基础的命令 1 ps axj 命令 2 top 命令 3 proc 目录 二、进程的标识符 1范围 2如何获取标识符 3bash进程 三、创建进程 前面介绍了那么多,但是我们没有观察到进程相关状态,所以下面我们介绍几个命令,帮助查看进程 1 ps axj 命令 这个命令就能查看当前所有进程相关信息

    2024年04月09日
    浏览(55)
  • 《ARM Linux内核源码剖析》读书笔记——0号进程(init_task)的创建时机

    最近在读《ARM Linux内核源码剖析》,一直没有看到0号进程(init_task进程)在哪里创建的。直到看到下面这篇文章才发现书中漏掉了set_task_stack_end_magic(init_task)这行代码。 下面这篇文章提到:start_kernel()上来就会运行 set_task_stack_end_magic(init_task)创建初始进程。init_task是静态定义的

    2024年01月17日
    浏览(67)
  • 一探Linux下的七大进程状态

    本篇博客全站热榜最高排名:6 Hello,大家好,本文我们所要介绍的是有关Linux下的进程状态 在上一文中,我们重点介绍了有关 Linux下进程的基本概念,了解了什么是进程、怎么去描述并组织进程、创建一个进程。 在本文中,我们将先通过了解操作系统学科下的进程状态,对

    2024年02月13日
    浏览(35)
  • 【Linux笔记】Linux进程概念与进程状态

    进程的概念: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序

    2024年02月06日
    浏览(48)
  • 【Linux进程篇】进程概念(1)

    作者:爱写代码的刚子 时间:2023.7.30 前言:操作系统和软硬件的关系就相当于管理者和被管理者的关系,管理者并不需要见到被管理者,通过执行者拿到对应数据,通过对数据的管理来达到管理的目的。==对软硬件的管理最后一定会变成对某种数据结构的增删查改。==本篇博

    2024年02月14日
    浏览(51)
  • 【Linux】进程概念与进程状态

    在通常的计算机书籍或者课本中对进程概念的描述是这样的 – 进程就是被加载到内存中的程序,或者被运行起来的程序就叫做进程 ;这样说的原因如下: 首先,从 【Linux】计算机的软硬件体系结构 中我们知道,为了提高计算机的整体效率,在数据层面,CPU 不会直接和外设

    2024年02月02日
    浏览(44)
  • Linux下的系统编程——进程间的通信(九)

    前言:  前面我们已经对进程已经有了一个简单的了解与认识,那么进程间的通信是什么样的呢,什么是父子进程,什么是兄弟进程,没有血缘关系间的进程是如何实现进程通信的,下面让我们一起学习一下什么是进程间的通信吧。 目录 一、进程间通信常用方式 IPC方式:

    2024年02月09日
    浏览(34)
  • Linux下的系统编程——进程的执行与回收(八)

    前言: 前面我们对进程已经有了一个初步的了解与认识,现在让我们学习一下进程中一些函数的具体使用,比如exec可以执行一些指定的程序,wait / waitpid可以回收子进程,什么是孤儿进程,什么是僵尸进程,下面让我们一起对这些进行中的操作进行学习吧 目录 一、exec函数族

    2024年02月09日
    浏览(48)
  • 【Linux】进程学习(1)---理解进程概念

    数学家冯·诺依曼提出了计算机制造的三个基本原则,即采用二进制逻辑、程序存储执行以及计算机由五个部分组成(运算器、控制器、存储器、输入设备、输出设备),这套理论被称为冯·诺依曼体系结构。我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大

    2023年04月25日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包