进程(一) 进程概念

文章目录

  • 什么是进程呢?
  • 描述进程-PCB
    • task_struct-PCB的一种
    • task_struct内容分类
  • 查看进程
    • 通过系统目录查看
    • 通过ps命令查看
    • 通过系统调用获取进程的PID和PPID
    • 通过系统调用创建进程- fork()函数
  • fork()函数
    • fork函数做了什么?
    • fork之后,父子进程谁先运行
    • fork函数的返回值:
    • 为什么fork会有两个返回值?
    • fork的两个返回值

什么是进程呢?

运行起来的程序吗?

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

对于我们所写的代码,在进行编译链接之后形成的.exe(可执行程序文件),这个可执行程序本质上是一个文件,是放在磁盘上的。当我们运行这个可执行程序时,本质上是将这个程序加载到内存当中了,因为只有加载到内存后,CPU才能对其进行逐行的语句执行,而一旦将这个程序加载到内存后,我们就不应该将这个程序再叫做程序了,严格意义上将应该将其称之为进程。

其实在我们的程序加载到内存之前操作系统早已经加载到内存中,而程序是操作系统将其进行加载拷贝到内存当中的。

描述进程-PCB

pcb全程为process control block
进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct。

我们知道在操作系统中会同时存在多个进程
在这里插入图片描述
那么操作系统如何管理呢?

结合前面的知识,我们知道 应该先描述,再组织。操作系统是用C语言写的,所以操作系统要想管理进程,那么就必须用C语言来描述进程,通过进程的各种重要属性来描述进程,我们很容易想到结构体。这么多进程,结构体里面可以放一些结构体指针将他们链接起来,那么对进程的管理就转变成了对链表的增删查改。

在这里插入图片描述

所以进程=可执行程序+内核数据结构(PCB)

task_struct-PCB的一种

在Linux中描述进程的结构体叫做task_struct。
task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

task_struct内容分类

task_struct就是Linux当中的进程控制块,task_struct当中主要包含以下信息:

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

查看进程

通过系统目录查看

根目录下有一个proc的系统文件夹。
在这里插入图片描述
文件夹当中包含大量进程信息,其中有些子目录的目录名为数字。
在这里插入图片描述
这些数字其实是某一进程的PID,对应文件夹当中记录着对应进程的各种信息。

通过ps命令查看

ps aux
在这里插入图片描述

通过系统调用获取进程的PID和PPID

