【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

相关文章

Linux线程同步/互斥过程详解

《Linux线程同步/互斥过程详解》文章讲解多线程并发访问导致竞态条件,需通过互斥锁、原子操作和条件变量实现线程安全与同步,分析死锁条件及避免方法,并介绍RAII封装技术提升资源管理效率... 目录01. 资源共享问题1.1 多线程并发访问1.2 临界区与临界资源1.3 锁的引入02. 多线程案例2.1 为

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

在macOS上安装jenv管理JDK版本的详细步骤

《在macOS上安装jenv管理JDK版本的详细步骤》jEnv是一个命令行工具,正如它的官网所宣称的那样,它是来让你忘记怎么配置JAVA_HOME环境变量的神队友,:本文主要介绍在macOS上安装... 目录前言安装 jenv添加 JDK 版本到 jenv切换 JDK 版本总结前言China编程在开发 Java

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

Spring Boot Actuator应用监控与管理的详细步骤

《SpringBootActuator应用监控与管理的详细步骤》SpringBootActuator是SpringBoot的监控工具,提供健康检查、性能指标、日志管理等核心功能,支持自定义和扩展端... 目录一、 Spring Boot Actuator 概述二、 集成 Spring Boot Actuat

Linux下在线安装启动VNC教程

《Linux下在线安装启动VNC教程》本文指导在CentOS7上在线安装VNC,包含安装、配置密码、启动/停止、清理重启步骤及注意事项,强调需安装VNC桌面以避免黑屏,并解决端口冲突和目录权限问题... 目录描述安装VNC安装 VNC 桌面可能遇到的问题总结描js述linux中的VNC就类似于Window

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin