这次作业主要基于Linux-0.12的源代码,分析Linux是如何组织进程,进程的状态之间是如何转换,以及进程是如何调度的。

一. 进程的概念:

  1.进程就是:程序在数据集合上的一次运行过程,是系统进行资源分配和调度的独立单位。

  2.对进程的静态描述为:是一个数据集合,以及在其上运行的程序。

  3.我本来认为进程与程序是差不多的东西,但发现他们其实并不一样,进程是一个动态的概念,不同于程序又依赖于程序,既有联系又有区别,进程具备程序不具备的特征,比如:

   1).动态特征:进程具有生命周期,创建之后才产生,调度时运行,得不到资源就发生阻塞,撤销之后就消亡。进程本身就是一个执行过程,程序,却仅仅是个静态文本(指令合集);

   2).并发特征:多个进程实体,同存于主存中,能在一段时间内同时运行。由此可见进程的并发特征是其第二基本特征,程序不具备并发性;

   3).独立特征:进程是系统进行资源分配和调度的一个基本单位,程序段是不可做为独立单位接收资源分配和调度的;

   4).结构特征(静态特征):为了描述进程的运动变化过程系统为每一个进程配置了一个进程控制块(PCB:Process Control Block),这样静态的看或从结构上看,进程就由正文段,数据集合(结构)以及PCB三部分组成,一般将这三部分组成结构成为进程映像:

进程映像

  

   5). 异步特征:各进程按照其各自独立的,不可预知的速度向前推进。

  In a word, 进程 == 可以和其他程序并发执行的 程序的 一次执行。

二. Linux操作系统是怎么组织进程的:

  1. Linux是一个多任务的开放式操作系统,进程就是许多分离的任务,每一个进程彼此独立,并通过进程间的通信机制实现进程之间的同步与互斥。在Linux系统中,进程与任务是相同的概念。

  2. 系统中有许多进程,Linux要对其进行管理和调度,就要通过存放在系统数据段中的进程控制信息,其中最重要的就是task_struct数据结构。

      • 正文段:是具有可再入性的代码组成的程序(可再入程序也称纯代码,可同时被多个进程或程序所共享的程序),因此对用不同的数据集,可以构成不同的进程,所以正文段是可以调用但是不可以修改的,一般情况下是由系统程序组成。
      • 进程控制块(PCB):PCB中记录了用于描述进程情况及控制进程运行所需的全部属性信息。系统通过PCB感知进程的存在,是进程进行控制存在的唯一标识。系统根据PCB来对并发执行的进程进行控制和管理。系统会在创建进程时就创建该进程的PCB,在撤销一个进程时就撤销其PCB。当操作系统要调用进程执行时。需要从该进程的PCB中查询其现行状态机优先级等调度参数,在调度到某进程后,要根据PCB中保存的处理机状态信息去设置进程回复运行的现场,并根据其PCB中的进程和数据的内存地址来找到程序和数据;进程在执行过程中,当需要与其它进程通信时,也需要访问其PCB;当进程因某种原因而暂停执行时,需要将断点的现场信息保存在其PCB中。
      • 数据集合:由数据所组成的集合。 
PCB通常包含的内容
进程描述信息 进程控制和管理信息 资源分配清单 处理机相关信息
进程标识符(PID) 进程当前状态 代码段指针 通用寄存器值
用户标识符(UID) 进程优先级 数据段指针 地址寄存器值  

  3. 在linux内核代码定义了task_struct 数据结构,包含了一个进程所有的信息:

 struct task_struct {
/* these are hardcoded - don't touch */
long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter;
long priority;
long signal;
struct sigaction sigaction[];
long blocked; /* bitmap of masked signals */
/* various fields */
int exit_code;
unsigned long start_code,end_code,end_data,brk,start_stack;
long pid,pgrp,session,leader;
int groups[NGROUPS];
/*
* pointers to parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->p_pptr->pid)
*/
struct task_struct *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
unsigned long timeout,alarm;
long utime,stime,cutime,cstime,start_time;
struct rlimit rlim[RLIM_NLIMITS];
unsigned int flags; /* per process flags, defined below */
unsigned short used_math;
/* file system info */
int tty; /* -1 if no tty, so it must be signed */
unsigned short umask;
struct m_inode * pwd;
struct m_inode * root;
struct m_inode * executable;
struct m_inode * library;
unsigned long close_on_exec;
struct file * filp[NR_OPEN];
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
struct desc_struct ldt[];
/* tss for this task */
struct tss_struct tss;
}; 

