进程概念

什么是进程

冯诺依曼体系结构

在这里插入图片描述

输入设备:采集获取数据(键盘)
输出设备:数据输出(显示器)
存储器:内存/
运算器+控制器:中央处理器CPU

硬件结构决定软件行为。
所有硬件都是围绕内存工作的。

**操作系统:**系统内核+外部应用。管理计算机上的软硬件资源。

进程概念

运行中的程序。进程就是一个PCB。是一个运行中程序的描述,通过描述信息中的内存指针能够找到内存中运行的程序代码以及数据,并且通过上下文数据可以保存程序调度切换时正在处理的数据,以及通过程序计数器保存进程切换时程序即将执行的下一步指令,等等…通过这些描述信息实现控制一个程序的运行,因此对于一个操作系统来说进程就是PCB。

进程在操作系统中是调度切换运行的,每个进程都有一个CPU时间片(一个进程在CPU上的运行时间段),在CPU上时间片运行完毕后则切换到下一个进程–CPU分时机制。

PCB

一个CPU同一时间只能处理一个进程,其他进程就会处于阻塞状态。为了提高处理效率,CPU采取分时技术(每个进程CPU只处理很短的时间)。那么问题来了,CPU在处理一个进程的时候怎么知道它上次处理这个进程处理到哪里了?所以就有了PCB(process control block,进程控制块–存放进程信息的数据结构,Linux中的PCB是task_struct)。
task_struct内容分类:

内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
上下文数据:保存上次正在运行的数据(休学例子)
程序计数器:程序中即将被执行的下一条指令的地址。
标识符(ID):描述本进程的唯一标识符,用来区别其他进程(学生学号)。
状态:任务状态,退出等。
优先级:执行的优先性。
记账信息:包含处理器时间总和,时间限制(人类年龄)。

进程的创建和查看

查看进程信息

ps -ef
e:查看所有进程信息
f:树状展开
ps aux
显示所有包含其他使用者的行程
ps -ef | grep loop

杀死进程

kill
kill 进程ID //杀死普通进程
kill -9 进程ID //强制杀死

进程状态

运行/就绪/阻塞
Linux下进程状态:

运行状态R:正在运行的以及只要拿到时间片就能运行的
可中断休眠状态S:可以被中断的阻塞状态
不可中断休眠状态D:
停止状态T:
僵死状态Z:进程已经退出但是资源没有完全释放

僵尸进程

僵尸进程的产生原因是什么?

子进程先于父进程退出,退出后,为了保存自身的退出原因(返回值),因此资源没有完全释放(PCB),操作系统这时候通知父进程获取子进程的退出状态,并允许操作系统释放资源,但是如果父进程没有关注到这个退出状态,则子进程虽然退出,但是资源没有完全被释放,处于僵死状态,成为僵尸进程。(猝死,家人,警察例子)

僵尸进程的危害是什么?

资源泄露。

僵尸进程代码演示:

    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
   
    int main(){
        printf("***********%d\n",getpid());
        pid_t pid=fork();
        if(pid<0){
           printf("fork error\n");
        }else if(pid==0){
            printf("this is child--%d\n",getpid());
            sleep(5);
            exit(0);
        }else{
            printf("this is father--%d\n",getpid());
        }
        while(1){
            printf("------------%d\n",getpid());
            sleep(1);
        }
        return 0;
    }

运行结果:
在这里插入图片描述

孤儿进程

父进程先于子进程退出,子进程成为孤儿进程在系统后台运行(例如S+是在前台运行,S是在后台运行),被1号init进程收养。

孤儿进程代码演示:

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
   
    int main(){
   
        printf("******\n");
        pid_t pid=fork();
        if(pid>0){
            sleep(5);
            exit(0);
        }
        while(1){
            printf("hello\n");
            sleep(1);
        }
        return 0;
    }

进程优先级

决定进程CPU调度优先权级别。优先级越小越早被执行

环境变量

用于存储系统运行环境参数的变量—使系统的参数配置更加灵活。
向进程传递参数。

env:查看所有的环境变量
export:将一个变量设置为环境变量
set:查看所有变量信息

程序地址空间

程序地址空间如下图:
在这里插入图片描述

内存地址:内存区域的编号。
每个进程都有一个自己的进程地址空间。
创建子进程—父子进程代码共享,数据独有。
我们在进程中所访问到的地址实际都是一个虚拟地址
程序地址空间->进程地址空间->虚拟地址空间
虚拟地址空间:通过一个结构体描述出一块完整的连续的线性的地址空间(mm_struct结构体–内存描述符)。

父子进程代码共享,数据独有,代码演示:

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    int gval=10;
    int main(){
   
        pid_t pid=fork();
        if(pid==0){
           gval=100;
            printf("child=%d,%p\n",gval,&gval);
        }else if(pid>0){
            sleep(3);
            printf("father=%d,%p\n",gval,&gval);
        }
        return 0;
    }

运行结果:
在这里插入图片描述
解释: 这里打印出来的地址是虚拟地址而不会物理地址,这里是采用的写实拷贝技术,代码共享,数据独有。子进程在开始复制父进程时,页表也会拷贝的,只是在子进程要修改数据时会给子进程申请新的物理地址来存放修改的数据。
顺序存储数据:内存利用率低。
离散式存储数据:使用虚拟地址映射物理地址来实现离散存储数据。
页表:记录虚拟地址与物理地址之间的映射关系。

操作系统通过虚拟地址空间向进程描述了一个完整的连续的虚拟地址空间,供进程使用,但是在物理内存中进程数据存储采用离散式存储(提高内存利用率),并且使用页表映射虚拟地址与物理地址的映射关系,并且在页表中可以实现内存访问控制(标志位表示内存的访问权限)。

如何通过虚拟地址得到物理地址:分段式内存管理/分页式内存管理/段页式内存管理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值