浅谈Linux进程概念

在探讨进程概念这个内容之前,必须先对冯诺依曼体系结构以及操作系统这俩个概念做一个简单的了解和认识。

1.冯诺依曼体系结构

  冯诺依曼体系结构是绝大多数现代计算机的硬件体系结构,其认为现代计算机应该包含如下图所示的五大硬件体系结构。
在这里插入图片描述

  1. 输入设备:作用是将原始的数据和处理这些数据的程序送入计算机,键盘即典型的输入设备之一。
  2. 输出设备:将计算结果转化为用户或设备所能识别或者接收的信息形式,如打印机输出和显示器输出等。
  3. 存储器:计算机为了完成存储程序和存储数据的功能,则出现了可以存储信息的存储器,内存便是存储器的典型代表。
  4. 运算器:运算器是进行算术运算和逻辑运算的部件。
  5. 控制器:控制器是计算机的指挥中心,是发布命令的“决策机构”,要完成协调和指挥整个计算机系统的操作。控制器的主要功能是产生计算机的全部操作控制信号,对取指令、分析指令和执行指令的操作过程进行控制。运算器+控制器=中央处理器(CPU)。

冯诺依曼体系结构的俩大特点:

  1. 二进制:所有的数据都是按照二进制的方式进行存储。
  2. 内存存储:所有的数据都是由存储器设备进行存储的。

2.操作系统

2.1什么是操作系统

  操作系统其实也是一款软件,是安装在计算机上的一个程序。操作系统包括内核(进程管理+内存管理+文件管理+驱动管理…)以及其他程序(外部应用)。
  操作系统可以实现与硬件的交互,管理所有的软硬件资源,且为用户程序提供了一个良好的执行环境。在整个计算机软硬件架构中,操作系统的定位是:一款纯正的“搞管理”的软件

2.2操作系统如何进行软硬件的管理

  刚才说操作系统是一款管理所有的软硬件的软件,那么其到底是怎么管理的呢?很简单,举个例子,比如学校的管理体系,可简单看成是校长–>院领导–>辅导员–>学生这样的管理体系。那么,以学生为例,学校把学生的信息录入学籍,将学生描述了起来,再通过学籍管理系统组织起来。此后,如果某学生的信息发生改变,只需要改变关于他的描述信息(学籍)即完成了对该学生的管理。
  而操作系统也是这样,总的来说,就是通过描述+组织的方式来进行管理。
  操作系统管理硬件的方式为:先用struct结构体将硬件描述起来,再用链表或者其他高效的数据结构将它们组织起来,而下面要说的进程同理。

计算机的层次结构:
在这里插入图片描述

3.进程概念

3.1什么是进程

  • 从户用层面上来看,进程就是一个运行中的程序

  • 而从操作系统的角度来看,进程则是描述一个程序运行过程的描述信息,也就是下面要说的进程控制块-PCB。在linux中,PCB就是一个名为task_stauct的结构体。

3.2进程控制块-PCB

  PCB(process control block),也叫进程控制块,linux中进程信息被放在这样一个叫进程控制块的数据结构中,可以理解为属性的集合。Linux下描述进程的结构体叫做task_struct,这个结构体在内核中的sched.h头文件中。路径为/usr/src/kernels/3.10.0-1062.18.1.el7.x86_64/include/linux(kernels下为内核版本,每个人可能不同)。

task_ struct内容分类

  1. 标示符: 描述本进程的唯一标示符,用来区别其他进程。
  2. 状态: 任务状态,退出代码,退出信号等。
  3. 优先级: 相对于其他进程的优先级。
  4. 程序计数器: 程序中即将被执行的下一条指令的地址。
  5. 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
  6. 上下文数据: 进程执行时处理器的寄存器中的数据。让操作系统调度切换一个进程继续运行时能接着切换之前的位置继续运行,继续处理之前没有处理完成的数据。
  7. I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  8. 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  9. 其他信息

