Linux操作系统和进程基本概念(上)

简介: Linux操作系统和进程基本概念

🎵一、冯诺依曼体系和操作系统


🎈1.1冯诺依曼体系结构


我们常见的台式计算机、笔记本以及不常见的公司使用的服务器,大部分都遵从冯诺依曼体系。


1669271442033.jpg


冯诺依曼体系结构主要讲述的是什么呢?它主要向我们介绍了计算机的基本架构:


输入设备:包括键盘、鼠标、扫描仪、写板等。


中央处理器(CPU):含有运算器、控制器等


输出设备:显示器、打印机、网卡等。


我们输入设备输入的数据必须先加载到内存(存储器),才能被CPU处理,CPU能且只能对内存进行读写,不能访问外设(输入设备)。输出设备从内存读取信息。


🎈1.2操作系统


Ⅰ概念


任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。简单来说,操作系统是一款软硬件资源管理的软件,包括:


🖊内核(进程管理,内存管理,文件管理,驱动管理)


🖊其他程序(例如函数库,shell程序等)


Ⅱ目的


设计操作系统的目的是为了与硬件交互,通过合理的管理软硬件资源,为用户提供良好的执行环境。


1669271466113.jpg


Linux操作系统内核是用C语言写的,所以它是如何管理硬件呢?操作系统本身并不管理硬件,驱动管理硬件,从硬件获取数据,对数据做管理,用struct结构体描述,把数据做分类描述,对应设备做特定的结构管理起来,比如队列,链表等数据结构。最后交付给操作系统,而我们用户通过操作系统提供的接口查看这些数据信息。


🎵二、进程


🎈2.1基本概念


进程:一个运行起来(加载到内存)的程序。也就是在内存中的程序,进程与程序相比,具有动态属性。


比如Windows下我们打开任务管理器就可以查看当前正在运行的程序,这些都是一个个独立的进程:

1669271487822.jpg


🎈2.2描述进程-PCB


进程信息被放在一个叫做进程控制块的数据结构中,也就是PCB。Linux操作系统下的PCB是:task_struct。进程被转化为内核数据结构(task_struct)和进程对应的磁盘代码。


PCB概念的提出,使得对进程管理,变成了对进程对应的PCB相关管理。


1669271511947.jpg


task_struct 内容分类:


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


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


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


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


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


🖊上下文数据:进程执行时处理器的寄存器中的数据。


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


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


🖊其他信息。


🎈2.3进程基本指令


👓Ⅰps ajx


ps ajx :显示当前目录下所有进程


1669271533013.jpg


我们也可以通过管道检索指定正在运行的进程。比如:


1669271541076.jpg


当然,我们看向这些内容并不知道是什么数据,我们可以把它的标头打印出来方便我们查看。


1669271549426.jpg


👓Ⅱkill 指令


kill -l 我们查看一下这个指令。


1669271561672.jpg


kill指令集下有很多指令,我们这里需要着重关注的有三条指令 :


🖊kill -9 终止进程


🖊kill -19 停止/暂停进程


🖊kill -18 继续进程


我们先来看如何终止一个进程。

1669271570065.jpg

这里的PID是进程的编号,Linux下的大多数对进程的操作都是对进程的PID,也可称之为它的ID进行操作。


1669271580609.jpg


执行过后,进程就被终止了。还有两个重要的kill指令,后续会提及。


👓Ⅲ getpid && getppid


getpid和getppid是Linux下获取当前进程和父进程id的函数。

1669271597158.jpg


//头文件
#include<unisted.h>
#include<sys/types.h>
//sunopsis
pid_t getpid(void);
pid_t getppid(void);
//返回值
getpid()   返回当前进程ID
getppid()  返回当前进程父进程ID


①getpid

我们写一个程序来查看一下它的ID:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
  while(1)
  {
    printf("我是一个进程,我的ID是%d\n",getpid());                                                 
    sleep(1);                                 
  }   
  return 0;
}

1669271641748.jpg

那么这个ID它真的可以代表这个进程吗?我们来验证一下:

1669271656660.jpg

1669271665656.jpg

1669271672229.jpg

通过验证,我们发现,确实如此,pid确实可以代表各个进程,就如同我们的学号对应一位同学。


②getppid


在了解pid之后,ppid又是何方神圣呢?ppid是当前进程的父进程的id。按照关系,当前进程是其父进程的子进程。


我们编写一个程序来查看一下父进程的id。

/*myprocess.c*/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
  while(1)
  {
    printf("我是一个进程,我的ID是%d,父进程的ID是%d\n",getpid(),getppid());                                                 
    sleep(1);                                 
  }   
  return 0;
}

1669271716831.jpg

我们发现子进程的id每次运行程序都会变化,而父进程的id是不会变化的。也就是说,父进程相对于子进程来说只有一个,而子进程可以经父进程创建生成很多个,执行程序时由子进程来执行,就算挂了也不会影响父进程。而shell执行命令就是以子进程来执行的。


那么这里子进程的父进程到底是什么呢?其实就是当前的命令行解释器:

1669271729530.jpg

1669271742163.jpg

👓 Ⅳ fork


fork用于创建子进程。

1669271755802.jpg


1669271763090.jpg


/*fork*/
//头文件
#include<unisted.h>
pid_t fork(void);
//返回值
//如果创建成功,子进程的ID被返回给父进程,0返回给子进程。如果失败,-1返回给父进程,没有子进程创建并报错。

我们研究一下返回值就会发现一个惊奇的现象:如果创建成功,子进程的PID被返回给父进程,0返回给子进程。失败-1返回给父进程,没有子进程创建。我们发现fork的返回值有两个!!而这个会对我们的程序有什么影响呢?


