Linux 操作系统 进程(1)

news2024/9/21 16:36:36

什么是进程

想要了解什么是进程,或者说,为什么会有进程这个概念,我们就需要去了解现代计算机的设计框架(冯·诺依曼体系):

计算机从设计之初就以执行程序为核心任务,也就是运算器从内存中读取,也只从内存中读取,输入设备也只能输入到内存中。在早期计算机系统中,计算机一次只能运行一个程序,所有资源都被这个程序独占。随着需求的增加,计算机需要能够同时运行多个任务,比如一个任务处理文件读写,另一个任务计算数据。这时,系统需要一种机制来管理多个程序的执行,确保它们能够公平、有效地利用计算机的资源,这就是进程概念产生的原因。

进程的定义

进程是操作系统中执行程序的一个实例,它包含了程序运行所需的所有信息和资源。简单来说,进程就是操作系统为运行中的程序提供的一个执行环境,包括程序代码、数据、打开的文件、内存空间和处理器时间等。一个程序在操作系统中可能运行多个实例,每个实例就是一个独立的进程。

每个进程通常包含以下几个部分:

  • 可执行程序代码:程序的二进制指令。
  • 进程的内存空间:包括堆、栈、数据段等。
  • 进程状态信息:CPU寄存器、程序计数器等,记录当前进程执行的具体状态。
  • 调度信息:操作系统需要的信息,用来决定何时执行该进程。

这些也就是计算机或者说是操作系统用来描述每一个需要执行的程序的方法,在linux里,描述程序的结构体叫做 task_struct  也叫做PCB  Process Control Block,进程控制块)PCB是一个概念,task_struct则是在linux里PCB的具体表现。

struct task_struct {
	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
	struct thread_info *thread_info;
	atomic_t usage;
	unsigned long flags;	/* per process flags, defined below */
	unsigned long ptrace;

	int lock_depth;		/* Lock depth */

	int prio, static_prio;
	struct list_head run_list;
	prio_array_t *array;
}

这是在  linux-2.6.11.1 截取的task_struct 片段,通过这个片段,我们可以看到操作系统用来描述进程信息的部分属性。

  • state 表示进程的当前状态(可运行、不可运行等)。
  • usage 是引用计数,记录进程被使用的次数。
  • priostatic_prio 是进程的优先级,用于调度。
  • run_list 用于将进程挂入运行队列,array 管理进程的优先级队列。
struct list_head {
	struct list_head *next, *prev;
};

 而这里链接进程进入运行队列的结构就是这个结构体,

通过上篇博客(不同结构体之间的链接-CSDN博客)的字节运算从而获得每一个结构体的成员。

为什么需要进程?

引入进程的核心原因在于多任务处理资源管理。现代计算机需要同时运行多个任务,而进程是管理这些任务的一种机制。进程可以:

  1. 隔离任务:每个进程运行在自己的内存空间中,避免相互影响。这种隔离性提高了系统的安全性和稳定性。
  2. 资源管理:操作系统通过进程来分配 CPU、内存和I/O设备等资源,确保每个进程都能公平地使用系统资源。
  3. 并发执行:通过多任务调度,操作系统可以在一个 CPU 上快速切换进程,使得多个进程看似同时执行,提升系统的利用效率。

进程的出现,使得操作系统能够高效管理多个任务,并为每个任务提供独立、受保护的执行环境。

查看进程 

在window操作系统中,由于图形化的原因,我们可以通过任务管理器更加方便直接的看到当前计算机正在运行的进程,同时我们还可以看到他的基本信息,那么在Linux系统中,我们该如何查看进程呢 ? 

我们可以直接在 /proc/ 文件夹里查看进程

这些蓝色的数字就是进程的PID (唯一标识符) ,如果我们想要查进程信息,同样可以进入文件夹内查看

大多数进程信息同样可以使用top和ps这些用户级工具来获取

我们可以写一个一直循环的进程用来使用ps查询

#include <stdio.h>
#include <unistd.h>

int main()
{
    while (1)
    {
        sleep(5);  // 暂停 5 秒
        printf("mypid: %d\n");  
    }

    return 0;
}

