【Linux】操作系统及进程概念

阅读 201

2023-01-04

文章目录


一、冯诺依曼体系结构

我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。
在这里插入图片描述

计算机包含输入设备、输出设备、存储器、中央处理器(运算器+控制器)
至目前,我们所认识的计算机,都是有一个个的硬件组件组成。

磁盘属于外存,具有永久性存储能力。
CPU作为计算机的核心,负责计算,速度最快,寄存器次之,内存在次之,而外设是较慢的。
在这里插入图片描述
但是CPU只能被动接受别人的指令和别人的数据,那么CPU必须先认识别人的指令(每个CPU被制作都有自己的指令集),才能执行别人的指令,起到计算别人数据的目的。

上面说到CPU的速度很快,而外设的速度很慢,那么CPU直接从外设拿数据效率就降低了,所以数据是从外设加载到内存中的,然后CPU再从内存中读取数据,CPU处理完的数据再返回给内存(产生了缓存),数据再从内存中加载到外设,这大大提高的数据的处理。

所以CPU再读取和写入时候,在数据层面只和内存打交道,为了整体效率。

内存从外设读取和写入数据的过程成为I/O过程(input/output)

对于冯诺依曼体系,我们应该注意:

所以程序的运行必须要加载到内存,CPU执行的代码访问数据,只能从内存中读取(这也是体系结构规定的)。

对冯诺依曼的理解,不能停留在概念上,要深入到对软件数据流理解上,请解释,从你登录上qq开始和某位朋友聊天开始,数据的流动过程。 从你打开窗口,开始给他发消息,到他的到消息之后的数据流动过程。如果是在qq上发送文件呢?

二、操作系统OS

  • 是什么

操作系统是一个进行软硬件资源管理的软件,操作系统包含了进程管理,文件管理,内存管理,驱动管理。
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:

  • 为什么

操作系统通过合理的管理软硬件资源(手段),为用户提供良好的,稳定的,高效的,安全的执行环境(目的)。

在整个计算机软硬件架构中,操作系统的定位是: 一款纯正的“搞管理”的软件

  • 怎么办
  1. 管理者不需要与被管理者直接交互,依旧能够很好的将被管理者管理起来
  1. 管理的本质是对数据进行管理
  1. 管理的方法是先描述,再组织

在这里插入图片描述

所有的管理,本质是对数据做管理,管理的方法是先描述在组织
计算机管理硬件

1.描述起来,用struct结构体或者类
2.组织起来,用链表或其他高效的数据结构

总结:

三、系统调用和库函数概念

系统提供调用接口原因:操作系统不相信任何用户 – 操作系统不确定我们是否会对各种软硬件进行违法操作。但是操作系统又必须给上层用户提供各种服务,于是 给用户提供系统调用的接口,即当用户有访问软硬件的需求时,直接调用操作系统提供的接口,然后由操作系统来帮助用户完成对应的工作;这样即满足了用户的需求,又保护了软硬件资源。
在这里插入图片描述

四、进程

1.概念

也有书籍是一个运行起来(加载到内存)的程序时进程。

进程和程序相比进程具有动态属性。
而程序的本质计算文件,存储在磁盘中。

2.描述进程-PCB

当大量的程序加载到内存中,,操作系统用进行管理,会对程序进行先描述,在组织。

而描述进程-PCB

//进程控制块
struct task_struct3
{
	//该进程的所有属性
	struct task_struct* next;
	//该进程对应的代码和属性的地址
}

组织:对进程管理变成了进程对应的PCB进行相关的的管理。而对进程管理转化成了对链表的增删查。

struct task_struct* p1 = malloc(struct task_struct);
p1->..=xx;
p1->addr = 代码和数据的地址;
  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
  • 课本上称之为PCB(process control block), Linux操作系统下的PCB是: task_struct

先描述,再组织工作 : struct task_struct内核结构体 --> 内核对象task_struct 对象 --> 将该结构体,代码和数据关联起来。

所以 进程 = 内核数据结构(task_struct) + 进程对应的磁盘代码

  • 程序和进程

