Linux:进程概念详解

进程概念详解

一、进程的基本概念

进程在书本上的定义是:计算机中正在运行的程序实例。仅此描述可能让很多人感到困惑。

我们磁盘上存储着.exe文件,启动文件时,文件会从磁盘加载到内存,由CPU对文件的数据和代码进行运算。但进程并非仅仅是数据和代码。

 在计算机中有许许多多个应用程序在指向,有些程序可能是新执行进来的,有些程序可能是执行完了将要结束,可能还有些程序需要阻塞等待。有这么多种程序也有这么多种情况,那么操作系统是需要对这些程序进行管理,但又应该怎么管理呢?

计算机中有众多应用程序,它们的执行情况各不相同,操作系统需要对这些程序进行管理。每个程序都有各种属性,如代码地址、数据地址和最重要的ID(用来标识进程的唯一标识符)。操作系统将这些属性通过struct整合,用来描述一个应用程序当前的状态,并且每个struct都有一个next指针指向下一个整合属性,从而将对进程的管理转化为对链表的管理。我们把每一个struct都称之为内核数据结构对

因此,进程 = 内核数据结构对象 + 数据和代码。

二、认识进程

  进程的计算机业里统称为Process Control Block(PCB).

PCB通常包含以下内容

  • 进程状态:如就绪、运行、阻塞等。
  • 进程ID:用来表示进程唯一性的标识符。
  • 程序计数器:指示进程下一条指令的地址。
  • CPU寄存器:保存进程在执行过程中使用的寄存器内容。
  • 内存管理信息:如进程的地址空间、页表等。
  • 调度信息:包括优先级、调度队列等信息。

在Linux中,PCB具体指的是task_struct,以下是其部分源代码

struct task_struct {volatile long state;  // 进程状态struct thread_info *thread_info;  // 指向线程信息的指针struct mm_struct *mm;  // 进程的内存描述符struct files_struct *files;  // 进程打开的文件描述符struct fs_struct *fs;  // 进程的文件系统信息struct signal_struct *signal;  // 信号处理相关struct sighand_struct *sighand;  // 信号处理程序struct task_struct *parent;  // 父进程struct list_head children;  // 子进程链表struct list_head sibling;  // 同级兄弟进程链表pid_t pid;  // 进程标识符pid_t tgid;  // 线程组标识符(线程的主线程)int exit_state;  // 进程退出状态unsigned long flags;  // 标记进程状态的标志位unsigned int prio;  // 进程优先级unsigned int static_prio;  // 静态优先级unsigned int normal_prio;  // 正常优先级unsigned int rt_priority;  // 实时优先级struct sched_entity se;  // 调度实体struct mm_struct *active_mm;  // 活动的内存描述符// 其他许多字段...};

三、查看进程信息

(一)通过系统调用函数获取

getpid函数是一个系统调用函数,用于获取当前进程的进程ID(PID,Process ID)。

例如,我们可以在Linux中编写一个简单的死循环输出打印的程序,执行程序后,再打开一个Linux窗口,使用ps ajx | head -1 && ps axj |grep mycode命令显示当前系统中运行的进程信息。可以看到循环中输出的pid值与显示的pid值正好对应。

(二)通过/proc系统文件查看

我们还可以通过/proc系统文件查看进程信息。例如,使用ll /proc/9430 -1命令查看当前进程包含的内容,其中exe指的是当前进程对应的可执行文件,cwd表示当前进程运行所处的文件的绝对路径。这也解释了为什么通过fopen函数创建文件时,如果不带上绝对路径,文件就会在当前路径下创建。

此外,在使用ps ajx命令时,除了显示PID还有一个PPID,PPID是当前进程的父进程ID。我们可以通过调用getppid()函数查看当前进程的PPID。

通过上图运行可以看到,我们一直运行mycode的文件时,它的PID是依次递增的,但一直不变的是PPID。那mycode的PPID又是谁呢?

        通过上图运行可以看到,我们一直运行mycode的文件时,它的PID是依次递增的,但一直不变的是PPID。那mycode的PPID又是谁呢?

        通过ps ajx命令观察到,PID为8729的进程所代表的名称为 bash。