为什么有两个呢,因为作为查询任务的 grep 也是一个进程 ,同样,我们也可以使用系统接口,在程序内获取进程PID 和父进程的PID (PPID) 

每一次我们执行程序,进程PID都是改变的 

top命令大多数情况下都是用在进程优先级上,我们在优先级那里在回顾top的使用

 创建进程

在系统给出的系统调用接口中,也有创建子进程的相关函数,那就是 fork()

 fork() 函数是 Unix 和 Linux 系统中用于创建新进程的系统调用。它是进程控制的一部分,用于实现多任务处理。fork() 在调用时会创建一个新的进程,这个新进程是调用进程的一个副本,称为子进程

  • 创建新进程fork() 会复制调用进程的所有属性,创建一个新的进程。
  • 返回值
    • 在父进程中,fork() 返回新创建的子进程的 PID。
    • 在子进程中,fork() 返回 0
    • 如果 fork() 失败,它会返回 -1,并设置 errno 以指示错误原因。

 我们通常使用 if 来分流父进程与子进程

#include<stdio.h>    
#include<unistd.h>    
    
int main()    
{    
    pid_t id = fork();    
    
    if(id==0) //子进程    
    {    
        int i = 5;    
        while(i--)    
        {    
            printf("我是子进程 pid : %d, ppid : %d\n",getpid(),getppid());        
            sleep(1);    
        }    
    }    
    else if(id>0)    
    {    
        int i=7;    
        while(i--)    
        {    
            printf("我是父进程 pid: %d,ppid: %d\n",getpid(),getpid());        
            sleep(1);                              
        }    
    }    
    else    
    {    
        perror("进程创建失败\n");    
    }    
    
    return 0;    
}

 fork()函数

 上述代码,我们可以看出来,我们创建了一个子进程,但是,在以往我们学习C语言的经验里,一个程序里,一个值怎么进入两个完全不同的if判断呢,那我们最直观的想法就是,父进程跟子进程使用的数据并不是用一个甚至并没有在一起

在fork()官访问当中,我们可以看到

内存空间的独立性

  1. 进程复制

    • 当调用 fork() 时,操作系统会创建一个新的进程(子进程),这个子进程是父进程的一个副本。在内存中,这意味着子进程会有一份与父进程相同的内存内容,包括代码、数据、堆栈等。
  2. 独立的内存空间

    • 虽然父进程和子进程在 fork() 时内存内容是相同的,但它们的内存空间是独立的。每个进程在其自己的地址空间中操作,因此一个进程的内存更改不会直接影响到另一个进程的内存。
  3. 写时复制(Copy-on-Write)

    • 在现代操作系统中,fork() 采用了一种优化机制叫做写时复制(Copy-on-Write)。最初,父进程和子进程共享相同的物理内存页,只有当其中一个进程试图修改这些内存页时,操作系统才会复制这些页,确保每个进程拥有自己的副本。这种机制减少了 fork() 操作的开销。

子进程与父进程的分流

当我们了解 fork()函数后,了解了fork()函数之后的代码是子进程与父进程共有的,当子进程要修改某一个变量的值时,系统才会给子进程拷贝一份这个值,并开辟空间给其进行修改,那我们是不是可以通过取地址  id 的地址来获得子进程存放数据的地址呢?

#include<stdio.h>    
#include<unistd.h>    
    
int main()    
{    
    pid_t id = fork();    
    
    if(id==0) //子进程    
    {    
        printf("%p\n",&id);                                                                                                                                         
    }    
    else if(id>0)    
    {    
        printf("%p\n",&id);    
    }    
    else    
    {    
        perror("进程创建失败\n");    
    }    
    
    return 0;    
}  

我们惊奇的发现,两个id的地址竟然是一样的,那我们之前的拷贝的id在哪里,同一个地址给出的id值竟然会不一样 ! 其实这是操作系统包含内存的设计,如果让我们的程序简简单单就可以访问到物理地址,那么操作系统很容易就崩溃了。对与每一个进程,或者说是每一个程序,操作系统都平等分配一个虚拟地址空间,通过这个虚拟地址空间跟页表映射到真实的物理地址,那么也就是说,这两个id不同的是物理地址。

 

当fork函数返回时,对id进行了写时拷贝,子程序的页表重新映射到操作系统存放的新id的物理地址(简图)

