前言

回望笔者之前发的数篇技术博客,中规中矩,阅读量更是不尽人意,看来没帮到多少人,不行,文风要改,要大改。于是乎,笔者金荣摇身一变,化作Linux OS的一个进程,我是一个进程,我来讲述我的故事。

Linux内核之话说进程

  • 前言
  • 我从哪里来?
  • 讲讲我的故事
  • 看看我的模样
  • 和我交朋友吧

我从哪里来?

进程:“若要问我从哪里来,还要从操作系统的发展说起。”(进程的回忆开始了)那是在20世纪50年代中期,出现了第一代计算机,那时候还需要程序员亲自手工操作穿孔的纸带卡片,虽然CPU的速度在迅速提高,但是I/O设备的速度却提高缓慢,来看看CPU和人工处理的I/O设备的日常对话。

相传,为了解决人机矛盾及CPU和I/O设备之间速度不匹配的矛盾,脱机I/O技术诞生了,看看那时候CPU在聊些什么。

为了提高系统资源利用率和吞吐量,单道批处理系统诞生了,这下好了,任务一个接一个来,CPU总算是能表现一下自己了,来看看这时候CPU和OS监督程序的对话。

虽然单道批处理系统提高了系统资源的利用率和系统的吞吐量,但是任然不能充分地利用系统资源,因为在内存中仅有一道程序,程序在运行中发出I/O请求后,CPU就在那一直等,当时的情况是这样的:

虽然如此,但是问题依旧不大,因为在20世纪60年代中期,引入了多道程序的设计技术,形成了多道批处理系统,进一步提高了资源的利用率和系统吞吐量,我也是在这个时期开始形成的,当时可把CPU乐坏了。

后来的后来,为了方便用户,CPU继续发展快速更新换代,各种操作系统也是层出不穷,例如常见的Windows 、Linux、Contiki 等,然而我的作用依旧不可替代。

讲讲我的故事

你以为进程我三头六臂,真的那么大本事,可以让一个CPU核心同时运行多个程序?别你以为了,只是一种错觉,只是操作系统的并发性罢了,实际上一个CPU核心在同一时刻只能运行一个程序,只不过是我快速切换,让CPU这个高速的家伙闲不下来,知道真相的你,是不是觉得理解错了呢?事实上现在的CPU已经可以同一时刻运行多个程序啦,因为现在的CPU有多个核心呐。

我们也不容易呀,虽然让CPU这家伙完全跑了起来,有效地改善了资源利用率,提高了系统吞吐量,但是我们把操作系统弄的更复杂了,如果我们不受约束的话,就会随意争夺系统资源,给操作系统老大带来麻烦,程序也会显现出不可再现性。老大当然不允许了,于是和我约法三章,定了一些硬件同步机制、信号量机制、管程机制等一系列同步机制,好让老大更加稳定可靠。

当然我们进程之间也经常联系呢,早期的通信被人们叫做低级进程通信,当然这时候我们进程的通信人们才不知道呢。后来,OS老大更强大了,制定了高级通信机制,他给人们提供了高级通信工具,我们进程之间的通信能传送大量的数据了,对人们也透明了,这个高级通信机制,被人们归了四类,分别是:共享存储系统、管道通信系统、消息传递系统和客户机-服务器系统。

听了我们进程的故事,是不是对我有所了解呢,其实我们家族的故事多着呢,有兴趣可以自己去了解一番,这里有一张金荣制作的思维导图,有助于更好地了解我们,收好。

看看我的模样

也许你对进程我已经有所了解,那么现在就请你在Linux OS中看看我的真面目吧,要问我到底是谁,我只是一些程序和数据罢了,也可以认为进程我就是运行中的程序。Linux OS老大为了管住我,将我的状态信息、链接信息、各种标识符、进程间通信信息、时间和定时器信息、调度信息、文件系统信息、虚拟内存信息、处理器环境信息等封印在一个巨大的结构体中,江湖上称之为进程控制块(Process Contrlo Block),简称PCB,在内核源码中的定义是酱紫的,且看Linux内核3.18.43版本的源码。

/include/linux下的头文件sched.h中的第1237行代码

了解我的状态,这点很重要,在一般的操作系统中,我的状态有就绪态、运行态和等待态三种状态,而在Linux OS中,为了管理上的方便,我的状态被改造成了就绪态、睡眠态、暂停态和僵死态,状态转换是酱紫的。


当然了,我们进程也并非长生不老,陈莉君老师就对我们极为了解,不信请看看陈老师语录:

