第一次作业:深入源码分析进程模型(代码片段)

QianQiYing QianQiYing     2022-11-07     802

关键词:

写在最前:

  • 本次使用的内核源码:Linux 0.12版本。
  • 这篇文章在讲什么:旨在利用源码来帮助理解操作系统中进程这一概念。

  进程:这是对正在运行程序的一个抽象。操作系统的其它所有内容都是围绕着进程的概念展开的。一个进程就是一个正在执行程序的实例。

    

一.操作系统是如何组织进程的

  1.进程数

  在sched.h中,有如下语句:

   1 #define NR_TASKS 64  

  该语句定义了系统中的最多任务(进程)数,即:在同一瞬间,系统中最多可有64个进程。

  

  2. 进程标识符

  • 在sched.h中有一个进程的结构体:task_struct。在结构体中,定义了进程的标识符(唯一):

   1 long pid;  

  • 注:任务0是“空闲”任务,当没有其他任务可以运行时会被调用。 它不能被杀死,它无法入睡。 任务[0]中的\'状态\'信息从不使用。
  • 该结构体的完整定义如下:
 1 struct task_struct 
 2 /* these are hardcoded - don\'t touch */
 3     long state;        //任务的运行状态,-1 不可运行, 0 可运行(就绪), >0 已停止
 4     long counter;    //任务运行时间计数
 5     long priority;
 6     long signal;
 7     struct sigaction sigaction[32];
 8     long blocked;    /* bitmap of masked signals */
 9 /* various fields */
10     int exit_code;
11     unsigned long start_code,end_code,end_data,brk,start_stack;
12     long pid,pgrp,session,leader;    //从左到右依次为:进程标识号(进程号)、进程组号、会话号、会话首领
13     int    groups[NGROUPS];    //进程所属组号,一个进程可以属于多个组
14     /* 
15      * pointers to parent process, youngest child, younger sibling,
16      * older sibling, respectively.  (p->father can be replaced with 
17      * p->p_pptr->pid)
18      */
19     //从左到右:指向父进程的指针、指向最新子进程的指针、指向比自己后创建的相邻进程的指针、指向比自己早创建的相邻进程的指针。
20     struct task_struct    *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
21     unsigned short uid,euid,suid;
22     unsigned short gid,egid,sgid;
23     unsigned long timeout,alarm;
24     long utime,stime,cutime,cstime,start_time;
25     struct rlimit rlim[RLIM_NLIMITS]; 
26     unsigned int flags;    /* per process flags, defined below */
27     unsigned short used_math;
28 /* file system info */
29     int tty;        /* -1 if no tty, so it must be signed */
30     unsigned short umask;
31     struct m_inode * pwd;
32     struct m_inode * root;
33     struct m_inode * executable;
34     struct m_inode * library;
35     unsigned long close_on_exec;
36     struct file * filp[NR_OPEN];
37 /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
38     struct desc_struct ldt[3];
39 /* tss for this task */
40     struct tss_struct tss;
41 ;

 

 

  3. 进程可能的状态的定义

1 //这里定义了进程运行时可能处于的状态
2 #define TASK_RUNNING                 0  //进程正在运行或已准备就绪
3 #define TASK_INTERRUPTIBLE     1  //进程处于可中断等待状态
4 #define TASK_UNINTERRUPTIBLE     2  //进程处于不可中断等待状态,主要用于I/O操作等待
5 #define TASK_ZOMBIE                          3  //进程处于僵死状态,已经停止运行,但父进程还没发信号。
6 #define TASK_STOPPED                        4  //进程已停止

 

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

  •  进程的三个状态:

            运行态:该时刻进程实际占有CPU。

    就绪态:可运行,但因为其它进程正在运行而暂时停止。

    阻塞态:除非某种外部时间发生,否则进程不能运行。

  • 进程状态转换图:

          

  • 转换关系图解释如下:

     1. 进程因为等待输入而被阻止。

     2. 调度程序选择另一个进程。

     3. 调度程序选择这个进程。

     4. 出现有效输入。

 

