当前位置: 首页 > news >正文

【Linux】详细介绍进程的概念

目录

一、初识进程概念

真正的进程概念如下:

二、Linux中PCB的操作系统学科叫法:task_struct

1、简单认识task_ struct内容分类

2、问题:操作系统怎么知道当前程序执行到哪一行代码了?

三、linux关于进程的常用指令:

1、ps axj

2、运行一个.c可执行文件

3、 ps ajx | head -1

4、man getpid

5、man getppid

6、每一次启动程序 , 当前进程的pid值都会变化

7、进程的当前工作目录:

8、函数chdir

四、初识fork:通过系统调用fork创建新进程

1、通过一段代码引出fork

2、fork的返回值

3、创建子进程的作用:

问题:上述代码中一个id变量怎么会即等于0,又大于0呐?


 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家

点击跳转到网站

一、初识进程概念

很多教材观点:

1、加载到内存的程序就叫进程;

2、正在运行的程序就叫进程;

但这些叙述是模模糊糊的,看着根本不明白进程到底是什么。下面我们逐步介绍:

事实上:程序会被编译成二进制文件,文件又是存在磁盘上,磁盘属于外设;

1、我们可以同时启动多个程序,将这多个程序加载到内存(通常是可执行程序.exe);

2、操作系统必须去管理这些加载到内存的程序,比如如何给这些程序分配内存。

3、操作系统是如何管理加载到内存的程序呐,就是我们上述所介绍的:先描述再组织。

第3点过程介绍,引出进程的概念:

操作系统刚开始将进程加载到内存的时候,它是不认识这些进程的,所以根据“先描述,后组织”,会去创建一个结构体去描述这些进程,然后把对应的属性填入结构体的成员,这样就认识了,这样操作系统就可以通过访问这些结构体间接去管理这些进程数据。

如下:

这个结构体被叫做PCB(process ctrl block:进程控制块),上述图中只是部分属性,实际中可能有几百种属性。因为我们以链表为例,所以这里是在成员中添加一个PCB的指针用于指向下一个结点,这样对进程的管理就转化为对PCB链表的增删查改,这个就是对进程的建模过程。

上述就是大致管理图,

真正的进程概念如下:

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

所有对进程的控制和操作,都只和进程的PCB有关,和进程的可执行程序没有关系,因为是通过访问PCB去间接管理可执行程序,我们上面只是以链表为例,实际PCB结构体可以用任意数据结构进行管理。

二、Linux中PCB的操作系统学科叫法:task_struct

1、简单认识task_ struct内容分类

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

2、问题:操作系统怎么知道当前程序执行到哪一行代码了?

这就是通过task_ struct的内容中程序计数器知道的。CPU中存在一个eip寄存器(也叫PC指针),实际上程序计数器就是PC指针,里面存的是当前正在执行的指令的下一条指令,那些判断、循环、函数跳转等等操作的本质就是修改PC指针,因为程序是从上往下执行的,而这些操作都会改变这个顺序,所以实际上修改的是PC指针。

三、linux关于进程的常用指令:

1、ps axj

这个指令用来查看所有进程:

2、运行一个.c可执行文件

 1 #include<stdio.h>2 #include<unistd.h>3 int main()4 {5     while(1)6     {7         printf("i am a process!\n");8         sleep(2);9     }10     return 0;11 }

如上,写了一个test。c文件,此时我们将它编译运行,如下:

此时这个程序就变成了一个进程,我们可以通过指令查看

3、 ps ajx | head -1

该指令用来显示当前系统中所有进程表头的详细信息。

但为了看见我们自己的,我们可以筛选一下,使用指令:

ps ajx | head -1 && ps ajx | grep myprocess

这样可以筛选包含myprocess关键词的内容:

这里会显示第二行内容是因为:几乎所有的独立的指令都是程序,运行起来也会变成进程,所以筛选的时候会把grep这个进程也筛选进来,如果不想看到,可以使用-v选项,反向筛选不包括grep关键词的:

ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep

4、man getpid

这个指令用来查看getpid这个函数的信息:getpid就是一个系统调用,用来查看当前进程的pid值,返回值pid_t类型相当于int

5、man getppid

首先我们要知道,一般在linux中,普通进程都会有父进程,而getppid就是用来查看当前进程的父进程的pid值,man指令就是用来查看这个函数的信息。

6、每一次启动程序 , 当前进程的pid值都会变化

每一次启动程序 , 当前进程的pid值都会变化,因为每次启动程序,都会是一个新进程。