随着一句fork,一个新进程呱呱落地,但这时它只是老进程的一个克隆。然后,随着exec,新进程脱胎换骨,离家独立,开始了独立工作的职业生涯。
人有生老病死,进程也一样,它可以是自然死亡,即运行到主(main)函数的最后一个"}",从容地离我们而去;也可以是中途退场,退场有2种方式,一种是调用exit函数,一种是在主(main)函数内使用return,无论哪一种方式,它都可以留下留言,放在返回值里保留下来;甚至它还可能被谋杀,被其它进程通过另外一些方式结束它的生命。
进程死掉以后,会留下一个空壳,wait站好最后一班岗,打扫战场,使其最终归于无形。这就是进程完整的一生。

和我交朋友吧

想和我们交朋友吗,那就了解一下我的组织方式吧。为了对我们进行有效的搜索,内核建立了几个进程链表,每个进程链表由指向进程PCB的指针组成。当内核要根据我们的PID导出对应PCB的时候,遍历进程链表检查PCB中的PID太慢了,于是引入了哈希表,Linux OS中用了一个叫做pid_hashfn的宏,来实现把PID转换成表的索引的哈希函数。

在这里献上一个内核模块,功能为遍历进程链表,打印pcb相关字段的内核模块,并配上详细注释:

# include <linux/kernel.h>
# include <linux/module.h>
# include <uapi/linux/sched.h>
# include <linux/init_task.h>
# include <linux/init.h>
# include <linux/fdtable.h>
# include <linux/fs_struct.h>
# include <linux/mm_types.h>//内核模块初始化函数
static int __init traverse_pcb(void)
{struct task_struct *task, *p;//定义指向task_struct类型的指针struct list_head *pos;//定义双向链表指针int count=0;//定义统计系统进程个数的变量printk("Printf process'message begin:\n");//提示模块开始运行task = &init_task;//指向0号进程的PCBlist_for_each(pos,&task->tasks)//使用list_for_each宏来遍历进程链表{p = list_entry(pos,struct task_struct,tasks);//指向当前进程的task_struct结构count++;//统计系统进程个数printk("\n\n");//方便查看后续打印信息/*打印task_struct中的字段,其中pid:进程的pid号;state:进程的状态;prio:动态优先级;static_prio:静态优先级; parent'pid:父进程的pid号;count:文件系统信息,文件被使用的次数; umask:进程权限位的默认设置;使用atomic_read原子操作是为了(p->files)->count字段计数不被打断*/printk("pid:%d; state:%lx; prio:%d; static_prio:%d; parent'pid:%d; count:%d; umask:%d;",    \p->pid,p->state,p->prio,p->static_prio,(p->parent)->pid,                             \atomic_read((&(p->files)->count)),(p->fs)->umask);//打印进程地址空间的信息if((p->mm)!=NULL)printk("total_vm:%ld;",(p->mm)->total_vm);//total_vm:线性区总的页数}printk("进程的个数:%d\n",count);//打印进程个数return 0;
}//内核模块退出函数
static void __exit end_pcb(void)
{printk("traverse pcb is end.");
}
module_init(traverse_pcb);//入口
module_exit(end_pcb);//出口
MODULE_LICENSE("GPL");//许可证

Makefile代码如下

#产生目标文件
obj-m:=traverse_pcb.o
#路径变量,指明当前路径
CURRENT_PATH:=$(shell pwd)
#指明内核版本号
LINUX_KERNEL:=$(shell uname -r)
#指明内核源码的绝对路径
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
#编译模块
all:make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
#清理模块
clean:make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

编译并将.ko文件加载到内核,过程如下图

运行结果:

上图中,我们可以看到每个进程的pid号,进程的状态,动态优先级,静态优先级,父进程的pid号,文件系统信息(文件被使用的次数),进程权限位的默认设置,总进程数等。有些进程的total_vm是空的,说明他们是内核线程。

看完还想了解进程更多?这里给出参考资料:

[1]陈莉君,康华著.Linux 操作系统原理与应用.清华大学出版社.2012
[2]陈莉君,张琼声,张宏伟译,Daniel P.Bovet、Marco Cesati著.深入理解LINUX内核.中国电力出版社.2008
[3]陈莉君,康华译,RobertLove著.Linux内核设计与实现.机械工业出版社.2011
[4]汤小丹.计算机操作系统.西安电子科技大学出版社.2014
[5]陈莉君.Linux内核分析与应用.学堂在线视频