三.进程是如何调度的

  调度当系统中就绪的进程数大于系统中可用的CPU数时,可用的CPU必须选择下一个要运行的进程。在操作系统中,完成选择工作的这一部分称为调度程序(scheduler),该程序使用的算法称为调度算法(scheduling algorithm)

  在Linux 0.12中采用基于优先级排队的调度策略。

  schedule()函数首先扫描任务数组。通过比较每个就绪态(TASK RUNNING) 任务的运行时间递减滴答计数counter 的值,来确定当前哪个进程运行的时间最少。哪一个的值大,就表示运行时间还不长,于是就选中该进程,并使用任务切换宏函数切换到该进程运行。 

 

  源码:

 1 void schedule(void)
 2 
 3     int i,next,c;
 4     struct task_struct ** p;  //任务结构指针的指针
 5 
 6 /* check alarm, wake up any interruptible tasks that have got a signal */
 7 
 8     for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
 9         if (*p) 
10             if ((*p)->timeout && (*p)->timeout < jiffies) 
11                 (*p)->timeout = 0;
12                 if ((*p)->state == TASK_INTERRUPTIBLE)
13                     (*p)->state = TASK_RUNNING;
14             
15             if ((*p)->alarm && (*p)->alarm < jiffies) 
16                 (*p)->signal |= (1<<(SIGALRM-1));
17                 (*p)->alarm = 0;
18             
19             if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
20             (*p)->state==TASK_INTERRUPTIBLE)
21                 (*p)->state=TASK_RUNNING;
22         
23 
24 /* this is the scheduler proper: */
25 //-------------------这是调度程序的主要部分-------------------
26     while (1) 
27         c = -1;
28         next = 0;
29         i = NR_TASKS;
30         p = &task[NR_TASKS];
31         while (--i) 
32             if (!*--p)
33                 continue;
34             if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
35                 c = (*p)->counter, next = i;
36         
37         if (c) break;
38         for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
39             if (*p)
40                 (*p)->counter = ((*p)->counter >> 1) +
41                         (*p)->priority;
42     
43     switch_to(next);
44 

 

四.谈谈自己对该操作系统进程模型的看法  

    对于Linux0.12 来讲,系统最多可有64 个进程同时存在。程序使用进程标识号(pid) 来标识每个进程。对于只有一个CPU 的系统,在某一瞬间只能有一个进程真正在运行。内核通过调度程序分时调度各个进程运行。 利用分时技术,在Linux 操作系统上可以(伪)同时运行多个进程。分时技术的基本原理是把CPU 的运行时间划分成个个规定长度的时间片(time slice),让每个进程在一个时间片内运行。当进程的时间片用完时系统就利用调度程序切换到另一个进程去运行。因此实际上对于具有单个CPU 的机器来说某一时刻只能运行一个进程。但由于每个进程运行的时间片很短(例如15 个系统滴答=l50ms),所以表面看来好像所有进程在同时运行着。
  调度的实现有很多不同的算法,Linux 0.12版本较为早期了,后期的版本代码量似乎大了很多,有关进程调度的也一定更为完善。

 

最后:

参考资料: 

  • Linux内核完全剖析-基于0.12内核 (赵炯) 中文pdf扫描版   下载地址:http://www.jb51.net/books/415345.html  ;
  • 《现代操作系统》第四版。

 

第一次作业:深入源码分析进程模型(代码片段)

前言:源代码下载地址:https://elixir.bootlin.com/linux/v2.6.39/source  一、操作系统是怎么组织进程的 1.进程是什么?进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位... 查看详情

第一次作业:深入源码分析进程模型(代码片段)

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

第一次作业:深入源码分析进程模型(代码片段)

前言:     这是一篇关于linux操作系统的简单介绍。linux本身不能算是操作系统,只是一个内核,基于linux内核的操作系统有很多,比如流行的android,ubuntu,红旗linux等等。Linux以它的高效性和灵活性著称。它能... 查看详情

第一次作业:深入源码分析进程模型

挑选一个开源的操作系统,Linux深入源码分析其进程模型,具体包含如下内容:1.操作系统是怎么组织进程的:以下参考了文章编号1672-5913(2009)14-0027-01举的代码例子使用了sort()调用创建进程:      #includ... 查看详情

