操作系统(OS)与系统进程

操作系统(OS)与系统进程

冯诺依曼体系结构

要去了解操作系统,冯诺依曼体系结构是必须掌握的,它决定了计算机最底层最基础的设计思路。

首先,冯诺依曼体系结构由四大部分构成,输入设备,存储器,中央处理器(CPU),输出设备。CPU里又有控制器和运算器两大器件组成。

这里的++存储器指的是内存++ ,不考虑缓存情况,这里的**++CPU能且只能对内存进行读写++**,不能访问外设(输入或输出设备)外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。一句话,所有设备都只能直接和内存打交道 。

因此,一个程序要运行,必须加载到内存中。原因就是冯诺依曼体系结构设计就决定了必须是这样的。

那么为什么必须是内存,CPU不能直接去外设,例如硬盘中读取数据呢,原因是存储是分级的。

木桶的短板效应很好理解,要考虑到效率问题。

操作系统(Operator System)

任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括内核(进程管理,内存管理,文件管理,驱动管理),其他程序(例如函数库,shell程序等等)。

设计OS的目的 :操作系统本质就是一组软件,负责与底层硬件资源交互。与硬件交互,管理所有的软硬件资源
为用户程序(应用程序)提供一个良好的执行环境

操作系统本质是一款负责管理的软件,管理所有的软硬件资源。

用户是不可能直接管理底层硬件资源的,因为操作系统不相信任何人,要与底层资源交互唯一的方式就是通过系统调用接口,通过操作系统去完成。

在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。

系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发 。

总结:

操作系统管理硬件方式:先描述,后组织。

描述:将要管理的对象的属性用结构体描述整合起来

组织:将一个个的结构体用特定的数据结构进行组织

进程

基本概念

课本概念:程序的一个执行实例,正在执行的程序等。

内核观点:担当分配系统资源(CPU时间,内存)的实体。

简单理解,就是加载到内存中的一个个程序,最简单直观的就是打开任务管理器,就是有很多很多进程。

概念简单理解即可。真正难理解的是进程的各种属性,以及操作系统对进程的管理。

进程的描述(PCB)

一个进程通常有进程信息(PCB)以及它的数据和代码组成。

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

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

PCB包含的信息:

标示符: 描述本进程的唯一标示符,用来区别其他进程。

状态: 任务状态,退出代码,退出信号等。

优先级: 相对于其他进程的优先级。

程序计数器: 程序中即将被执行的下一条指令的地址。

内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针

上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。

I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。

记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

其他信息

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

Linux中是通过双链表的方式将task_struct组织起来的。

查看进程

进程信息都在/proc目录下可以找到,如要获取PID为1的进程信息,你需要查看 /proc/1 这个文件夹

大多数进程信息同样可以使用top和ps这些用户级工具来获取 ,并且是比较推荐的。

例如查看全部进程。

怎么查找一个进程呢。

只需要会查找进程即可。上面一行进程的详细信息需要慢慢来理解。

通过系统调用获取进程标示符(PID)

通过系统调用可以获取自己进程的PID或者PPID,getpid()和getppid()。

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

fork非常的神奇,它有两个返回值,没错,它是个函数,但是有两个返回值,将子进程的PID返回给父进程,子进程返回直接0。

这次你会发现一个神奇的现象,代码中写的if else结构竟然同时执行了。难道id既是0,又是大于0的数吗。

fork是怎么做到的呢,它究竟做了什么事?

Linux文档中关于fork的描述是这样的:

fork是创建一个有自己PID的子进程,但是**++子进程和父进程却是共享一份代码的++**。

但是我们的创建子进程的目的是为了让两个进程做不同的事情,所以需要用一定的方法将两者区别开来,所以fork采用了两个返回值的方式,但是一个id如何能表示两个值呢?

在代码执行完毕,最后要return时,父进程和子进程每个都返回一次,这才实现了fork两个返回值。

但是还有一个问题子进程和父进程却是共享一份代码,那么数据也是共享的,问题是如果要对数据做修改怎么办呢?

Linux下给出的解决方式是在子进程想要对数据进行修改的时候,操作系统会阻止,并且为子进程单独开辟一块空间将数据拷贝给子进程,这种技术叫做写时拷贝。

进程状态(初识)

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在

Linux内核里,进程有时候也叫做任务),下面是Kernel源代码中的定义:

复制代码
/*
\* 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):这个状态只是一个返回状态,你不会在任务列表里看到这个状态 。

进程状态有很多种,第一次接触进程状态只简单认识三大状态,运行、阻塞、挂起。

一个进程要执行要先进到运行队列中排队。

++一个进程到CPU上不一定必须等到它执行结束才被拿下去,每一个进程都有时间片,如果时间到了但是没有结束依然会被拿下来到放到后面重新排队,防止一个进程一直占用资源的情况。++

而由于后面的进程都在排队,但是还占据资源,为了保证进程既能正常排队,又能节省大量资源,所以只留下PCB来排队,将对应的代码和数据交换到磁盘中,等轮到时再将对应的代码和数据交换过来,中间只有PCB的过程就是一种挂起状态。

相关推荐
Lovyk15 分钟前
Linux 正则表达式
linux·运维
Fireworkitte1 小时前
Ubuntu、CentOS、AlmaLinux 9.5的 rc.local实现 开机启动
linux·ubuntu·centos
sword devil9002 小时前
ubuntu常见问题汇总
linux·ubuntu
ac.char2 小时前
在CentOS系统中查询已删除但仍占用磁盘空间的文件
linux·运维·centos
中科米堆3 小时前
中科米堆CASAIM自动化三维测量设备测量汽车壳体直径尺寸
运维·自动化·汽车·视觉检测
淮北也生橘123 小时前
Linux的ALSA音频框架学习笔记
linux·笔记·学习
缘华工业智维4 小时前
CNN 在故障诊断中的应用:原理、案例与优势
大数据·运维·cnn
开航母的李大5 小时前
软件系统运维常见问题
运维·服务器·系统架构·运维开发
华强笔记6 小时前
Linux内存管理系统性总结
linux·运维·网络
十五年专注C++开发7 小时前
CMake进阶: CMake Modules---简化CMake配置的利器
linux·c++·windows·cmake·自动化构建