作者:GWD 时间:2019.7.28

一、系统的进程的运转方式
1、系统时间:(jiffies系统滴答):CPU内部有一个RTC,会在上电的时候调用mktime函数算出从1970年1月1日0时开始到当前开机点所过的秒数给MKTIME函数传来的时间结构体的赋值是由初始化时从RTC(coms)中读出的参数 转化为时间存入全局变量中,并且会为JIFFIES所用;
2、 JIFFIES 是一个系统的时钟滴答 ,一个系统滴答是10ms ,定时器10ms一个系统滴答—>每隔10ms会引发一个定时器中断(这个中断服务函数中,首先进行了jiffies的自加;
Jiffies自增后调用do_timer函数

(一)、分析do_timer()函数
1、Sched.c中打开do_timer函数

 时钟中断C 函数处理程序,在kernel/system_call.s 中的_timer_interrupt(176 行)被调用。
// 参数cpl 是当前特权级0 或3,0 表示内核代码在执行。
// 对于一个进程由于执行时间片用完时,则进行任务切换。并执行一个计时更新工作。
void do_timer (long cpl)
{extern int beepcount;      // 扬声器发声时间滴答数(kernel/chr_drv/console.c,697)extern void sysbeepstop (void);  // 关闭扬声器(kernel/chr_drv/console.c,691)// 如果发声计数次数到,则关闭发声。(向0x61 口发送命令,复位位0 和1。位0 控制8253// 计数器2 的工作,位1 控制扬声器)。if (beepcount)if (!--beepcount)sysbeepstop ();// 如果当前特权级(cpl)为0(最高,表示是内核程序在工作),则将超级用户运行时间stime 递增;// 如果cpl > 0,则表示是一般用户程序在工作,增加utime。if (cpl)current->utime++;elsecurrent->stime++;// 如果有用户的定时器存在,则将链表第1 个定时器的值减1。如果已等于0,则调用相应的处理
// 程序,并将该处理程序指针置为空。然后去掉该项定时器。if (next_timer){                // next_timer 是定时器链表的头指针(见270 行)。next_timer->jiffies--;while (next_timer && next_timer->jiffies <= 0){void (*fn) ();  // 这里插入了一个函数指针定义!!!??fn = next_timer->fn;next_timer->fn = NULL;next_timer = next_timer->next;(fn) ();      // 调用处理函数。}}
// 如果当前软盘控制器FDC 的数字输出寄存器中马达启动位有置位的,则执行软盘定时程序(245 行)。if (current_DOR & 0xf0)do_floppy_timer ();if ((--current->counter) > 0)return;         // 如果进程运行时间还没完,则退出。current->counter = 0;if (!cpl)return;         // 对于超级用户程序,不依赖counter 值进行调度。schedule ();
}

2、问:current是什么?

答:是当前进程,为什么当前进程可以用current一个变量来表示呢?这就是操作系统的,魅力,也是面向对象的思想。它有一个封装的非常好的结构体叫task_struct。CPL变量是内核中用来指示被中断程序的特权,0表示内核进程,1表示被中断的是用户进程;

3、task_struct:无论是进程的创建、退出、管理都是在跟这个结构体在打交道。创建进程的时候就是创建一个这个task_struct变量;

// 这里是任务(进程)数据结构,或称为进程描述符。
// ==========================
// long state 任务的运行状态(-1 不可运行,0 可运行(就绪),>0 已停止)。
// long counter 任务运行时间计数(递减)(滴答数),运行时间片。
// long priority 运行优先数。任务开始运行时counter = priority,越大运行越长。
// long signal 信号。是位图,每个比特位代表一种信号,信号值=位偏移值+1。
// struct sigaction sigaction[32] 信号执行属性结构,对应信号将要执行的操作和标志信息。
// long blocked 进程信号屏蔽码(对应信号位图)。
// --------------------------
// int exit_code 任务执行停止的退出码,其父进程会取。
// unsigned long start_code 代码段地址。
// unsigned long end_code 代码长度(字节数)。
// unsigned long end_data 代码长度 + 数据长度(字节数)。
// unsigned long brk 总长度(字节数)。
// unsigned long start_stack 堆栈段地址。
// long pid 进程标识号(进程号)。
// long father 父进程号。
// long pgrp 父进程组号。
// long session 会话号。
// long leader 会话首领。
// unsigned short uid 用户标识号(用户id)。
// unsigned short euid 有效用户id。
// unsigned short suid 保存的用户id。
// unsigned short gid 组标识号(组id)。
// unsigned short egid 有效组id。
// unsigned short sgid 保存的组id。
// long alarm 报警定时值(滴答数)。
// long utime 用户态运行时间(滴答数)。
// long stime 系统态运行时间(滴答数)。
// long cutime 子进程用户态运行时间。
// long cstime 子进程系统态运行时间。
// long start_time 进程开始运行时刻。
// unsigned short used_math 标志:是否使用了协处理器。
// --------------------------
// int tty 进程使用tty 的子设备号。-1 表示没有使用。
// unsigned short umask 文件创建属性屏蔽位。
// struct m_inode * pwd 当前工作目录i 节点结构。
// struct m_inode * root 根目录i 节点结构。
// struct m_inode * executable 执行文件i 节点结构。
// unsigned long close_on_exec 执行时关闭文件句柄位图标志。(参见include/fcntl.h)
// struct file * filp[NR_OPEN] 进程使用的文件表结构。
// --------------------------
// struct desc_struct ldt[3] 本任务的局部表描述符。0-空,1-代码段cs,2-数据和堆栈段ds&ss。
// --------------------------
// struct tss_struct tss 本进程的任务状态段信息结构。
// ==========================
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[32];long blocked;           /* bitmap of masked signals */
/* various fields */int exit_code;unsigned long start_code, end_code, end_data, brk, start_stack;long pid, father, pgrp, session, leader;unsigned short uid, euid, suid;unsigned short gid, egid, sgid;long alarm;long utime, stime, cutime, cstime, start_time;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;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[3];
/* tss for this task */struct tss_struct tss;
};

4、接下来看一下next_timer是什么?
next_timer 是嫁接与jiffies变量的所有定时器的事件链表。如果链表上有定时器的话就执行这个定时器,若没有就不执行

next_timer 是嫁接与jiffies变量的所有定时器的事件链表,jiffies就好像一根绳子,链表是在上边打的节,比如十分钟的时候要执行某些程序,第十分钟就是链表。

5、current->counter ---->进程的时间片

单核CPU操作系统是伪并行的,进程调度就是根据时间片来的;
task_struck一个进程,task_struck[]进程向量表counter;
1)、counter–在哪里用:进程的调度就是task_struck[]进程链表的检索,找时间片最大的那个进程对象(task_struck),然后进行调用,直到时间片为0,退出之后在进行新一轮的调用。
2)、counter–在哪里被设置:当全部的 task_struck[](task[])所有的进程的counter都为0,就进行新一轮的时间片分配;
3)、分配方式:优先级时间片轮转调度算法,可以看出把优先级加到时间片上了,优先级越高时间片越大,就越先执行(*p)->counter = ((*p)->counter >> 1) +(*p)->priority;

(二)、分析mktime.c
1、首先打开Mktime.c

我们看看谁调用了kernel_mktime这个函数就知道谁在一开始就给他1970的时间了,搜索一下发现有两个函数调用了这个

这里可以看出时间是从cmos中读出的,这个do…while用的很好,先读一次,若第二次读的和第一次不一样就再读一次,以防读的过程中过去了1秒。然后kernel_mktime(&time)把时间返回给全局变量start_time

再看一下startup_time这个全局变量是干什么用的

其中jiffies/HZ是开机用的秒数


注:linux一开始就很注重面向对象的编程,tm结构体就是一个对象,在系统中也不断地在进行新建对象