        那么 Bash 在Linux中是一个命令行解释器,用于解释用户输入的各种命令比如ls,pwd等。从中不难得出一个结论:我们历史上所执行的指令,工具,以及自己编写的程序,只要运行起来就都是进程。

四、创建子进程

在Linux中,有一个系统调用接口fork()用于创建子进程。

fork函数创建子进程后,子进程将继承父进程的代码,并且子进程将拥有一个唯一的进程ID。fork函数的返回值为pid_tpid_t其实是被typedef过的int

(一)fork()函数的使用示例

分析上图代码,一开始我们输出当前进程的PID和PPID,接着通过fork进行创建子进程后再次打印PID和PPID,我们会发现此时除了第一条打印的语句我们理解,还多了一条打印的语句。并且观察PID,会发现PID为 19215 的PPID正是一开始打印的PID 19214,那么就能够证明了fork会创建子进程,并且子进程会继承父进程fork()之后的代码,所以会打印两句输出语句。

调用fork()创建子进程后,返回值id会根据是父进程还是子进程进行区分:子进程返回的id为0,父进程返回的id是子进程的PID。

那这里可能就会产生一些疑惑。1.为什么fork给父进程返回的是子进程的PID,而子进程返回0。 2.为什么一个 fork() 函数会返回两次。 3.为什么一个id变量,即==0,又满足>0,if else if 同时成立。

(二)fork()函数的返回值及原因分析

问题1:

对于为什么fork给父进程返回的是子进程的PID,而子进程返回0。这是因为在所有进程就类似于一个进程树。

对于父进程来说,我需要知道我的子进程PID是什么,以进行区分因为一个父进程可以有多个子进程。 对于子进程来说,我没有子进程,只需要返回0即可。那可能会有疑惑,那我子进程是怎么找到父进程的呢?其实在之前的代码就可以知道,是有一个系统调用接口 getppid() 就可以知道自己的父进程是谁。 

所以对于父子进程来说,是一个 1:n 之间的关系。

 问题2:

为什么一个 fork() 函数会返回两次呢?其实这个问题也很好理解

那么在fork函数内会申请新的pcb,malloc一块新的空间给子进程以及拷贝父进程pcb,那么此时子进程已经创建,就会和父进程一起执行代码,到最后返回pid。所以并不是一个函数返回两次,而是有两个进程在执行同一段代码,子进程返回0,父进程返回子进程的pid。

        问题3:

                为什么一个id变量,即==0,又满足>0,if else if 同时成立。在讨论这个问题之前,我们先想一下,我此时同时打开了抖音以及微信,如果微信崩了,会不会影响抖音?显然是不会的,那么就可以得出一个结论,进程是具有独立性的

父进程创建子进程后,两个进程同时指向一份代码,但这部分代码是只读的。如果父子任何一方,对数据进行修改,那么操作系统会把被修改的数据在底层拷贝一份,让目标进程修改这份拷贝。这种操作称之为写时拷贝

(三)实验验证进程的独立性和写时拷贝

         gval是一个全局变量,父子进程都可以看到,当我们fork之后,子进程会开始对gval值进行修改,而父进程只对gval值进行查看。并且通过运行代码很明显能看到,子进程修改了gval值后,父进程的gval值并没有发生改变,这更加证明了父子进程之间是相互独立,并且如果父子一方对数据进行修改并不会影响到另一方。

