【Linux】进程概念(2)(进程 操作系统管理进程 PCB(struct task_struct) 查看进程 进程的常见调用 系统调用 man getpid/getppid man fork)

本文主要是介绍【Linux】进程概念(2)(进程 操作系统管理进程 PCB(struct task_struct) 查看进程 进程的常见调用 系统调用 man getpid/getppid man fork),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 进程
    • 概念
  • 操作系统管理进程
    • PCB(struct task_struct)结构体
  • 查看进程
    • 另一种查看进程的方式:
  • 进程的常见调用
    • 系统调用
      • man getpid
      • man getppid
      • man fork


进程

概念

  • 课本概念:程序的一个执行实例,正在执行的程序等。
  • 内核观点:担当分配系统资源(CPU时间,内存)的实体。

一个运行起来(加载到内存)的程序 — 进程
在内存中的程序 — 进程
进程和程序相比,进程具有动态属性

操作系统管理进程

操作系统如何管理进程?

先描述再组织,要管理这些进程,操作系统首先将这些进程描述,所以就引出了一个叫做PCB的概念,

PCB(struct task_struct)结构体

在这里插入图片描述
操作系统为了管理进程,给PCB里面写上包含了进程的所有属性,理所当然,这里的属性有几百个,我们通过每个进程对应的ID来进行管理。进程控制块里面保存的是进程被创建时的所有属性,这些属性不在我们曾经的可执行程序里面,可执行程序里面只有我们的代码数据和逻辑。

struct task_struct
{//进程的所有属性//该进程对应的代码和属性地址struct task_struct *next;}

struct tack_struct *next包含了大堆的指针信息,对我们来讲,描述每一个进程都是一个task_struct

task_struct内容分类:

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器: 程序中即将被执行的下一条指令的地址。
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  • 其他信息

每一个程序加载进内存,每一个进程对应的代码和数据在加载的时候,操作系统要进行操作,然后就初始化完了一个task_struct结构体,

在这里插入图片描述

其中每一个进程都要做这个工作,所以在系统里面,除了加载进程到内存里,操作系统给每一个可执行程序匹配一个进程控制块,说白了就是task_struct所对应的结构体对象或者变,然后它们每一个都指向自己的代码,到这里就完成了先描述,然后再组织,操作系统把所有的进程的PCB,结构体对象链接起来,拿着process_header这个头,CPU要调度某个进程,操作系统就遍历所有进程的PCB,然后找到优先级最高的进程,比如说process_header指向的那个,然后把代码交给CPU,CPU就可以执行对应进程的代码了,若以后有一个进程想退出了,我们只需要确定PCB属性里面有没有一个进程的状态是死亡的,死亡的话操作系统遍历链表,把状态是死亡的节点找到,然后把对应的代码和数据释放掉,然后把PCB释放掉,此时这个进程就会释放了。
在这里插入图片描述

最后我们有了先描述再组织这样的理念,我们得出一个结论:**所谓的对进程管理,变成了对进程对应的PCB进行相关的管理。对进程管理本质不是对进程的可执行程序管理,而是对应的PCB结构做管理。
对进程管理——转化成立对链表的增删查

struct task_struct是一个内核结构体,是操作系统给我们提供的用来描述进程的结构体,当加载进程的时候会创建对应的内核对象task_struct 对象(内核变量),并且将结构和我们的代码和数据关联起来从而完成先描述再组织的工作。

  • 进程 = 内核数据结构(task_struct)+ 进程对应的磁盘代码

查看进程

-rw-rw-r-- 1 test_106 test_106   76 Nov 11 17:09 Makefile
-rwxrwxr-x 1 test_106 test_106 8408 Nov 11 17:16 myproc
-rw-rw-r-- 1 test_106 test_106  135 Nov 11 17:16 myproc.c

进程在运行,本质是进程读取代码,依次做执行,进程在被调度运行的时候,进程就具有动态属性。

[test_106@VM-4-13-centos 20221111]$ man getpid
[test_106@VM-4-13-centos 20221111]$ ps ajx | head -1 && ps axj | grep 'myproc'

另一种查看进程的方式:

一个进程每一次被启动,就意味着每一次被重新加载到内存,每一次被重新加载到内存就意味这操作系统每一次都要给这个进程创建task_struct,重新分配PID,所以PID不断变化。
在Linux当中有一个目录结构:proc,它是一个内存级的目录
[test_106@VM-4-13-centos 20221111]$ ls /proc/
在这里插入图片描述

我们可以看到有一些目录是以数字开头,其实那些数字就是对应进程的PID
在这里插入图片描述
在Linux下,一个进程可以被当做文件来看待,最后我们可以通过proc这个目录来查到对应的属性信息。
[test_106@VM-4-13-centos 20221111]$ ls /proc/5660 -d
在这里插入图片描述
进程一退出,目录就自动删除了。

一个进程被加载到内存,这个进程已经跑起来了,现在把它在磁盘中的二进制程序删了,请问进程还能不能正常运行?
结果是还能。
在这里插入图片描述

进程的常见调用

系统调用

man getpid

在这里插入图片描述

返回值pid_t是系统给我们封装的类型,其实就是整数。提供的接口,谁调用就返回调它进程的PID。

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>                                                                                                                             4 int main()5 {6   while(1)7   {8     printf("我是一个进程!,我的ID是:%d\n",getpid());9     sleep(1);10   }11   return 0;12 }

在这里插入图片描述
在这里插入图片描述
杀掉进程:kell -9 1193

man getppid

第一个p表示父,main getppid表示获取父进程ID,

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 int main()5 {6   while(1)7   {8     printf("我是一个进程!,我的ID是:%d,父进程的pid:%d\n",getpid(),getppid());                                                 9     sleep(1);                                                                                      10   }                                                                                                11   return 0;                                                                                        12 }  

在这里插入图片描述
关掉进程,再次打开,我们发现子进程一直在变,父进程pid不变化,我们查看:
[test_106@VM-4-13-centos 20221111]$ ps ajx | grep 7651

在这里插入图片描述

我们发现7651进程的PID叫做bash
命令行上启动的进程,一般它的父进程没有特殊情况的话,都是bash!

man fork

  • 运行 man fork 认识fork
  • fork有两个返回值
  • 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
    在这里插入图片描述
    创建子进程:fork - create a child process fork 是一个函数.
    函数执行前:只有一个父进程,函数执行后:父进程+子进程
  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 int main()5 {6   fork();7   printf("我是一个进程,pid:%d,ppid:%d\n",getpid(),gitppid());8   sleep(2);                                                                                                                     14   return 0;15 }  

在这里插入图片描述

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 int main()5 {6   pid_t id = fork();7   printf("我是一个进程,pid: %d ,ppid:%d,id: %d\n",getpid(),getppid(),id);                                                     8   sleep(2);                                                                                                                     14   return 0;                                                          15 } 

在这里插入图片描述
同一个变量id,在后续不会被修改的情况下,竟然有不同的内容!

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 int main()5 {6   pid_t id = fork();7   if(id == 0)8   {9     //子进程10     while(1)11     {13      printf("子进程,pid: %d ,ppid:%d,id: %d\n",getpid(),getppid(),id);14       sleep(1);15     }16   }17   else if(id > 0)18   {19     //parent20     while(1)21     {22 23       printf("父进程,pid: %d ,ppid:%d,id: %d\n",getpid(),getppid(),id);24          sleep(1);25     }26   }27   else{29   }                                                                                                                            37   return 0;38 }

在这里插入图片描述
创建出来了多进程,在C语言中if和else if不能同时条件成立,以前写的代码,两个死循环不能同时跑,证明fork之后会有父进程+子进程两个进程在执行后续代码,fork后续的代码,被父子进程共享。通过返回值不同,让父子进程执行后续共享的代码的一部分!

这篇关于【Linux】进程概念(2)(进程 操作系统管理进程 PCB(struct task_struct) 查看进程 进程的常见调用 系统调用 man getpid/getppid man fork)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/625750

相关文章

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

基于Linux的ffmpeg python的关键帧抽取

《基于Linux的ffmpegpython的关键帧抽取》本文主要介绍了基于Linux的ffmpegpython的关键帧抽取,实现以按帧或时间间隔抽取关键帧,文中通过示例代码介绍的非常详细,对大家的学... 目录1.FFmpeg的环境配置1) 创建一个虚拟环境envjavascript2) ffmpeg-py

python常见环境管理工具超全解析

《python常见环境管理工具超全解析》在Python开发中,管理多个项目及其依赖项通常是一个挑战,下面:本文主要介绍python常见环境管理工具的相关资料,文中通过代码介绍的非常详细,需要的朋友... 目录1. conda2. pip3. uvuv 工具自动创建和管理环境的特点4. setup.py5.

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

Windows的CMD窗口如何查看并杀死nginx进程

《Windows的CMD窗口如何查看并杀死nginx进程》:本文主要介绍Windows的CMD窗口如何查看并杀死nginx进程问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows的CMD窗口查看并杀死nginx进程开启nginx查看nginx进程停止nginx服务

Linux链表操作方式

《Linux链表操作方式》:本文主要介绍Linux链表操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、链表基础概念与内核链表优势二、内核链表结构与宏解析三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势六、典型应用场景七、调试技巧与

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

详解Linux中常见环境变量的特点与设置

《详解Linux中常见环境变量的特点与设置》环境变量是操作系统和用户设置的一些动态键值对,为运行的程序提供配置信息,理解环境变量对于系统管理、软件开发都很重要,下面小编就为大家详细介绍一下吧... 目录前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变