Linux内核之话说进程相关推荐

  1. Linux内核中的进程组及会话

    Linux内核中的进程组及会话 将阐述Linux内核中的如下几个概念 1) 进程组 2) 会话 3) 控制终端 前面的概念来源于前人,我只是站在前人的肩膀上结合内核中的实现加深概念理解. 1.概念: ...

  2. linux 进程管理 ppt,Linux内核结构与进程管理.ppt

    Linux内核结构与进程管理.ppt Linux 内核结构与进程管理,Linux系统结构Linux kernel 开放源代码的linux操作系统内核,目前版本为2.6,Linux内核组成1. 进程调度 ...

  3. linux内核打开文件数,放开Linux内核对用户进程可打开文件数和TCP连接的限制

    一. 检查linux内核 uname -a lsb_release -a 二.用户进程可打开文件数限制 1)vim /etc/security/limits.conf *       -      n ...

  4. linux内核arc4算法,linux内核中与进程相关的数据结构(基于linux-mainline-rc4)

    1.进程描述符 struct task_struct { volatile long state; ....... struct list_head tasks; ....... struct mm_ ...

  5. 修改linux内核达到隐藏进程目的(2.6.28)

    修改linux内核达到隐藏进程目的(2.6.28) 要求: 高级操作系统与分布式系统作业 ps和top命令列出了unix中当前所有进程的相关信息,作业要求在linux中增加两个系统调用,功能如下: h ...

  6. Linux内核学习008——进程管理(四)

    Linux内核学习007--进程管理(四) 进程家族树 Unix系统的进程之间存在一个明显的继承关系,所有的进程都是PID为1的init进程的后代.内核在系统启动的最后阶段启动init进程,然后ini ...

  7. linux内核 current当前进程指针 task_struct结构介绍

    尽管内核模块不象应用程序一样顺序执行, 内核做的大部分动作是代表一个特定进程的. 内核代码可以引用当前进程, 通过存取全局项 current, 它在 <asm/current.h> 中定义 ...

  8. linux内核调用( )为进程创建虚存区_Linux内核分析-总结篇(九)

    本次内容作为Linux内核的总结内容,主要涉及对Linux系统的总体的一些理解,同时将之前的一些总结贴出来作为大家的一个索引,希望笔者一样的菜鸟有一些帮助和入门的作用.从一个初学者的角度对Linux有 ...

  9. Linux内核态之间进程通信,内核态和用户态通信(二)--实现

    本文主要使用netlink套接字实现中断环境与用户态进程通信. 系统环境:基于linux 2.6.32.27 和 linux 3.16.36 Linux内核态和用户态进程通信方法的提出和实现 用户上下 ...

最新文章

  1. Android开发学习笔记(二)——编译和运行原理(2)
  2. 电路板必须用c语言编程吗,上大学才知道绿油油的板子叫PCB,如何成为一名电子工程师...
  3. 顺时针打印3*3矩阵
  4. 模拟电子技术不挂科学习笔记2(三极管、场效应管)
  5. 网络协议分析(Network Protocol Analysis)之点到链路控制协议LCP
  6. 博科光交机SNMP配置
  7. django初体验 学习笔记
  8. coco 数据集_PyTorch版YOLOv4更新了,适用于自定义数据集
  9. matlab axes坐标轴长度,[转载]Matlab 坐标轴(axes),数据提示(data
  10. 《哥德尔、艾舍尔、巴赫——集异璧之大成》
  11. c语言void调用不可作为,C语言的选择题.pdf
  12. FFmpeg 以及帧率的解释
  13. 机器学习入门实战——决策树算法实战Titanic数据集
  14. BigDecimal运算和比较大小
  15. 是真正的发现,还是可耻的堕落?
  16. 以太网接口 数据采集 matlab,基于以太网接口并行多通道采集器的设计
  17. Web实验六 JavaScript实验
  18. android动画不占cpu如何实现,【实战总结】帧动画调优实践
  19. 自动化专业本科学习笔记
  20. 家长怒进游戏群控诉:网瘾是表象 亲子关系问题是核心

热门文章

  1. Linux 下 PHP 5.2.x 连接 SQL Server 数据库 FreeTDS 配置笔记
  2. 开源 java CMS - FreeCMS2.6 模型管理
  3. git常用基本简单命令
  4. 获取上层调用函数地址的代码
  5. 为任务关键型Java应用优化垃圾回收
  6. golang os.Rename 移动文件 报错 invalid cross-device link 解决方法
  7. python3 pyclamd模块调用clamav杀毒
  8. linux /proc目录文件详解
  9. linux shell map dict 字典数组
  10. linux screen 命令详解(后台执行linux命令)