                                                                        那么本片文章到这里就结束了,感谢各位观看!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/18447.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

04性能监控与调优篇(D1_学习前言)

目录 一、引言 二、基本介绍 三、JVM基础 1. java堆 2. 垃圾回收 3. STW 四、调优层次 五、调优指标 六、JVM调优原则 1. 优先原则 2. 堆设置 3. 垃圾回收器设置 1> GC 发展阶段 2> G1的适用场景 3> 其他收集器适⽤场景 4. 年轻代设置 5. 年⽼代设置 …

系统思考—慢就是快

“所有成长,都是一个缓慢渗透的过程,回头看,才发现自己已经走了很远。” —— 余秋雨 这让我想起一个最近做的项目。和一家公司合作,他们的管理模式一直陷入困境,员工积极性低,领导层的决策效率也不高。刚…

String常量池(2)

大家好,今天我们继续学习String常量池,昨天我们已经做了一个介绍,相信大家✓String常量池有了一定了解,那么就来看看它的应用。 字符串常量地(String Table). 字常量她在IVM中是StringTable类,实际是一个固定大小的 HashTable(一…

LabVIEW显微镜成像偏差校准

在高精度显微镜成像中,用户常常需要通过点击图像的不同位置,让电机驱动探针移动到指定点进行观察。然而,在实际操作中,经常会遇到一个问题:当点击位于图像中心附近的点时,探针能够相对准确地定位&#xff1…

Typora“使用”教程

文章目录 零、Typora简介一、下载并安装Typora二、修改License文件三、每次启动第一个Typora时,总弹出Activate窗口四、去除软件左下角未Activate提示五、参考文章 零、Typora简介 Typora 是一款由 Abner Lee 开发的轻量级 Markdown 编辑器,与其他 Mark…

【scikit-multiflow】使用 scikit-multiflow 的流数据生成器生成概念漂移数据流

说在前面 scikit-multiflow 是一个专注于多流学习(multi-stream learning)的Python库,它为数据流挖掘和在线学习提供了丰富的工具集。这个库的设计灵感来源于著名的scikit-learn,旨在为研究人员和从业者提供一个易于使用且功能强…

计算机视觉-局部特征

一、局部特征 1.1全景拼接 先用RANSAC估计出变换,就可以拼接两张图片 ①提取特征 ②匹配特征 ③拼接图像 1.2 点的特征 怎么找到对应点?(才能做点对应关系RANSAC) :特征检测 我们希望找到的点具有的特征有什么特…

matlab下载安装图文教程

【matlab介绍】 MATLAB是一款由美国MathWorks公司开发的专业计算软件,主要应用于数值计算、可视化程序设计、交互式程序设计等高科技计算环境。以下是关于MATLAB的简要介绍: MATLAB是MATrix LABoratory(矩阵实验室)的缩写&#…

Whisper+T5-translate实现python实时语音翻译

1.首先下载模型,加载模型 import torch import numpy as np import webrtcvad import pyaudio import queue import threading from datetime import datetime from faster_whisper import WhisperModel from transformers import AutoTokenizer, AutoModelForSeq2…

Python微博动态爬虫

本文是刘金路的《语言数据获取与分析基础》第十章的扩展,详细解释了如何利用Python进行微博爬虫,爬虫内容包括微博指定帖子的一级评论、评论时间、用户名、id、地区、点赞数。 整个过程十分明了,就是用户利用代码模拟Ajax请求,发…

爬虫实战:利用代理ip爬取推特网站数据

引言 亮数据-网络IP代理及全网数据一站式服务商屡获殊荣的代理网络、强大的数据挖掘工具和现成可用的数据集。亮数据:网络数据平台领航者https://www.bright.cn/?promoRESIYEAR50/?utm_sourcebrand&utm_campaignbrnd-mkt_cn_csdn_yingjie202502 在跨境电商、社…

2.认识标签和去标签|下载boost库|建立项目结构

下载Boost库 Boost C Libraries 选择右边的Documentation 选择最新的1.87.0版本 可以在首页的这里下载最新版本 建立项目结构 新建目录boost_searcher mkdir boost_searcher移动到boost_searcher目录 cd boost_searcher下载rz命令 yum install lrzsz导入boost文件&…

Transformer 模型介绍(三)——自注意力机制 Self-Attention

Transformer 模型由 Vaswani 等人于2017年提出,主要应用于序列到序列的任务,最初应用于机器翻译。其核心思想是通过自注意力机制捕捉序列中的长期依赖关系,从而有效地进行任务建模 在著名的论文《Attention Is All You Need》中,…

《AI大模型开发笔记》Open-R1:对 DeepSeek-R1 的完全开源再现(翻译)

Open-R1:对 DeepSeek-R1 的完全开源再现(翻译) 原文链接:https://huggingface.co/blog/open-r1 什么是 DeepSeek-R1? 如果你曾经为一道艰难的数学题苦思冥想,那么你就知道花更多时间、仔细推理是多么有用…

Java虚拟机面试题:JVM调优

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

每日Attention学习23——KAN-Block

模块出处 [SPL 25] [link] [code] KAN See In the Dark 模块名称 Kolmogorov-Arnold Network Block (KAN-Block) 模块作用 用于vision的KAN结构 模块结构 模块代码 import torch import torch.nn as nn import torch.nn.functional as F import mathclass Swish(nn.Module)…

Centos安装php-8.0.24.tar

查看系统环境 cat /etc/redhat-release 预先安装必要的依赖 yum install -y \ wget \ gcc \ gcc-c \ autoconf \ automake \ libtool \ make \ libxml2 \ libxml2-devel \ openssl \ openssl-devel \ sqlite-devel yum update 1、下载解压 cd /data/ wget https:/…

百度千帆平台对接DeepSeek官方文档

目录 第一步:注册账号,开通千帆服务 第二步:创建应用,获取调用秘钥 第三步:调用模型,开启AI对话 方式一:通过API直接调用 方式二:使用SDK快速调用 方式三:在千帆大模…

linux-shell脚本

shell的编码语法 shell脚本的第一行内容是: #!/bin/bash,这句话相当于是一个导包语句,将shell的执行环境引入进去了。 shell中变量的命名要求: 只能使用数字、字母和下划线,且不能以数字开头 变量赋值是通过"&q…

免费deepseek的API获取教程及将API接入word或WPS中

免费deepseek的API获取教程: 1 https://cloud.siliconflow.cn/中注册时填写邀请码:GAejkK6X即可获取2000 万 Tokens; 2 按照图中步骤进行操作 将API接入word或WPS中 1 打开一个word,文件-选项-自定义功能区-勾选开发工具-左侧的信任中心-信任中心设置…