Linux进程

Linux进程

1. 冯诺依曼结构

数学家冯·诺依曼提出了计算机制造的三个基本原则,即采用二进制逻辑、程序存储执行以及计算机由五个部分组成(运算器、控制器、存储器、输入设备、输出设备),这套理论被称为冯·诺依曼体系结构。

冯诺依曼结构

输入设备:键盘,鼠标,摄像头,话筒,磁盘,网卡
输出设备:显示器,声卡,磁盘,网卡
CPU:运算器,控制器
存储器:内存

数据需要在计算机的体系结构中的流动和加工。而数据从一个设备到另一个设备,本质就是拷贝。数据设备间的拷贝效率决定了计算机整机的基本效率。

计算机存储的特点:

1.CPU不和外设直接打交道,CPU只和内存打交道。

2.外设(输入和输出)的数据不是直接给CPU的,而是先要存入内存中。

3.程序没有被加载到内存中时,储存在磁盘里。

存储金字塔:

存储金字塔

寄存器速度快但造价高、内存小,所以需要有内存和磁盘这样的结构。

2. OS(操作系统)

**定义:**OS是一种内置的程序,用来协作计算机的各种硬件,以与用户进行交互。

组成:

1.内核:内存管理、进程管理、文件管理、驱动管理

2.其他程序:库函数、shell外壳

**作用:**OS对下层进行软件硬件的管理工作,对上层提供良好、高效、稳定、安全的运行环境。

理解:

1.操作系统是一个进行“管理”的软件。

2.管理的理念是**“先描述,再组织**”。

3.对系统管理<->对数据管理<->对PCB(统称,Linux的具体称呼是task_struck)数据结构管理

系统调用和库函数的概念:

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

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

请添加图片描述

3. 进程

进程的组成:

进程 = 可执行程序+该进程对应的内核数据结构 = PCB + 自己的代码和数据 = 内核task_struct结构体 + 程序的代码和数据

processbar(可执行程序):

processbar被存储在磁盘里,当可执行程序运行时,内存会加载进程的代码和数据(不是进程)。当电脑开机时,存在磁盘里的操作系统会先被拷贝到内存中,而一个一个PCB结构体被存在操作系统在内存中开的空间里。

PCB(进程控制块):

系统中存放进程的管理和控制信息的数据结构称为PCB,一个进程一定有一个PCB,CPB由CPU运行。

PCB一般包括:

1、程序ID(PID、进程句柄):它是唯一的,一个进程都必须对应一个PID。PID一般是整形数字

2、特征信息:一般分系统进程、用户进程、或者内核进程等

3、进程状态:运行、就绪、阻塞,表示进程现的运行情况

4、优先级:表示获得CPU控制权的优先级大小

5、通信信息:进程之间的通信关系的反映,由于操作系统会提供通信信道

6、现场保护区:保护阻塞的进程用

7、资源需求、分配控制信息

8、进程实体信息,指明程序路径和名称,进程数据在物理内存还是在交换分区(分页)中

9、其他信息:工作单位,工作区,文件信息等

为什么要有PCB?因为OS要对进程进行管理,OS不能直接管理进程的代码和数据,而是通过PCB管理进程的代码和数据,再通过管理PCB来达到管理进程的目的。因此,PCB指针的连接使对进程的管理,变成了对链表的增删查改。

struct PCB
{
	//所有属性
	struct PCB *next;//指向下一个进程的PCB
	//内存指针->指向自己的代码和对应的数据
};

进程=PCB+自己的代码和数据

在这里插入图片描述

3.1 task_struct

因为Linux是用c语言编写的操作系统,所以Linux的PCB是一个叫做task_struct的结构体。

调度运行进程,本质就是让进程控制块task_struct进行排队,

进程的动态运行:只要进程的task_struct将来在不同的队列里,就可以访问不同的资源

在这里插入图片描述

进程的task_本身内部的属性:

① 标识符:描述本进程的唯一标识符,用来区别其它进程

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

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

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

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

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

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

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

⑨ 其它信息

查看进程:

编写一个简单的死循环代码来查看该进程的状态

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

