linux篇(四)linux进程(上)
作者介绍:
关于作者:东条希尔薇,一名喜欢编程的在校大学生
主攻方向:c++和linux
码云主页点我
作者CSDN主页地址
目录
- 认识操作系统
- 感性的认识操作系统
- 理性的认识操作系统
- 初步认识OS的管理
- 进程的认识
- PCB的基本数据说明
- 查看进程
- PCB基本数据之标识符
- PCB基本数据之上下文数据
- 利用fork来认识父子进程
- PCB基本数据之进程状态
- 睡眠状态和运行状态
- 特殊状态之僵尸状态
- 特殊进程之孤儿进程
- PCB基本数据之优先级
认识操作系统
感性的认识操作系统
我们的计算机,其实它的本质是由冯诺依曼结构为基础,由一个个硬件之间相互配合而形成的拥有计算功能的机器罢了
而我们是不能直接对一堆冷冰冰的机器进行交互的。它需要有一个管家,来管理好这些硬件,并且这个管家我们是能够直接使用的,这个管家,就叫做操作系统
像这种任何计算机包含的一种最基本的能够进行软硬交互的一款软件,我们把它叫做操作系统(英文缩写OS)
而狭义上的OS,它包括:
- 内核:进程管理,内存管理,文件管理,驱动管理:这是OS用于管理硬件的
- 其它程序:函数库,shell程序等,这些程序能帮助用户更方便的使用OS
理性的认识操作系统
既然我们知道了操作系统是一款搞管理的软件,那么它是如何搞管理的呢?
首先,我们先来认识一下OS的工作基本原理
先上一张OS的层次图
通过这张图:我们可以得出以下结论:
OS对下先通过调用驱动程序(驱动程序是能直接与硬件交互的一种软件),能往下操作硬件
对应用户,OS有一些暴露在外的用户能够直接调用的接口(其实说白了,这个接口就是函数,就是对一些接口进行封装而成的),能使用户向OS下达命令,实现一些功能
补充:OS是不信任任何用户的,所以我们也只能通过接口来与OS打交道
所以,在整个计算机设计架构中,OS的定位是:一款纯正的“搞管理”的软件
初步认识OS的管理
先看看生活中,我们有哪些管理的例子?
我们可以拿校长和学生来举例子,可以得出管理者和被管理者的关系
我们可以想象在学校中,你可能很少与你的校长打交道,而你在学校需要遵守什么规则,你的校级评奖等等,都是需要通过校长的
假如,你要给一个学生发奖,需要通过哪些流程?先查出他的考试成绩,然后可能需要开会来决定你最后给这位学生颁奖,最后通过某位老师,把奖状发下去
所以,我们可以得出以下的结论:
- 管理者和被管理者并不直接打交道
- 如何对被管理者进行管理?先进行一些决策,再把这些决策施行
但是我们可不能盲目的管理,比如你肯定不会给全年级倒数第一发奖学金。所以,我们如果要管理,可能还需要一些材料来支撑我们高效的管理
这个材料,就是数据
比如,你要查看一个学生的基本信息,可能需要查看他的生源地啊,成绩啊,获奖历史啊等等数据,然后根据这些数据来决定是否给他发奖学金
那么,如何聚合这些数据呢?
而在c++中,我们可以使用类来描述我们需要管理的一个个对象,c语言中我们叫结构体
而这个过程,我们通常叫做数据的描述
其次,如果你要快速找出全校排满前几的学生,可能需要一些数据结构和算法,来高效的找出你需要的对象
而这个过程,我们通常叫做数据的组织
所以,我们可以得出一个十分重要的结论:
计算机执行管理时,先把管理对象描述起来,再把管理对象组织起来
- 描述在系统底层使用struct结构体
- 组织可以使用链表,队列等数据结构进行组织
进程的认识
进程管理作为OS一款十分重要的组件之一,它可以管理我们计算机中运行的所有程序
而进程又是什么呢?
这是书本上的定义:
程序的一个执行实例,正在运行的程序,加载到内存中的程序
而根本我们本文提到的OS管理的中心思想,我想重新给进程下一个定义:
进程=程序对应的文件内容(struct)+相关数据结构(比如优先级队列)
OS如何管理进程?先描述再组织
其实OS中的描述也是这样,在每个进程开始时,都会创建对应的PCB进程控制块
PCB的本质就是task_struct结构体,进程的所有属性都存储到了这个结构体中
所有,有了PCB,所有的进程管理都与程序本身无关,而与PCB强相关
PCB包含的所有信息:
- 标示符: 描述本进程的唯一标示符,用来区别其他进程。
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- 其他信息
不急,下文将会详细地说明它们分别的含义
进行管理图示:
PCB的基本数据说明
查看进程
linux下,我们可以使用ps命令来查看进程
有两种指令:
ps axj | grep “你的程序名”
ps -l查看运行中进程的详细信息
因为linux下一切皆文件,所以进程的详细信息都被保存在一个proc文件夹中
演示:
我们先写出一个死循环,一直运行的程序
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>int main()
{while(1){printf("hello,pid:%d,ppid:%d\n",getpid(),getppid()); sleep(1);}return 0;
}
注:unistd.h用于调用sleep休眠函数
sys/types.h用于调用pid(后文讲解)
我们把这个程序取名为test,使其开始运行
然后打开新的对话框,查看
或者,利用文件查找
PCB基本数据之标识符
每个进程都有一个独一无二的标识符,就像人的名字一样,用来区分不同的进程
在程序中,我们使用getpid函数来获取当前进程的pid,使用getppid来获取它的父进程(后文讲解)的id
PCB基本数据之上下文数据
我们知道,一个电脑只有1个cpu,而我们的电脑可能会同时存在几十个进程,它们真的是同时运行的吗?
其实不是的,OS规定了每个程序单次运行的时间片,也就是每个进程只能运行这么多时间,然后立刻切换到下一个进程,但是由于进程之间的切换极快,(大概是纳秒ns级别),所以看起来像在一起运行一样,这种模式我们也称作并发
而上下文数据,就是保存每次进程在运行时生成的临时数据,可以实现进程切换回来时,立刻恢复到切换前的状态继续运行此程序
利用fork来认识父子进程
我们知道,我们每个进程都有自己的父进程,父进程负责回收管理其对应的子进程,而有些进程的父进程可以直接是OS本身(pid为1)
而我们可以查看我们上面程序的父进程的信息
它的父进程是bash(bash是shell外壳程序的一种),其实,基本所有命令行程序的父进程都是bash
fork是一种可以创建子进程的函数,它的返回值是一个int
用fork接受返回值,可能会出现意料之外的情况
测试代码:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>int main(){int ret=fork();if(ret==0){printf("hello world!\n");}else{printf("can you see me?\n");}sleep(1); return 0;}
一般我们的函数只有一个返回值,但是我们却发现我们的程序却两个条件都执行了!我们在语言层次上根本不能理解这种行为
其实,正是因为我们的程序创建了一个子进行,它们在fork处进行的分流,分别执行他们各自的语句罢了,而它们接受到的返回值分别是不一样的
我们可以验证一下:
int main(){int ret=fork();if(ret==0){while(1){printf("hello world!,pid:%d,ppid:%d\n",getpid(),getppid());sleep(1);}}else{while(1){printf("can you see me?,pid:%d,ppid%d\n",getpid(),getppid());sleep(2);}} return 0;}
我们发现,helloworld的父进程刚好就是can you see me
那么,父子进程有什么相互联系呢?
- 父子进程之间的数据是共享的,但它们又不完全共用一个空间,而是会发生写时拷贝,简单验证:
#include<stdio.h>#include<unistd.h>#include<sys/types.h>//两个进程都打印创建进程之前的数据int main(){int a=10;int ret=fork();if(ret==0){printf("%d\n",a);sleep(1);}else{printf("%d\n",a);sleep(1); }return 0;}
虽然共享同一数据,但父子进程之间的数据不会直接影响的验证
#include<stdio.h>#include<unistd.h>#include<sys/types.h>//两个进程都打印创建进程之前的数据int main(){int a=10;int ret=fork();if(ret==0){a=20;//修改aprintf("%d\n",a);sleep(1);}else{printf("%d\n",a);sleep(1); }return 0;}
fork的返回值问题:如果子进程创建失败,给父进程返回-1。如果创建成功,给父进程返回子进程pid,给子进程返回0
为什么要创建子进程?多个进程运行一个代码,提高效率
fork子进程后,一般要用ifelse分流,让它们分别执行不同的功能
PCB基本数据之进程状态
进程状态可以方便OS快速判断进程的状态,方便使其完成各种功能,本质是一种分类
linux中的进程一般有以下状态:
- R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列
里。 - S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠
(interruptible sleep))。 - D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的
进程通常会等待IO的结束。 - T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可
以通过发送 SIGCONT 信号让进程继续运行。 - X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态
回到我们的第一个程序,状态码在这里显示:
睡眠状态和运行状态
- 运行状态:其实一个程序在运行状态,并不代表它一定在运行,它也可能在cpu的等待队列中,在时间片之外罢了,也就是在并发中罢了
- 睡眠状态:如果一个程序需要的资源没有准备好,那么程序将会睡眠,等待资源准备就绪了它才会再次运行
演示:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>int main()
{while(1){printf("hello,pid:%d,ppid:%d\n",getpid(),getppid()); //sleep(1);//我们删除它的休眠}return 0;
}
程序打印的这么快,为什么它仍然在休眠状态呢?
因为我们的IO设备的相应其实相对于cpu很慢(cpu在纳秒级而io在毫秒级)
所以cpu相应完后io设备却还没准备就绪,所以程序在进行休眠
但相对我们人来说,cpu的切换实在太快,所以我们可能会认为程序一直在运行,其实它本来大部分时间在休眠
官方定义:
把程序从等待队列放在运行队列中,就叫唤醒
等待队列中的程序处于睡眠态
运行队列中的程序处于运行态
特殊状态之僵尸状态
当一个进程需要退出时,系统会回收这个进程的资源,然后进程就进入了死亡
而linux却不能随便让一个程序死亡,它需要先确认退出原因,确认后才会允许死亡
而一个进程在发出死亡请求后,linux确认死亡原因会有一个时间段,这个进程在这个时间段就会被置为僵尸状态
验证:根据子进程的维护由父进程管理,所以我们先让子进程死亡,然后不让父进程正常退出
先让这个程序运行
int main(){int ret=fork();if(ret==0){while(1){printf("hello world!,pid:%d,ppid:%d\n",getpid(),getppid());sleep(1);}}else{while(1){printf("can you see me?,pid:%d,ppid%d\n",getpid(),getppid());sleep(2);}}return 0; }
然后杀掉子进程
然后这个子进程就会进入z状态(僵尸状态)
根本原因是父进程在运行是无法读取子进程的状态,所以无法回收子进程
僵尸进程我们需要尽量避免,因为会导致过度占用空间和内存泄漏
特殊进程之孤儿进程
父子进程在同时运行时,父进程先退出,而子进程会因为没有父进程而被置为孤儿进程
孤儿进程将会被1号进程(OS本身)领养
PCB基本数据之优先级
为什么要有优先级?本质是因为资源太少而进程太多!
所以OS会把优先级高的进程赋予其优先使用资源的权限,这样优先级可以把重要的和不重要的进程分开,以提高OS的效率
如何查看?
中间的PRI和NI就是跟优先级有关的
PRI代表进行的优先级,该值直接决定一个程序的优先等级
PRI值默认为80,值越小,说明其优先级越高
NI是优先级的校正值,可以人为的修改,PRI的最终值也取决于NI值(PRI=80+NI)
如何修改优先级?
输入top后按r->输入进程pid->输入nice
强烈建议大家不要随意修改进程优先级,会导致进程饥饿问题
linux篇(四)linux进程(上)相关推荐
- linux ttf,Linux篇:linux安装字体
01 前言 今天在处理confluence预览文件乱码时,解决问题需要在linux安装windows相关的字体,此篇文章是记录如何在linux下安装字体格式 02 安装过程 查看已安装的字体格式命令f ...
- Hacker基础之Linux篇——基础Linux命令二
我们继续学习Linux命令 mv mv命令是move的缩写,可以用来移动文件或者将文件改名(move (rename) files). 是Linux系统下常用的命令,经常用来备份文件或者目录. mv命 ...
- linux篇---解决 Linux 系统,出现“不在sudoers文件中,此事将被报告”的问题
解决 Linux 系统,出现"不在sudoers文件中,此事将被报告"的问题 我在使用个人用户(非root用户)时,在添加用户,使用sudo命令来执行的时候,需要验证当前用户的密码 ...
- linux内核调用( )为进程创建虚存区_Linux内核分析-总结篇(九)
本次内容作为Linux内核的总结内容,主要涉及对Linux系统的总体的一些理解,同时将之前的一些总结贴出来作为大家的一个索引,希望笔者一样的菜鸟有一些帮助和入门的作用.从一个初学者的角度对Linux有 ...
- (转载)Linux内核源代码情景分析---第四章 进程与进程调度
原文地址: http://blog.sina.com.cn/s/blog_6b94d5680101vkiv.html 引用这篇文章主要是因为,你经常会发现不root的情况下,完全无法ping通,而又不 ...
- Linux高性能服务器开发——进程篇
本文主要是学习Linux高性能服务器开发需要提前了解的知识,后续还会涉及到虚拟内存方面的内容,各位看官可以多了解了解,看到文章内有将的不清楚或者讲错的地方请各位一定留言,我看到后会第一时间验证并修正的 ...
- 24丨基础篇:Linux磁盘I-O是怎么工作的(上)
上一节,我们学习了 Linux 文件系统的工作原理.简单回顾一下,文件系统是对存储设备上的文件,进行组织管理的一种机制.而 Linux 在各种文件系统实现上,又抽象了一层虚拟文件系统 VFS,它定义了 ...
- linux内核调度 0号进程,Linux内核源代码情景分析---第四章 进程与进程调度
4.1 进程四要素 什么是进程? 1:有一段代码段供其执行,这代码段不一定是进程所专用,可以与其他进程公用. 2:每个进程有其专用的系统空间的堆栈(栈)[这个栈是进程起码的"私有财产&quo ...
- linux进程管理内存管理,Linux专业知识四:Linux系统进程管理及查看内存
本文主讲Linux专业知识之Linux系统进程管理及查看内存的情况,以Redhat RHEL7操作系统为例. 一.进程 程序与进程:程序是静态的(文件),进程是动态的(运行的程序). 进程和线程:一个 ...
- Linux进程(上)
一. 操作系统小知识 注:此笔记的重点不是讲操作系统,故操作系统知识比较粗浅,只是介绍. 1. 进程和程序 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源. 进程,是活跃的(动态的)的程序,占 ...
最新文章
- 重新编号_武汉黄陂公交线路PW、PG、PZ……分不清?别急,就要重新编号啦
- 剑三服务器维护是因为人太多吗,剑网三怀旧服两类服务器哪家强?一类人多且热闹,一类人少却稳定...
- 报名领奖|云栖大会,10月19-22日杭州不见不散!
- java testng 源代码_根据测试用例的java源码自动生成TestNG的XML文件
- eclipse安装web插件、安装centos版本的idea
- windows多线程同步互斥--总结
- 函数的实参 函数的形参 闭包 js 1
- Linux虚拟文件系统:数据结构与文件系统注册、文件打开读写
- html语言汇总,第三讲HTML语言全面介绍汇总.ppt
- php对象的表示方法,PHP对象相关知识总结
- Spring入门之IOC
- paip.网站扫描安全工具hp WebInspect 使用指南
- Powerpoint中VBA编程技巧
- 雷诺方程推导及FDM求解
- 小汪Hibernate 学习之一 Hibernate 小例子
- 如何下载 Chrome 应用商店的 .crx 文件
- Unity Bone weights do not match bones.
- 【Spring Boot】构造、访问Restful Webservice与定时任务
- e5cz温控表中文说明书_欧姆龙温控器e5cz说明书 OMRON温控表E5EC说明书
- 严重性 代码 说明 项目 文件 行 禁止显示状态 警告 CS8032 无法从...创建分析器...的实例: 未能加载文件或程序集...或它的某一个依赖项。系统找不到指定的文件
热门文章
- 图神经网络论文阅读(十六) GraLSP: Graph Neural Networks with Local Structural Patterns,AAAI 2020
- python练习题答案,python练习题-答案
- 操作系统——文件目录+对磁盘的管理
- apoc插件安装说明
- Openoffice安装中文字体
- 探究ExecutorService的invokeAll()方法获取的结果是否具有顺序性
- 易推宝网站推广关键词组合设置有什么技巧?
- 质量意识培训 故事之3
- 禁用和启用 Chrome 浏览器自动更新服务的批处理脚本
- c语言int转换为十六进制,C语言将int型数据转换为十六进制的字符串