程序的本质是放在磁盘上的可执行文件(.exe文件),就是一个文件,根据冯诺依曼体系,软件运行要加载到内存中,而进程则是将程序加载到内存当中,并且由操作系统进行管理,生成一个描述自身性质的数据结构(PCB),由内核数据结构和进程对应的磁盘代码两者共同组成“进程”

  • task_struct

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

可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里。

  • task_ struct内容分类

3.查看进程

首先创建一个死循环文件,方便查看进程:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
make一下,生成可执行程序,开始执行:
在这里插入图片描述
接下来可以查看进程:

进程的信息可以通过 /proc 系统文件夹查看
如:要获取PID为1的进程信息,你需要查看 /proc/1 这个文件夹
大多数进程信息同样可以使用top和ps这些用户级工具来获取

ps ajx | grep "myproc"
ps ajx | head -1
ps ajx | head -1 && ps ajx | grep "myproc"

在这里插入图片描述
同时,我们可以杀掉(kill)进程,当然ctrl+c也可以直接结束掉:

kill -9 进程PID

在这里插入图片描述
进程在调度运行的时候,进程就具有动态属性。
进程在运行的时候本质是在读取进程内部的代码,内部在执行,从启动到终止中间可能会有一段很长的时间,这个进程就具备了动态属性。

查看进程:

ls /proc/

在这里插入图片描述

4.查看系统调用

  • getpid()
man 2 getpid

如果指令无法实现,则要下载:

sudo yum -y install man-pages

在这里插入图片描述
获取进程PID需要两个头文件,调用响相应函数,最后的返回值就是进程的PID
对myproc.c进行修改:
在这里插入图片描述
运行并查看进程:
在这里插入图片描述

此外,还有另一种方法查看进程:
在Linux中proc是内存级目录

ls /proc/

在这里插入图片描述
数字开头就是进程的pid,一个进程也可以当做文件来看待

ls /proc/进程PID -d

在这里插入图片描述
在这里插入图片描述

如果程序被删除了,那么进程还会跑吗?
在这里插入图片描述
可以看到进程依然可以跑。

5.查看进程调用

  • getppid()
    获得父进程ID
man 2 getppid

在这里插入图片描述

  • 创建文件
touch myproc.c
tpuch Makefile

在这里插入图片描述
在这里插入图片描述

  • 运行停掉
    在这里插入图片描述
    可以看到每次进程运行的时候,子进程的ID是变的,父进程的ID不变。
  • 查看父进程
ps axj | head -1 && ps axj | grep 父进程PPID

在这里插入图片描述
命令行上启动的进程,一般它的父进程没有特殊情况的话,都是bash
以子进程方式运行,遇到问题只与子进程有关,与父进程无关。

6. 通过系统调用创建进程-fork初识

  • fork
make fork

在这里插入图片描述

  • fork第一种用法

在这里插入图片描述

运行

在这里插入图片描述

fork是一个函数,用于创建子进程,函数执行前只有一个进程,函数执行后有两个进程:父进程和子进程,即打印两条。
即前一个进程的子进程是后一个进程的父进程。

  • fork第二种用法
    fork()返回类型是 pid_t
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
同一个变量id,在后续不被修改的情况下,竟然有不同的内容。
(所以对于结果我们很好理解,返回成功时,会给父进程返回子进程的pid,子进程会返回0)。但是,这里居然一个变量id居然会有两个返回值。我们根据这个返回结果写代码:
在这里插入图片描述
在这里插入图片描述
我们可以看到,两个while循环都执行起来了,这也证明了实际上参与while循环的有两个进程!并且它们是父子进程,即父子关系。

这也说明了,在fork之后,又创建了一个进程,两个进程分别在两个执行流中,因此可以分别执行if 和 else if,也可以分别进入while循环!

总结一句话,fork()之后,会有父进程+子进程两个进程在执行后续代码,fork()后续的代码,被父子进程共享,通过返回值不同,让父子进程执行共享代码的一部分,这就是并发式编程。

精彩评论(0)

0 0 举报