int main()
{
    while(1)
    {
        printf("I am a process!\n");
        sleep(1);
    }
    return 0;
}

运行结果:

请添加图片描述

kill -9+进程的pid可以"杀"掉正在进行的进程

请添加图片描述

查看父进程pid:

可以使用unistd.h库提供的getpid()函数和getppid()来获得获得代码进程的pid和该进程的父进程的pid:

#include <stdio.h>
#include <unistd.h>
 
int main()
{
    while(1)
    {
        printf("I am a process! pid: %d, ppid : %d\n", getpid(), getppid());
        sleep(1);
    }
    return 0;
}

!请添加图片描述

可以看到两边的pid和ppid是一致的。

如果我们多次运行这个进程,就会发现:每次pid是变化的,但ppid是不变的。这是因为这个进程的父进程是shell中的bash,几乎我们在命令行上所执行的所有的指令(cmd),都是bash进程的子进程。

请添加图片描述

fork()函数:

fork函数是一个用来创建子进程的库函数,它有两个返回值。对于父进程,它返回子进程的pid;对于子进程,它返回0。

创建子进程的目的是为了让子进程执行和父进程不一样的代码。

为什么一个函数能有两个返回值呢?这是因为父进程的代码和数据是从磁盘加载来的,而子进程会继承父进程的代码和数据(?),fork函数在结束前就已经创建了子进程并调度了,结束时再判断当前的进程是父进程还是子进程来返回不一样的值。

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

int main()
{
    pid_t id=fork();
    while(1)
    {
         if(id)
    {
        printf("I am a parent process, my id is %d, my subprocess is %d\n",getpid(),id);
        sleep(1);
    }
    else 
    {
        printf("I am a subprocess, my id is %d, my parentprocess is %d\n",getpid(),getppid());
        sleep(1);
    }
    }
   
    return 0;
}

请添加图片描述

3.2 进程状态

进程状态的概念:

进程状态反映进程执行过程的变化。这些状态随着进程的执行和外界条件的变化而转换。在三态模型中,进程状态分为三个基本状态,即运行态,就绪态,阻塞态。在五态模型中,进程分为新建态、终止态,运行态,就绪态,阻塞态。