当子进程被创建时,PCB等内容被填充,父子进程指向相同的代码,同时,父子进程都有了属于自己的task_struct,可以被操作系统调度并执行了,同时由于,直接拷贝导致消耗过大,也就有了,修改数据时分配空间同时让子进程的页表指向该空间从而获得不同的数据。页表的设计,将虚拟地址跟物理地址连接到一起并且让内存单独维护内存,进程单独维护进程,保护数据的同时,解耦两部分。 

ps: Linux 源码下载  Index of /pub/linux/kernel/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

24款奔驰CLE升级原厂360全景影像效果怎么样

24款奔驰 CLE 轿跑&#xff1a;全景视野&#xff0c;驾驭无忧 24款奔驰 CLE 轿跑&#xff0c;以其优雅的线条和卓越的性能&#xff0c;成为道路上的一道亮丽风景。而升级原厂 360 全景影像&#xff0c;将为您的驾驶增添更多安全与便利。 原厂 360 全景影像的升级&#xff0c;…

算法分享——《双指针》

文章目录 ✅[《移动零》](https://leetcode.cn/problems/move-zeroes/)&#x1f339;题目描述&#xff1a;&#x1f697;代码实现&#xff1a;&#x1f634;代码解析&#xff1a; ✅[《复写零》](https://leetcode.cn/problems/duplicate-zeros/)&#x1f339;题目描述&#xf…

心觉:潜意识是一个免费的“超级工作狂”,你居然不会用

我们常听说&#xff1a;潜意识的力量是意识到3万倍以上 你信吗 估计很多人不相信&#xff0c;不相信当然用不好 不相信的原因核心有两个&#xff1a; 没有体验过 寻求绝对的科学验证 这两个原因会让你对潜意识不相信&#xff0c;或者半信半疑 今天我也不会给你绝对的科学…

基于 Unet-MobileNet 网络实现的腹部肝脏语义分割

1、MobileUnet 网络 Unet是一种卷积神经网络&#xff08;CNN&#xff09;架构&#xff0c;通常用于图像分割任务 Unet架构由编码器和解码器组成。编码器负责捕获上下文并从输入图像中提取特征&#xff0c;而解码器负责上采样并生成分割掩模。 Unet中的编码器由多个卷积层组成…

汽车免拆诊断案例 | 捷豹 E-type怠速不稳定

故障现象 一辆3.8E型直列6缸的捷豹&#xff0c;该车的故障原因表现为怠速不稳定&#xff0c;转速不均匀&#xff0c;以及在节气门全开&#xff08;WOT工况&#xff09;时“回火”和加速踏板不能及时提速。这是该车型一个值得关注的典型案例。车主表示&#xff0c;几年前&#…

Python条形码生成

条形码基础知识 在开始编码之前&#xff0c;让我们先了解一下条形码的基本概念。条形码本质上是一种将数据编码成可视模式的方法&#xff0c;通常由一系列平行的黑色条和白色空格组成。常见的条形码类型包括&#xff1a; UPC&#xff08;通用产品代码&#xff09; EAN&#x…

828华为云征文|华为云Flexus X实例部署k3s与kuboard图形化管理工具

828华为云征文&#xff5c;华为云Flexus X实例部署k3s与kuboard图形化管理工具 华为云最近正在举办828 B2B企业节&#xff0c;Flexus X实例的促销力度非常大&#xff0c;特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求&#xff0c;一定…

数据结构(邓俊辉)学习笔记】排序 6——希尔排序:框架 + 实例

文章目录 1. 策略2.实例3.循秩访问4. 插入排序5.Shell序列 1. 策略 来学习一种非常别致的排序算法&#xff0c;也就是希尔排序。 希尔排序算法既有着悠久的历史&#xff0c;同时也仍然不失活力。该算法的别致之处在于&#xff0c;它不再是将输入视作为一个一维的序列&#x…

SpringTest框架JUnit单元测试用例获取ApplicationContext实例的方法

JUnit单元测试用例中使用Spring框架&#xff0c;之前我的使用方式很直接。 /*** 用于需要用到Spring的测试用例基类* * author lihzh* alia OneCoder* blog http://www.coderli.com*/ RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(locations { "/sprin…

七. 部署YOLOv8检测器-deploy-yolov8-basic

目录 前言0. 简述1. 案例运行2. 补充说明3. 代码分析3.1 main.cpp3.2 trt_detector.hpp3.2 trt_detector.cpp 4. INT8量化前瞻总结下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程…

【车载开发系列】ParaSoft入门介绍

【车载开发系列】ParaSoft入门介绍 【车载开发系列】ParaSoft入门介绍 【车载开发系列】ParaSoft入门介绍一. ParaSoft的背景二. 设计理念三. ParaSoft C/CTest简介四. 具备常用功能1&#xff09;静态代码分析2&#xff09;代码覆盖率分析3&#xff09;模糊测试4&#xff09;自…

协议的认识和理解

目录 1. 协议 1.1. 站在日常生活的角度初始协议 1.2. 网络分层结构 (OS vs 网络) 1.2.1. 软件分层 1.2.2. 网络分层 1.3. 站在语言的角度理解协议 1. 协议 对于协议&#xff0c;我们可以用一句话概括它&#xff1a;协议本质上就是一种约定。 1.1. 站在日常生活的角度初始…

由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(四)

概述 在 WWDC 24 中,苹果推出了数据库框架 SwiftData 2.0,并为其加入了全新的 History Trace、“墓碑”等诸多激动人心的新功能。那么它们到底如何实际应用到我们的 App 中去呢? 想搞清楚历史记录追踪(History Trace)如何在 SwiftData 2.0 中大放异彩吗?看这篇就对了! …

压缩文件隐写

1、伪加密 &#xff08;1&#xff09;zip伪加密 考点&#xff1a;winhex打开压缩包&#xff1b;搜索504b0102(注意不是文件头部&#xff1b;zip文件头部伪504b0304);从50开始&#xff0c;往后面数第9&#xff0c;10个字符为加密字符&#xff0c;将其设置为0000即可变为无加密状…

攻防世界--->获取

做题笔记。 下载 查壳 64ida打开 main函数&#xff1a; 查找字符&#xff1a; 根据程序逻辑&#xff0c;创建了一个新文件并且进行了写入。 直接Linux上动调一下。 SharifCTF{b70c59275fcfa8aebf2d5911223c6589}

python安装以及访问openAI API

安装python 我是python小白&#xff0c;所以需要一步一步来&#xff0c;先安装。 一口吃不成胖子&#xff0c;记住。 从官网下载python&#xff0c;目前最新版本是3.12&#xff0c;但是据说稳定版3.11更好一点&#xff0c;所以&#xff0c;下载3.11&#xff0c;注意不要下载…

Hiredis的使用

Hiredis的使用 &#x1f4f8;这里安利一个github仓库介绍 图片生成 Socialify 一键生成专业 GitHub 仓库简介图 一、Hiredis的安装与使用 1、下载hiredis软件包&#xff0c; https://github.com/redis/hiredis.git 或者使用git下载到本地 git clone https://github.com/redi…

Camtasia 2024破解版注册机包含激活码秘钥

&#x1f3ac; 嗨&#xff0c;亲爱的朋友们&#xff01;今天我要给你们安利一款超级炫酷的屏幕录制和视频编辑软件——Camtasia 2024&#xff01;&#x1f389; camtasia2024绿色免费安装包winmac下载&#xff0c;点击链接即可保存。 https://pan.quark.cn/s/5ee0c4655701 C…

vite+vue3+typescript+elementPlus前端实现电子证书查询系统

实现背景&#xff1a;之前电子证书的实现是后端实现的&#xff0c;主要采用GD库技术&#xff0c;在底图上添加文字水印和图片水印实现的。这里采用前端技术实现电子证书的呈现以及点击证书下载&#xff0c;优点是&#xff1a;后端给前端传递的是一组数据&#xff0c;不需要传证…

假期学习-- iOS runloop了解和使用

iOS runloop的总结和理解 https://juejin.cn/post/7167497134294433829?searchId202408060922235E28560E3792F91107ED runloop的概念和数据结构 一般情况下&#xff0c;程序&#xff08;或者说线程&#xff09;在执行完毕后会立即退出或销毁&#xff1b;&#xff0c;但如果对…