第一次作业:深入源码分析进程模型

本文针对linux罗列一些个人的理解或看法这是本人第一次写博客,有写得不好的地方请见谅。进程是什么当我们打开任务管理器的时候,我们可以看到这样的画面:从这里我们可以看到进程的页面,当然这样的理解是浅显的,详... 查看详情

第一次作业:深入源码分析进程模型

1.简介本文的内容是基于Linux2.6的源码,深入分析进程模型。什么是进程操作系统是怎么组织进程的进程状态如何转换进程是如何调度的谈谈自己对该操作系统进程模型的看法2.什么是进程 进程的概念:进程是处于执行期的程... 查看详情

第一次作业:深入源码分析进程模型

前言:这个是老师布置的作业,一什么是进程1.进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是... 查看详情

第一次作业:深入源码分析xv6进程模型

1.进程1.1进程的概念1)狭义定义:进程是正在运行的程序的实例。2) 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本... 查看详情

第一次作业-(代码片段)

1.作业内容挑选一个开源的操作系统,深入源码分析其进程模型,具体包含如下内容:操作系统是怎么组织进程的进程状态如何转换(给出进程状态转换图)进程是如何调度的谈谈自己对该操作系统进程模型的看法一.操作系统是... 查看详情

深入源码分析进程模型(代码片段)

1.操作系统是怎么组织进程的structtask_struct....../*进程状态*/volatilelongstate;/*指向内核栈*/void*stack;/*用于加入进程链表*/structlist_headtasks;....../*指向该进程的内存区描述符*/structmm_struct*mm,*active_mm;......../*进程ID,每个进程(线程)的PID都... 查看详情

第一次作业:基于orange'sos系统的进程模型分析与心得体会(代码片段)

1一.操作系统进程概念模型与进程控制块概念浅析1.什么是进程?        图1-1(WIN10系统任务管理器对进程管理的图形化界面)     计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源... 查看详情

lamp实验作业详细过程(代码片段)

1、请描述一次完整的http请求处理过程;由客户端发起请求给服务端,服务端接收到请求后解析http报文内容,把处理完成后的内容反馈给客户端,再将每次请求记录在日志中。2、httpd所支持的处理模型有哪些,他们的分别使用于... 查看详情

深入分析dart集合操作符源码(代码片段)

上篇文章我们详细介绍了有关Dart集合操作符函数的基本使用,那么这篇文章将会从源码角度,分析其内部原理。通过它你将会理解什么是惰性迭代器。1.forEach函数源码解析voidforEach(voidf(Eelement))//可以看到在forEach内部实际上就是... 查看详情

深入分析dart集合操作符源码(代码片段)

上篇文章我们详细介绍了有关Dart集合操作符函数的基本使用,那么这篇文章将会从源码角度,分析其内部原理。通过它你将会理解什么是惰性迭代器。1.forEach函数源码解析voidforEach(voidf(Eelement))//可以看到在forEach内部实际上就是... 查看详情

python课设:作业统计管理系统,源码+实验报告+论文需要自取(代码片段)

...下一些:学生提交作业情况slsx:学号,姓名,第一次作业,第二次作业 查看详情

flutter命令本质之fluttertools机制源码深入分析(代码片段)

...文章连载~《FlutterAndroid工程结构及应用层编译源码深入分析》《Flutter命令本质之Fluttertools机制源码深入分析》《Flutter的runApp与三棵树诞生流程源码分析》《FlutterAndroid端Activity/Fragment流程源码分析》《FlutterAndroid端FlutterInjec... 查看详情

gunicorn源码分析(代码片段)

   首先gunicorn是基于“preforkworker”模型,gunicorn启动之后会有一个master进程和多个worker进程,这个master进程的主要功能就是管理worker进程,所有的请求和响应都是由worker进程进行处理,pre-fork和fork模式类似,... 查看详情

oop第一次博客作业(代码片段)

OOP第一次博客作业目录OOP第一次博客作业前言第一次作业第二次作业第三次作业设计与分析定义日期类分析定义日期类源码定义日期类类图题目思路难点主要知识点日期类设计分析日期类设计源码日期类分析类图题目思路难点主... 查看详情