三. 进程状态如何转换(给出进程状态转换图):

  1. 在多道程序系统中,多个进程都要在CPU上运行,有时还要申请使用其他资源,由于资源的宝贵性,使得并非每个进程都能立即得到资源,从而导致进程之间的竞争(竞争是由两个以上进程以显式或隐式的方式共享资源而引起的状态)。

  2. 一般情况下进程有三种状态,就绪(资源,CPU),运行(资源,CPU),阻塞(资源,CPU)。

  3. Linux在每个进程的task_struct结构中,定义了state域来描述进程的调度状态,共有五种,定义如下:

 #define TASK_RUNNING        0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 3
#define TASK_STOPPED 4
#define TASK_RUNNING        0

    1)运行态或可运行态:已经占有CPU正在运行,或者正处于运行队列中,等待着系统的进程调度程序schedule()将CPU分配给它。系统中有一个运行队列run_queue,容纳了所有处于可运行状态的进程,当前正在运行的进程也一直处于该队列中,由全局变量current指向。

    *该状态是Linux与一般操作系统的区别,在其他操作系统中,只有正在使用CPU的进程才处于运行状态,其他都处于就绪状态。

#define TASK_INTERRUPTIBLE    1

    2)进程可中断的睡眠态:因等待某一事件或某种资源而加入等待队列,等待资源有效时被唤醒。

#define TASK_UNINTERRUPTIBLE    2

    3)进程不可中断的睡眠态:此时的进程因为硬件条件的不满足而睡眠,处于等待队列中,在任何情况下都不能被打断,除非通过特定的方式来唤醒,比如通过唤醒函数wake_up()等。

#define TASK_ZOMBIE        3

    4)进程僵死状态(终结态):当进程使用系统调用exit自我消亡时,将state设为此状态。发送信号给父进程并释放占有的系统资源,但它的task_struct结构仍未释放。父进程通过系统调用wait收集其中包含的出口码及一些计时信息后,释放他的task_struct结构。

#define TASK_STOPPED        4

    5)进程被暂停运行状态:进程暂时停止运行来接受某种处理,通过其他进程的信号才能唤醒。

 4. 进程状态的转换:

    1).Linux中用户进程是由父进程执行系统调用fork()或者clone()等创建的。这些系统调用都通过调用do_fork()函数来完成子进程的创建。do_fork()函数创建一个新进程,为其创建一个task_struct结构,继承父进程现有的资源,子进程创建后的状态为TASK_RUNNING态,父进程将它挂入到运行队列run_queue中,等待处理器的分配。

    2).获得CPU而正在运行的进程如果申请不到某个资源,则调用函数sleep_on()或interruptible_sleep_on()转入睡眠,其task_struct结构从run_queue队列移入xiangying的等待队列。如果调用sleep_on(),则其状态转入不可中断的睡眠态TASK_UNINTERRUPTIBLE,如果调用interruptible_sleep_on(),则其状态转入可中断睡眠态TASK_INTERRUPTIBLE 。无论转入哪种睡眠状态,都将调用schedule()函数把睡眠进程释放的CPU重新分配给run_queue队列中的某个可运行的进程。

    3).转入TASK_INTERRUPTIBLE的睡眠进程在它申请的资源有效时将被唤醒(被某函数,信号或者中断),而转入TASK_UNINTERRUPTIBLE的睡眠进程只有在它申请的资源有效时被唤醒,不能被信号,定时器中断唤醒。这些被唤醒的进程都转入TASK_RUNNING状态, 并进入run_queue队列。

    4).当进程收到暂停或停止信号时,状态转入TASK_STOPPED ,暂停运行,CPU重新分配给run_queue队列中的其他可运行进程,只有通过其他进程发送恢复信号,才能把TASK_STOPPED 进程唤醒,重新进入run_queue队列。

    5).当进程运行完成,执行系统调用exit()或do_exit()时,进程转入僵死态TASK_ZOMBIE,释放所占有的系统资源,同时启动schedule()把CPU分配给run_queue队列中的其他进程。

  5. 进程状态转换图:

四. 进程是如何调度的:

  1. Linux主要采用了基于优先权的时间片轮转法为进程分配CPU。按照这种调度方法,系统给每个运行进程分配一个时间片,而优先权的大小又决定了哪个进程被调度运行(Linux的进程调度并不局限于某一种调度策略,它融合了基于优先权的轮转法调度,基于优先权的先进先出调度以及多级反馈轮转调度的策略,具有很高的综合性)。 

  2.

       long priority;

    1). 进程(实时和普通)的优先级反映了进程相对于其他进程的可选择度,也是系统每次允许进程运行的时间。

       long counter;

    2). 进程运行所剩余的时间片,每次时钟中断发生时,值-1,直到为0,counter = 0表示进程的时间片已经用完,要停止运行。

  3. Linux进程调度时机主要有:

1). 进程状态转换的时时。如进程终止、进程睡眠;

2). 当前进程的时间片用完时(current->counter=0),要重新选择一个进程;

3). 设备驱动程序,直接调用schedule();

4). 进程从中断、异常及系统调用处理后返回到用户态时。

  4. Linux-0.12 schedule()如下:

void schedule(void)
{
int i,next,c;
struct task_struct ** p;
/*有信号来时,唤醒进程*/
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p) {
if ((*p)->timeout && (*p)->timeout < jiffies) {
(*p)->timeout = ;
if ((*p)->state == TASK_INTERRUPTIBLE)
(*p)->state = TASK_RUNNING;
}
if ((*p)->alarm && (*p)->alarm < jiffies) {
(*p)->signal |= (<<(SIGALRM-));
(*p)->alarm = ;
}
if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
(*p)->state==TASK_INTERRUPTIBLE)
(*p)->state=TASK_RUNNING;
}
while () {
c = -;
next = ;
i = NR_TASKS;
p = &task[NR_TASKS];
while (--i) {
if (!*--p)
continue;
if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
c = (*p)->counter, next = i;
}
if (c) break;
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p)
(*p)->counter = ((*p)->counter >> ) +
(*p)->priority;
}
switch_to(next);
}

五. 我对Linux操作系统进程模型的看法:

  Linux支持多进程,进程控制块task_struct结构包括进程标识,进程状态,进程调度,进程指针,文件管理和虚存管理等,Linux对普通进程采用的是优先级调度策略。尽量公平合理的进行各进程之间的调度。

六.  参考资料:

https://blog.csdn.net/hgnuxc_1993/article/details/54847732

http://www.docin.com/p-820504201.html

https://blog.csdn.net/songjinshi/article/details/23262923

操作系统原理与分析(第一版);曹聪,范廉明 著;科学出版社