linux内核——3_(进程管理)系统的进程管理相关推荐

  1. 《Linux内核分析》 第六节 进程的描述和进程的创建

    <Linux内核分析> 第六节 进程的描述和进程的创建 20135307 张嘉琪 原创作品转载请注明出处 +<Linux内核分析>MOOC课程http://mooc.study ...

  2. Linux Shell常用技巧(九) 系统运行进程

    Linux Shell常用技巧(九) 系统运行进程 十九.  和系统运行进程相关的Shell命令:         1.  进程监控命令(ps):       要对进程进行监测和控制,首先必须要了解当 ...

  3. Linux内核编译(通过内核模块显示进程控制块信息)

    Linux内核编译(通过内核模块显示进程控制块信息) 实验说明 在内核中,所有进程控制块都被一个双向链表连接起来,该链表中的第一个进程控制块为init_task.编写一个内核模块,模块接收用户传递的一 ...

  4. linux内核分成如下五个子系统,linux内核主要由5个子系统 Linux内核由哪几个子系统组成?...

    1, Linux内核由哪几个子系统组成? Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信.1.进程调度(SCHED):控制进程对CPU的访问.当需要选择下一 ...

  5. Linux内核的5个子系统

    首先一张熟悉的图来说明GNU/linux的基本体系结构: 体系的上部分是用户(或应用程序)空间,这是用户应用程序执行的地方.用户空间之下是内核空间,Linux 内核正是位于这里.Linux 内核可以进 ...

  6. Linux内核错误(引导系统)Deepin用户手册在/etc/sysctl.conf文件中加入kernel.panic = 20,在/etc/sysctl.conf中kernel.sysrq=1内存

    Linux内核错误(引导系统)- 系统管理 -Deepin深度系统用户手册 Power By Baidu Ai 00:00 00:00 目录 1 简介 2 问题分析 3 案例分析 此文章约为4327字 ...

  7. Android研究-linux内核启动到android系统

    很多人阅读代码,总喜欢从头开始,这样觉得很安全,有依靠,无论如何总是能知道"头",有头就能找到任何需要的部分. Android生在linux内核基础上,linux内核启动的最后一步 ...

  8. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  9. oracle smon 执行记录,Oracle SMON进程中系统监视进程SMON

    在Oracle中有很多的东西值得我们大家学习的地方,在这里我们主要描述的是Oracle SMON进程,也包括介绍归档进程ARCH等相关方面的内容.在Oracle数据库中有两个进程非常的渺小,但是其作用 ...

  10. 解决ubuntu更改Linux内核(或更新系统)后扩展屏(第二显示器)无法正常显示问题)

    解决ubuntu更改Linux内核(或更新系统)后扩展屏(第二显示器)无法正常显示问题 我的解决方案 一定先看这个(很重要) 直接看这个就可以 前几天更新了一下ubuntu系统,一切正常,但是当我把系 ...

最新文章

  1. ORACLE 添加删除列脚本
  2. react系列知识---11组件间抽象
  3. 教科书上的LDA为什么长这样?
  4. 机器值计算机组成,计算机组成原理_数据的机器运算.ppt
  5. An Energy-Efficient Ant-Based Routing Algorithm for Wireless Sensor Networks (无线传感网中基于蚁群算法的能量有效路由)2
  6. STL13-list容器(链表)
  7. 11 User Space, Kernel Space, and the System Call API(用户空间,核空间,系统api)
  8. asp.net MVC初学体会.
  9. 南阳oj-----Binary String Matching(string)
  10. dw1510_超低温种子储存柜
  11. 如何解决高分辨率下文本、图像和字体和布局?
  12. BZOJ #3653. 谈笑风生
  13. 编写一个静态方法 lg(), 接受一个整型参数 N,返回不大于 log2N 的最大整数。
  14. Matlab中interp1()和interp2()的用法
  15. 百度又一神器发布!网友:牛逼炸了...
  16. 人脸识别之人眼定位、人脸矫正、人脸尺寸标准化---Mastering OpenCV with Practical Computer Vision Projects
  17. 【动态规划】令你战栗的神奇算法:动态规划基础
  18. python期货程序化交易高手心得_位顶级高手谈期货心得
  19. php 微信服务号登录授权
  20. java 使用浏览器下载图片

热门文章

  1. java实验报告——雇员类
  2. XAMARIN Android获取WIFIMAC地址的方法
  3. 计算机屏幕变红色,Windows10系统电脑屏幕变成红色如何解决
  4. 河南留学欧美预备学校校歌——Alma Mater(母校)_控控控-上ke控_新浪博客
  5. 急性子的人,不妨来点“佛系”的心态
  6. 吐血推荐—计算机专业不可不看。
  7. Windows笔记本本地摄像头提供Rtsp视频流服务
  8. RT-Thread 之 WIZnet 软件包(全硬件TCP/IP协议栈W5500以太网芯片) 以太网 Socket 通信
  9. 【复现 | 论文】Seg4Reg Networks for Automated Spinal Curvature Estimation
  10. 【创想QQ图标点亮辅助工具●V2.0官方版】