1669271783835.jpg


我们看到,同一段代码执行了两次,这两次一次是父进程执行的,一次是子进程执行的。而在这里我们也可以看出系统和语言的不同,语言是不可能出现有两个返回值这样的情况的。


所以根据这种特性,我们在使用fork的时候,需要使用if条件判断执行。


1669271796276.jpg


如果我现在把正在执行的进程的可执行程序给删除,那么进程还会继续执行吗?


1669271808569.jpg


我们发现进程还在执行,但是我们查看exe文件会发现闪红并告诉我们deleted。

1669271818113.jpg

相关文章
|
3天前
|
算法 调度 UED
操作系统中的进程管理:原理与实践
在数字世界的心脏跳动着无数进程,它们如同细胞一般构成了操作系统的生命体。本文将深入探讨进程管理的奥秘,从进程的诞生到成长,再到最终的消亡,揭示操作系统如何协调这些看似杂乱无章却又井然有序的活动。通过浅显易懂的语言和直观的比喻,我们将一起探索进程调度的策略、同步机制的重要性以及死锁问题的解决之道。准备好跟随我们的脚步,一起走进操作系统的微观世界,解锁进程管理的秘密吧!
15 6
|
1天前
|
算法 调度 UED
深入理解操作系统之进程调度算法
【9月更文挑战第9天】在操作系统的心脏跳动中,进程调度扮演着关键角色,就如同指挥家控制交响乐的节奏。本文将通过浅显易懂的语言和生动的比喻,带领读者走进进程调度的世界,探索不同调度算法背后的哲学与实践,以及它们如何影响系统的性能和用户体验。从最简单的先来先服务到复杂的多级队列和反馈循环,我们将一同见证操作系统如何在众多任务中做出选择,确保系统的高效与公平。
|
9天前
|
算法 Linux 调度
深入理解操作系统:进程管理的艺术
【9月更文挑战第2天】在数字世界的复杂迷宫中,操作系统扮演着关键角色。它不仅是计算机硬件与软件之间的桥梁,更是协调和管理计算资源的核心力量。本文将带你探索操作系统的心脏——进程管理,揭示它是如何在幕后精心编排每一出数字戏剧的。通过深入浅出的介绍和生动的比喻,我们将一起解锁进程的秘密,并借助代码示例,直观感受进程管理的精妙之处。准备好,让我们启程,进入这个令人着迷的操作系统世界!
20 6
|
11天前
|
调度 开发者 Python
深入浅出操作系统:进程与线程的奥秘
【8月更文挑战第31天】 本文将带你探索操作系统中的核心概念——进程与线程。通过浅显易懂的语言和实际代码示例,我们将一起理解它们的定义、区别以及在操作系统中的作用。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你打开一扇了解计算机内部工作原理的新窗口。
|
11天前
|
算法 调度 Python
深入理解操作系统的进程调度
【8月更文挑战第31天】本文通过浅显易懂的语言,介绍了操作系统中进程调度的基本概念和常见算法。文章以通俗易懂的方式阐述了进程调度的重要性,并通过代码示例展示了先进先出(FIFO)调度算法的具体实现。读者可以通过本文加深对操作系统核心机制的理解,并激发对更深层次技术探索的兴趣。
|
11天前
|
存储 算法 调度
深入理解操作系统:进程调度的算法与实现
【8月更文挑战第31天】在操作系统的核心,进程调度扮演着关键角色,它决定了哪个进程将获得CPU的使用权。本文不仅剖析了进程调度的重要性和基本概念,还通过实际代码示例,展示了如何实现一个简单的调度算法。我们将从理论到实践,一步步构建起对进程调度的理解,让读者能够把握操作系统中这一复杂而精妙的部分。
|
11天前
|
算法 调度 开发者
深入理解操作系统:进程管理与调度算法
在数字时代的心脏,操作系统扮演着至关重要的角色。它不仅是计算机硬件与软件之间的桥梁,更是确保多任务高效运行的守护者。本文将带你一探操作系统中进程管理的奥秘,并通过实际代码示例深入解析进程调度算法。无论你是编程新手还是资深开发者,了解这些基础概念都将有助于你更好地理解计算机工作原理,并提升你对系统性能调优的认识。准备好,让我们一起揭开操作系统的神秘面纱!【8月更文挑战第31天】
|
11天前
|
算法 调度 UED
探索操作系统的心脏:深入理解进程调度
【8月更文挑战第31天】 在数字世界的每一次跳动中,有一个不可见的手在默默掌控着节奏——这就是进程调度。本文将带你走进操作系统的核心,一探进程调度的秘密。我们将从进程调度的基本概念出发,逐步深入到常见的调度算法,并通过实际代码示例,展现调度算法如何在真实系统中运作。无论你是计算机科学的初学者,还是希望深化理解的专业人士,这篇文章都将为你揭开操作系统中这一关键机制的面纱。
|
11天前
|
消息中间件 Unix Linux
深入浅出操作系统:进程与线程的奥秘
【8月更文挑战第31天】本文将带你一探操作系统中最为神秘的两个概念——进程和线程。我们将从基础的定义出发,逐步深入到它们在操作系统中的实现原理,并通过代码示例揭示它们在实际编程中的应用。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和理解。
|
11天前
|
开发者 Python
深入浅出操作系统:进程与线程的奥秘
【8月更文挑战第31天】在数字世界的幕后,操作系统扮演着至关重要的角色。本文将揭开进程与线程这两个核心概念的神秘面纱,通过生动的比喻和实际代码示例,带领读者理解它们的定义、区别以及如何在编程中运用这些知识来优化软件的性能。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和实用技巧。