在Linux中,进程的状态被具体分为:R、S、D、T、t、X、Z

  1. R(runing):表示运行态,程序正在运行。
  2. S(sleeping):表示浅睡眠态,可中断,正常情况下,大部分进程都是S状态(例如CPU在等待外设响应的时候)。
  3. D(disk sleeping):表示深睡眠态,Linux系统特有的进程状态。例如Linux为了防止进程向磁盘写入数据时,系统将该进程杀掉导致数据丢失,会将进程标记为D态,D态的进程不可被强制中断。
  4. T(stopped):表示暂停态,被暂停的进程会等待进一步唤醒。
  5. t(tracing stop):是一种特殊的暂停态,如当代码在调试时进程就会进入t态
  6. X(dead):终止态,一个系统处于X态后资源可以立马回收。
  7. Z(zombie):僵尸态,已经运行完毕但需要维持自己的退出信息,在自己的进程task_struct会记录自己的退出信息,未来让父进程来读取。僵尸进程无法被kill,因为僵尸进程本来就”死“了。(如果没有父进程,僵尸进程会一直存在,引起内存泄漏

孤儿进程:

一个进程结束后会进入Z态等待它的父进程回收它的退出信息,但如果一个子进程在结束前,它的父进程就被杀掉,那么这个子进程就会变成孤儿进程。僵尸进程如果长时间不回收就会导致内存泄漏,但孤儿进程不同。如果一个进程被系统识别为孤儿进程,那么这个进程就会被一号进程(OS本身)”领养“,即这个进程的父进程变成了一号进程,当这个进程结束后,它的退出信息会交给一号进程,防止内存泄漏

注意:

CPU在调度进程时,只要进程在运行队列中,该进程就是R状态。

CPU调度是基于时间片轮转调度的,当一个进程占用CPU的时间超过了时间片,该进程就会重新进入到队列中,等待下次调度。这种让多个进程以切换的方式进行调度,在一个时间段内同时得以推进代码的方式,叫做并发。

阻塞态:

操作系统是软硬资源的管理者,进程本身是软件,操作系统通过管理task_struct来管理进程,那么操作系统又是怎么管理硬件的呢?

与管理进程类似,各种不同的硬件都有属于自己的驱动,而操作系统也不是通过直接管理驱动来管理硬件,而是通过device结构体来管理驱动,操作系统再通过管理device结构体链表来管理驱动,进而管理所有的硬件。而且不只是CPU才有运行队列,各种设备也有自己的wait_queue。

**一个进程被放到设备的wait_queue等待设备的进一步响应,这种状态被称为阻塞状态。**如敲击键盘输入字母,如果不对键盘进行任何操作,相关的进程就会在wait_queue中一直处于阻塞状态,直到敲下键盘输入字母,相关进程才会被放出wait_queue,在CPU中得到调度,最后回到wait_queue。

挂起态:

磁盘上有一个swap分区,系统可以自主判断什么进程短时间内不会被频繁调度,然后把该进程的代码和数据从内存转移到swap分区里,以此节省内存空间,但该进程的task_struct依然在OS中等待调度。此时该进程的状态被称为阻塞挂起态

swap分区是一种用效率换空间的做法,swap分区如果设置过大,频繁的换进换出会导致效率降低的问题。

4. 寄存器

CPU的寄存器本身是硬件,具有数据的存储能力,CPU的寄存器硬件只有一套,但CPU内部的数据可以有很多套,有几个进程,就有几套该进程的上下文数据。

当一个进程被CPU剥离时,寄存器中会保存这个进程的临时数据,保存临时文件的目的是为了方便下次调度时恢复这个进程,CPU内部的所有寄存器中的临时文件,叫做进程的上下文。

5.进程的优先级

5.1 优先级的概念

指定进程获取某种资源的先后顺序叫做优先级。进程的优先级是由它的task_struck控制块的结构体的内部字段决定的在Linux中优先级数字越小,优先级越高。

为什么要有优先级呢?

因为系统中进程大部分情况下都是有较多的,而进程访问的资源(CPU)始终是有限的。

操作系统关于调度和优先级的原则:分时操作系统(时间片轮转调度),基本的公平。如果进程长时间不被调度,就造成了饥饿问题。

5.2 Linux的优先级

使用ps -al查看所有进程状态

[图片]

PRI:进程的优先级

NI:进程优先级的修正数据,nice值(新的优先级=PRI+nice),达到对于优先级动态修改的过程

使用top命令进入查看任务管理器模式,再按r,输入需要调整优先级的进程的PID,回车,输入调整值(注意输入的是nice值)

nice值也是有范围的,nice只能在[-20,19]里取,超过19的数会被取到19,反之取到-20。

相关命令

当进程开始执行时,会在proc下创建一个文件夹,使用/proc pid -d可以看到该进程的所有属性

ps axj命令可以查看所有的进程,结合管道|grep命令可以搜索指定名称的进程,head -1命令可以显示进程每一列的含义:

//显示名字叫做a.out的进程(一个进程的名字通常和它的可执行程序的名字相同)
ps axj | grep 'a.out'
//加上显示进程的具体信息
ps axj | head -1 && ps axj | grep 'a.out'
//使用shell脚本语法每隔1s显示一次进程
while :; do ps axj | head -1 && ps axj | grep 'a.out'; sleep 1; done
//如果不想看到grep进程,-v表示去掉某某
grep -v grep

kill指令:

-l:查看所有的kill指令组合

-9:杀掉进程

-18:继续运行

-19:暂停进程
//显示名字叫做a.out的进程(一个进程的名字通常和它的可执行程序的名字相同)
ps axj | grep ‘a.out’
//加上显示进程的具体信息
ps axj | head -1 && ps axj | grep ‘a.out’
//使用shell脚本语法每隔1s显示一次进程
while :; do ps axj | head -1 && ps axj | grep ‘a.out’; sleep 1; done
//如果不想看到grep进程,-v表示去掉某某
grep -v grep
``

kill指令:

-l:查看所有的kill指令组合

-9:杀掉进程

-18:继续运行
-19:暂停进程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值