但会发现父进程始终不会变。

所以我们可以看一下父进程10645是谁?使用如图指令后,发现是进程bash。

bash就是命令行解释器,所以我们命令行启动的进程都是bash的子进程。

7、进程的当前工作目录:

在文件操作中我们知道"fopen("file.txt","w");",如果不存在这个文件,就会在当前路径下帮我们创建这个文件。这里的当前路径我们以前都认为是该.c文件所在的路径,但实际上是当前可执行程序对应的进程的工作目录(cwd):

这里的cwd就是进程的当前路径,对应的下面还有exe程序对应的路径。

8、函数chdir

四、初识fork:通过系统调用fork创建新进程

1、通过一段代码引出fork

首先我们写一段测试代码:

  1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 int main()5 {6     printf("before fork:i am a prcess,pid:%d,ppid:%d\n",getpid(),getppid());7     pid_t id = fork();8     printf("after fork:i am a prcess,pid:%d,ppid:%d\n",getpid(),getppid());9     return 0;10 }                                                                                                                                                                       

运行结果如下:

我们会发现,我们代码中只有两个printf,但运行结果却打印了三行内容,原因就在于,当执行fork函数后,fork会创建子进程,所以此时会走两条分支,所以after的printf会打印两次,第一次打印的是父进程的内容,第二次打印的是子进程的内容,可以通过ppid看出打印顺序。

(所以可以这样理解,fork之后代码是父子进程共享的,相当于要执行两份代码)

2、fork的返回值

可以通过手册查看,发现fork的返回值如下:

如果创建失败,则返回-1;

如果创建成功,则给父进程返回子进程的pid,给子进程返回0;因为父进程可以有多个子进程,而子进程只有一个父进程,所以父进程找子进程是比较困难的,就需要一些标识符,比如这里pid。子找父是比较简单的,比如直接getppid。

3、创建子进程的作用:

一般情况,我们创建子进程是想让父子进程去做不同的事,这样的场景就可以通过一些判断语句,结合fork的返回值,就可以让父子进程做不同的事。

这段代码也是让我们第一次接触同时运行两个死循环。

创建子进程的时候,操作系统会给子进程创建一个PCB,默认情况会将父进程的大部分属性拷贝给子进程,只有一些用于标识的属性才和父进程不一样,比如pid和ppid。创建一个进程的时候,系统中就会多一个进程。

问题:上述代码中一个id变量怎么会即等于0,又大于0呐?

首先我们要知道,一个进程崩溃了,是不会影响其他进程的,也就是说进程之间是具有独立性的,并不是相互影响。我们可以通过指令去杀死对应进程。

相关文章:

  • 小白自学python第一天
  • Fabric.js 设置画布背景
  • AI在Java语言的发展方向与涉及领域——一场深度的求职面试
  • Spring AI - Redis缓存对话
  • 基于Flask与Ngrok实现Pycharm本地项目公网访问:从零部署
  • 开源模型应用落地-语音合成-Spark-TTS-零样本克隆与多语言生成的突破
  • 浏览器相关知识点
  • 【AI 加持下的 Python 编程实战 2_09】DIY 拓展:从扫雷小游戏开发再探问题分解与 AI 代码调试能力(上)
  • Joint communication and state sensing under logarithmic loss
  • iOS18 MSSBrowse闪退
  • Unity 创建、读取、改写Excel表格数据
  • 理解计算机系统_网络编程(1)
  • 自建开源远程协助服务RustDesk —— 筑梦之路
  • Axure中继器表格:实现复杂交互设计的利器
  • 【Bug】 [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
  • 【工具变量】各市ZF数字治理指标数据集(2001-2024年)
  • 大语言模型(LLM)的Prompt Engineering:从入门到精通
  • 同z科技面经
  • 2024从Maven-MySQL-Nginx部署
  • 【解决】layui layer的提示框,弹出框一闪而过的问题
  • 中国围棋协会将不组队参加今年的LG杯世界棋王赛
  • 旁白丨无罪后领到国家赔偿,一位退休教师卸下了“包袱”
  • 国家疾控局局长沈洪兵:将逐步缩小国内免疫规划与国际差距
  • 人民日报刊文:美国滥施关税及中国反制措施的法理视角透析
  • 平均25岁,天津茱莉亚管弦乐团进京上演青春版《春之祭》
  • 独家丨远洋渔船船长被害案嫌犯移送检方报捕,船上两段视频曝光