通过使用系统调用函数,getpid和getppid即可分别获取进程的PID和PPID。
我们可以通过一段代码来进行测试。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{while(1){printf("我是一个进程,我的pid是: %d, ppid: %d\n", getpid(), getppid()); // 这个函数只调用了一次sleep(1); }retrun 0;
}

在这里插入图片描述
我们可以通过ps命令查看该进程的信息,即可发现通过ps命令得到的进程的PID和PPID与使用系统调用函数getpid和getppid所获取的值相同。

通过系统调用创建进程- fork()函数

fork函数创建子进程
fork是一个系统调用级别的函数,其功能就是创建一个子进程。
运行以下代码:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{fork();while(1){printf("我是一个进程,我的pid是: %d, ppid: %d\n", getpid(), getppid()); // 这个函数只调用了一次sleep(1); // for test}return 0;
}

在这里插入图片描述
运行结果是循环打印两行数据,第一行数据是该进程的PID和PPID,第二行数据是代码中fork函数创建的子进程的PID和PPID。我们可以发现fork函数创建的进程的PPID就是proc进程的PID,也就是说proc进程与fork函数创建的进程之间是父子关系。
每一个进程,操作系统就会为其创建PCB,fork函数创建的进程也是如此。

fork()函数

fork函数做了什么?

在这里插入图片描述

上面谈到父进程跟子进程会共享代码和数据,会执行相同的代码,那么fork之前的代码呢,子进程能看到吗?
答案是可以看到。
为什么子进程不从头开始执行呢?

因为我们的程序从上往下按照顺序去执行pc/eip寄存器执行fork完毕,eip指向的是fork后续的代码,而eip也会被子进程继承。所以只执行从fork之后的代码。

fork之后,父子进程谁先运行

创建完成子进程之后,系统的其他进程,父进程,子进程接下来是要被CPU调度执行的,当父子进程的PCB都被创建并在运行队列中排队的时候,哪一个进程先运行是不确定的,因为哪一个进程的PCB先被CPU选择调度,哪个进程就先运行,然后谁会先被调度是由各自PCB中的调度信息(比如说 时间片,优先级等)+调度器算法共同决定的,所以谁先运行是没有明确答案的。

fork函数的返回值:

1、如果子进程创建成功,在父进程中返回子进程的PID,而在子进程中返回0。
2、如果子进程创建失败,则在父进程中返回 -1。

既然父进程和子进程获取到fork函数的返回值不同,那么我们就可以据此来让父子进程执行不同的代码,从而做不同的事。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{printf("我是一个父进程,我的pid: %d\n", getpid());pid_t id = fork();// fork之后,用if进行分流if(id < 0) return 1;else if(id == 0){// childwhile(1){printf("我是子进程: pid: %d, ppid:%d, ret: %d, 我正在执行下载任务, &id: %p\n", getpid(), getppid(), id, &id);sleep(1);}}else{// parentwhile(1){printf("我是父进程: pid: %d, ppid:%d, ret: %d, 我正在执行播放任务, &id: %p\n", getpid(), getppid(), id, &id);sleep(1);}}
}

在这里插入图片描述
fork创建出子进程后,子进程会进入到 else if 语句的循环打印当中,而父进程会进入到 else 语句的循环打印当中。

为什么fork会有两个返回值?

Q:如果一个函数执行到了return语句,那么他的工作结束了吗?
A:是的,结束了。

子进程跟父进程代码和数据会共享,那么return之前,子进程已经被创建出来了,而return 语句也是代码,所以return 语句也会被子进程共享,所以父进程子进程被调度都会执行return 语句,从而造成了fork函数有两个返回值。

fork的两个返回值

Q:为什么fork的两个返回值,会给父进程返回子进程的pid,给子进程返回0呢?
在现实生活中一个爹可以对应多个子女,BUT儿子只能对应一个爹,需要管理子女所以需要得到子女的信息(也就是子进程的pid),而对于子女来说只需要管理好自己就可以(所以不需要得到任何信息,即返回0)

Q:如何理解同一个变量会有不同的值?
A:如果启动一个qq,启动微信,启动浏览器,kill掉微信,qq还在、浏览器还在
如果父子进程,父进程被杀掉,子进程还在吗?子进程被杀掉,父进程还在嘛? 答案是:还在
结合以上两点,我们可以推出,进程之间运行的时候是具有独立性的,

进程的独立性,首先是表现在有各自的PCB,进程之间不会相互影响 !而代码又是只读的,不会影响!但是数据父子进程是会修改的!代码共享,数据各个进程必须想办法各自私有一份。
但是一般如果不对数据进行写入的话,数据是不会发生拷贝的,只有当写入时,才会进行拷贝,也就是写时拷贝。
总上,我们得出了一个结论这个我们以为的同一个地址,一定不是简单的物理地址。

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

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

相关文章

centos 编译升级内核

一.离线编译并升级内核 1.下载内核 https://mirrors.ustc.edu.cn/centos-vault/7.9.2009/updates/Source/SPackages/ kernel-3.10.0-1160.105.1.el7.src.rpm 2.解压内核 &#xff08;1&#xff09;安装rpmrebuild yum install rpmrebuild&#xff1b; &#xff08;2&#xf…

Vue加载序列帧动图

解读方法 使用<img :src"currentFrame" alt"加载中" /> 加载图片动态更改src的值使用 requestAnimationFrame 定时更新在需要的页面调用封装的组件 <LoadToast v-if"showLoading" /> 封装组件 <template><div class"…

CTF CRYPTO 密码学-1

题目名称&#xff1a;enc 题目描述&#xff1a; 压缩包中含两个文件&#xff1a;一个秘钥d.dec&#xff0c;一个密文flag.enc 解题过程&#xff1a; Step1&#xff1a;这题是一个解密他题目&#xff0c;尝试openssl去ras解密 工具简介 在Kali Linux系统中&#xff0c;openss…

React16源码: React中的异步调度scheduler模块的源码实现

React Scheduler 1 ) 概述 react当中的异步调度&#xff0c;称为 React Scheduler发布成单独的一个 npm 包就叫做 scheduler这个包它做了什么&#xff1f; A. 首先它维护时间片B. 然后模拟 requestIdleCallback 这个API 因为现在浏览器的支持不是特别的多所以在浏览当中只是去…

【计算机图形学】习题课:Viewing

【计算机图形学】Viewing 部分问题与解答 CS100433 Computer Graphics Assignment 21 Proof the composed transformations defined in global coordinate frame is equivalent to the composed transformations defined in local coordinate frame but in different composing…

1月14-17日为技术测试期!字节与腾讯上演“大和解”,抖音全面开放《王者荣耀》直播

综合整理&#xff5c;TesterHome社区 来源&#xff5c;《王者荣耀》官方、界面新闻 北京商报、IT之家 1月13日&#xff0c;腾讯游戏《王者荣耀》官方微博发布消息宣布&#xff0c;从1月21日起&#xff0c;《王者荣耀》抖音直播将全面开放。 为了筛查开播期间可能遇到的所有技…

几何_直线方程 Ax + By + C = 0 的系数A,B,C几何含义是?

参考&#xff1a; 直线方程 Ax By C 0 的系数A&#xff0c;B&#xff0c;C有什么几何含义&#xff1f;_设直线 l 的方程为axbyc0 怎么理解-CSDN博客 1. A B的含义&#xff1a;组成一个与直线垂直的向量 我们先来看A和B有什么含义。 在直线上取任意两点 P1:&#xff08;x1…

OceanBase集群部署

我认为学习一个中间件比较好的方式是&#xff0c;先了解它的架构和运行原理&#xff0c;然后动手部署一遍&#xff0c;加深对它的了解&#xff0c;再使用它&#xff0c;最后进行总结和分享 本篇介绍OceanBase部署前提配置和集群部署 1.使用开源免费的社区版&#xff0c;企业版…

MetaGPT task1学习

基础知识学习了解&#xff1a; 安装环境&#xff1a; 获取MetaGPT 使用pip获取MetaGPT pip install -i https://pypi.tuna.tsinghua.edu.cn/simple metagpt0.5.2 配置MetaGPT 完成MetaGPT后&#xff0c;我们还需要完成一些配置才能开始使用这个强力的框架&#xff0c;包括配…

RHCE: web服务器+nfs服务器搭建

网站需求&#xff1a; 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! web服务器准备工作&#xff1a; #添加多ip(也可以用nmtui命令在图形界面配置) [root192 ~]# nmcli connection modify ens32 ipv4.method manual ipv4.…

[面试题~] Golang

1. 逃逸分析 1.1 逃逸分析是什么&#xff1f; 在编译原理中&#xff0c;分析指针动态范围的方法称之为逃逸分析。在Go中的表现是&#xff0c;如果一个对象的指针被多个方法或线程引用时&#xff0c;则称这个指针发生了逃逸。 所以&#xff0c;我认为逃逸分析指的是&#xff0…

[leetcode~数位动态规划] 2719. 统计整数数目 hard

给你两个数字字符串 num1 和 num2 &#xff0c;以及两个整数 max_sum 和 min_sum 。如果一个整数 x 满足以下条件&#xff0c;我们称它是一个好整数&#xff1a; num1 < x < num2 min_sum < digit_sum(x) < max_sum. 请你返回好整数的数目。答案可能很大&#xff…

极客时间-《左耳听风》文章笔记 + 个人思考

极客时间-《左耳听风》文章笔记 个人思考 分布式架构21 | 分布式系统架构的冰与火 分布式架构 21 | 分布式系统架构的冰与火 比较流行的高并发框架&#xff1a; Node.js&#xff1a;是一个基于Chrome V8引擎的JavaScript运行环境&#xff0c;它使用事件驱动、非阻塞I/O模型…

2024.1.17

今天我已经回家了&#xff0c;感觉家就像我的温柔乡一样&#xff0c;一到了家&#xff0c;就不想学习了&#xff0c;这是很不对的事情&#xff0c;不该如此堕落&#xff0c;还是要像在学校一样该干什么干什么&#xff0c;所以说还是复习和写了一下曾经写过的代码。 #define _C…

[Android] Android架构体系(1)

文章目录 Android 的框架Dalvik 虚拟机JNI原生二进制可执行文件Android NDK中的binutils Bionic谷歌考虑到的版权问题Bionic与传统的C标准库&#xff08;如glibc&#xff09;的一些不同 参考 Android 的框架 Android 取得成功的关键因素之一就是它丰富的框架集。 没有这些框架…

第2章 法律法规

文章目录 2.1.1 《电信条例》概述2.1.2 《电信条例》关于电信市场的规定1、电信业务许可规定2、电信资费规定3、电信资费规定 2.1.3《电信条例》关于电信服务的规定1、电信业务经营者的义务2、电信用户的相关义务3、电信用户申诉及受理的规定4、电信业务经营者不正当行为的规定…

架构08- 理解架构的模式2-管理和监控

大使模式&#xff1a;构建一个辅助服务&#xff0c;代表消费者使用服务或应用程序发送网络请求。 进程外的代理服务&#xff08;之前介绍中间件的时候也提到了&#xff0c;很多框架层面的事情可以以软件框架的形式寄宿在进程内&#xff0c;也可以以独立的代理形式做一个网络中…

AI绘图制作红包封面教程

注意&#xff1a;有不懂的话可加入QQ群聊一起交流&#xff1a;901944946欢迎大家关注微信公众号【程序猿代码之路】&#xff0c;每天都会不定时的发送一些红包封面&#xff01;&#xff01; 2024的春节即将到来&#xff0c;而在这春节到来之前&#xff0c;就有一个非常爆火的小…

黑马程序员 Java设计模式学习笔记(一)

目录 一、设计模式概述 1.1、23种设计模式有哪些&#xff1f; 1.2、软件设计模式的概念 1.3、学习设计模式的必要性 1.4、设计模式分类 二、UML图 2.1、类图概述 2.2、类图的作用 2.3、类图表示法 类的表示方式 类与类之间关系的表示方式 关联关系 聚合关系 组合…

陀螺仪LSM6DSV16X与AI集成(6)----检测自由落体

陀螺仪LSM6DSV16X与AI集成.6--检测自由落体 概述视频教学样品申请源码下载生成STM32CUBEMX串口配置IIC配置CS和SA0设置串口重定向参考程序初始换管脚获取ID复位操作BDU设置 概述 本文介绍如何初始化传感器并配置其参数&#xff0c;以便在检测到自由落体事件时发送通知。 最近…