第一次作业:基于Linux-0.12的进程分析的更多相关文章

  1. Linux 0.12 内核管理存储器

    Linux 0.12 内核管理存储器 其分段,用分段的机制把进程间的虚拟地址分隔开. 每一个进程都有一张段表LDT.整个系统有一张GDT表.且整个系统仅仅有一个总页表. 其地址翻译过程为: 程序中给出 ...

  2. 第一次作业:基于Linux 4.5的进程模型与调度器分析

    1.操作系统是怎么组织进程的? 1.1什么是线程,什么是进程: 刚接触时可能经常会将这两个东西搞混.简单一点的说,进程是一个大工程,线程则是这个大工程中每个小地方需要做的东西(在linux下看作&qu ...

  3. 《linux 内核全然剖析》编译linux 0.12 内核 Ubuntu 64bits 环境

    我×.. . 最终好了,大概3 4个小时吧...各种毛刺问题.终究还是闯过来了.. .. ubuntu2@ubuntu:~/Downloads/linux-0.00-050613/linux-0.00 ...

  4. Linux内核的idle进程分析

    1. idle是什么 简单的说idle是一个进程,其pid号为 0.其前身是系统创建的第一个进程.也是唯一一个没有通过fork()产生的进程. 在smp系统中,每一个处理器单元有独立的一个执行队列,而 ...

  5. 转:基于 linux 平台的 libpcap 源代码分析

    libpcap 是 unix/linux 平台下的网络数据包捕获函数包,大多数网络监控软件都以它为基础.Libpcap 可以在绝大多数类 unix 平台下工作,本文分析了 libpcap 在 linu ...

  6. iOS开发--基于AFNetWorking3.0的图片缓存分析

    图片在APP中占有重要的角色,对图片做好缓存是重要的一项工作.[TOC] 理论 不喜欢理论的可以直接跳到下面的Demo实践部分 缓存介绍 缓存按照保存位置可以分为两类:内存缓存.硬盘缓存(FMDB.C ...

  7. 【转载】基于AFNetWorking3.0的图片缓存分析

    原文出处: Yasin的简书 理论 不喜欢理论的可以直接跳到下面的Demo实践部分 缓存介绍 缓存按照保存位置可以分为两类:内存缓存.硬盘缓存(FMDB.CoreData…).我们常说的网络请求缓存包 ...

  8. 基于Linux平台的libpcap源码分析和优化

    目录 1..... libpcap简介... 1 2..... libpcap捕包过程... 2 2.1        数据包基本捕包流程... 2 2.2        libpcap捕包过程... ...

  9. 第一次作业:基于Linux操作系统深入源码进程模型分析

    1.Linux操作系统的简易介绍 Linux系统一般有4个主要部分:内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使 ...

随机推荐

  1. Android CheckBox大小调整

    关键是: android:scaleX="0.5" <CheckBox android:id="@+id/checkBox1" android:layou ...

  2. TreeView控件概述、属性与方法

    1.作用:用于显示Node结点的分层列表.2.添加到控件箱菜单命令:工程 | 部件,在部件对话框中选择:Microsoft Windows Common Controls 6.03.TreeView控 ...

  3. Shell: extract more from listener.log (分析oracle监听日志)

    最近遇到了两起数据库连接数不足的问题, 通常都会预留一些会话增加的情况, 但在一些特殊情况下如连接风暴(logon storm), 如果在监听中没有做rate限流,对数据库来说巨大的冲击可能会导致数据 ...

  4. mysql-5.7 持久化统计信息详解

    一.持久化统计信息的意义: 统计信息用于指导mysql生成执行计划,执行计划的准确与否直接影响到SQL的执行效率:如果mysql一重启 之前的统计信息就没有了,那么当SQL语句来临时,那么mysql就 ...

  5. [翻译] ValueTrackingSlider

    ValueTrackingSlider What is it? A UISlider Subclass that displays live values in a popUpView. It’s i ...

  6. 解决华为交换机S5700无法解除ip/Mac绑定的问题

    今天同事离职,需要解除他的个人笔记本Mac与ip的绑定 首先进入系统用户视图,然后进入vlanif4,解除151绑定 system-view interface vlanif 4 undo dhcp ...

  7. css实现梯形

    使用伪元素before和after分别在矩形元素前后加三角形或者直接设置border 使用3d旋转矩形,使之看起来像矩形 <html> <head> <meta char ...

  8. javascript 大中小括号的区别

    小括号 JavaScript中小括号有五种语义 语义1,函数声明时参数表 function func(arg1,arg2){ // ... } 语义2,和一些语句联合使用以达到某些限定作用 // 和f ...

  9. 【2017.12.05 智能驾驶/汽车电子】转载:如何成为一名无人驾驶工程师 By刘少山

    之前对无人驾驶的理解就是通过刘少山老师的书:第一本无人驾驶技术书 通读之后,对智能驾驶有了一个初步的认识,如感知.决策.控制都涉及哪些领域,有哪些可以利用的技术: 但经过一段时间的实践,发现即使是在我 ...

  10. SDN上机第二次作业

    SDN第二次上机作业 1.安装floodlight 参考链接:http://www.sdnlab.com/19189.html 2.生成拓扑并连接控制器floodlight,利用控制器floodlig ...