3.3查看进程

ls /proc命令:
在这里插入图片描述
/proc这个文件夹中保存着系统中所有的进程信息,以进程号命(PID)名,如要查看具体的进程,则再/proc/之后跟具体的进程号即可,如

ls /proc/1 //查看进程号为1的进程信息

ps aux命令:
查看进程的具体状态信息,常与grep搭配使用,来查看某一个进程的状态信息。
在这里插入图片描述
其中第二列即为当前进程的进程号,即进程PID

ps -ef命令:
与ps aux 类似,也是查看进程的一些相关信息,只不过内容略有区别。
在这里插入图片描述
其中第二列和第三列的内容分别表示当前进程的PID和当前进程父进程的PID。

top命令:
在这里插入图片描述

3.4进程状态

  为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。进程状态用于描述操作系统应该去如何处理进程,描述一个进程什么时候能够干什么,是否能被CPU调度运行等。
  通过观察内核中关于进程状态的源码,我们可以知道linux中总共有如下几种进程状态:

/*
 * The task state array is a strange "bitmap" of
 * reasons to sleep. Thus "running" is zero, and
 * you can test for combinations of others with
 * simple bit tests.
*/
static const char * const task_state_array[] = {
	"R (running)", /* 0 */
	"S (sleeping)", /* 1 */
	"D (disk sleep)", /* 2 */
	"T (stopped)", /* 4 */
	"t (tracing stop)", /* 8 */
	"X (dead)", /* 16 */
	"Z (zombie)", /* 32 */
};
  • R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
  • D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
  • 僵尸状态(zombie):僵尸进程就处于僵尸状态,下方详解。

3.5僵尸进程

概念及产生原因:子进程先于父进程退出,但父进程没有关注子进程的退出状态,导致资源没有被完全释放,此时子进程进入僵尸状态,同时子进程也成为了僵尸进程。

通过以下代码和相关命令进行查看和验证

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

int main()
{
	pid_t pid = fork(); //创建子进程
	if (pid < 0) {
		perror("fork");
		return -1;
	}
	else if (pid == 0) {
		//子进程
		printf("I'm child,pid is %d\n", getpid());
		exit(0); //子进程先退出
	}
	else {
		//父进程
		sleep(20);
		printf("I'm father,pid is %d\n", getpid());
	}

	return 0;
}

启动俩个终端,一个终端运行当前程序,另一个终端通过ps aux命令查看进程信息:
在这里插入图片描述
在这里插入图片描述
可以看出,进程号为29444的子进程成为了一个僵尸进程。

僵尸进程的危害:
产生资源泄露,僵尸进程的PCB未被释放,可能会导致正常的进程无法运行。

3.6孤儿进程

孤儿进程:父进程先于子进程退出,子进程就会成为孤儿进程。
特性:让出终端,子进程进入系统后台运行,其父进程成为1号进程,孤儿进程会被1号进程领养。

通过以下代码和相关命令进行查看和验证

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

int main()
{
	pid_t pid = fork();
	if (pid < 0) {
		perror("fork");
		return -1;
	}
	else if (pid == 0) {
		//child
		while (1) {
			sleep(1);
		}
		printf("I'm child,pid is %d\n", getpid());
	}
	else {
		//parent                                                                                                    
		sleep(20);
		printf("I'm parent,pid is %d\n", getpid());
		exit(0);
	}
	return 0;
}

运行程序,注意父子进程的PID:
在这里插入图片描述

父进程会在20秒中后先于子进程退出,在父进程退出前使用ps-ef查看进程信息:
在这里插入图片描述
父进程退出后再次ps-ef:
在这里插入图片描述
可以看出父进程退出后,子进程的父进程成为了一号进程,而并非之前的30624。

需要注意的是,僵尸进程会产生危害(资源泄露),但孤儿进程并不会,而是被1号进程领养(回收)。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值