当前位置: 首页 > news >正文

Linux进程管理中的hash

     

      Linux内核必须能够根据进程的PID找出对应的PCB。顺序扫描进程链表并检查PCB的PID域是可行但效率相当低的。为了加速查找,引入了哈希表,于是建立了一个pid_hash的结构。

1、pid_hash的声明(kernel/pid.c):

static struct hlist_head *pid_hash;
   pid的初始化是在内核初始化(即start_kernel函数中)的时候完成的。由pidhash_init完成:

/*
 * The pid hash table is scaled according to the amount of memory in the
 * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or
 * more.
 */
void __init pidhash_init(void)
{
	int i, pidhash_size;
        //为数组开辟空间
	pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash), 0, 18,
					   HASH_EARLY | HASH_SMALL,
					   &pidhash_shift, NULL, 4096);
	pidhash_size = 1 << pidhash_shift;//数组的长度

	for (i = 0; i < pidhash_size; i++)
		INIT_HLIST_HEAD(&pid_hash[i]);//将数组中的指针都初始化为NULL
}
   alloc_large_system_hash是专门用于为hash表分配一块连续的内存的,参数4096意味着最多4k个项,也就是最多占用1页的内存。哈希数组大小实际上由pidhash_shift决定,默认取4,直接影响了pidhash_size取的大小为4096。
   pidhash_init 函数通过宏INIT_HLIST_HEAD把pid_hash数组的每个元素(struct hlist_head类型的变量)都初始化为空指针。

2、hash函数的建立

   Linux用一个叫做pid_hashfn的宏来建立(kernel/pid.c文件中)

/*linux-2.6.32.63/kernel/pid.c*/
#define pid_hashfn(nr, ns)	\
	hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)
	
/*linux-2.6.32.63/include/linux/hash.h  分析32bits*/
#define hash_long(val, bits) hash_32(val, bits)

/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
#define GOLDEN_RATIO_PRIME_32 0x9e370001UL

static inline u32 hash_32(u32 val, unsigned int bits)
{
	/* On some cpus multiply is faster, on others gcc will do shifts */
	u32 hash = val * GOLDEN_RATIO_PRIME_32;

	/* High bits are more random, so use them. */
	return hash >> (32 - bits);
}
  其中,nr是pid的值,而ns表示的是pid的命名空间(这个是为了支持轻量级虚拟化而引入的新概念)。 散列函数pid_hashfn先使关键字(nr和ns的和)乘以0x9e370001UL,然后取乘积的低pidhash_shift位。

   仔细分析一下上面的函数:

   首先,hash的方式是,让key乘以一个大数,于是结果溢出,就把留在32/64位变量中的值作为hash值,又由于散列表的索引长度有限,我们就取这hash值的高几为作为索引值,之所以取高几位,是因为高位的数更具有随机性,能够减少所谓“冲突”。

   那么,乘以的这个大数应该是多少呢?从上面的代码来看,32位系统中这个数是0x9e370001UL。这个数是怎么得到的呢?
   “Knuth建议,要得到满意的结果,对于32位机器,2^32做黄金分割,这个大数是最接近黄金分割点的素数,0x9e370001UL就是接近 2^32*(sqrt(5)-1)/2 的一个素数,且这个数可以很方便地通过加运算和位移运算得到,因为它等于2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1。

3、处理冲突

     Linux利用链地址法来处理冲突的PID,也就是说,每一个表项是由冲突的PID组成的双向链表,task_struct结构中由两个域pidhash_next和pidhash_prev来实现这个链表,同一个链表中pid由小到大排列。


学习博客:

      Linux内核中的PID散列表实例http://blog.csdn.net/npy_lp/article/details/7331245

      Linux内核中hash函数的实现http://blog.csdn.net/gaopenghigh/article/details/8831312

      linux内核PID管理http://blog.csdn.net/zhanglei4214/article/details/6765913(本文更加深入)

                     

相关文章:

  • 浏览器真的能“永不假死”?——六款主流浏览器防假死功能测试
  • [九度—剑指offer]—二维数组查找
  • 人人都能当“苍天哥” 手把手教你制作游戏视频
  • Linux 2.6 中导出sys_call_table表修改系统调用函数
  • [九度 1510 剑指offer]—替换空格 数组插入逆向移动
  • 个人设置随身携带口袋操作系统手到擒来
  • 免费邮箱,谁更可靠?6款常用免费邮箱收信效果对比测试
  • 哪个搜索引擎更聪明?微软必应搜索挑战赛
  • [九度1512 剑指offer7] 用两个栈实现队列
  • 无光驱没光盘 操作系统照样可以安
  • mmap() 实现文件复制
  • [Linux内存管理-分页机制]—把一个虚拟地址转换为物理地址
  • C#也能动态生成Word文档并填充数据
  • Epoll实现服务器高并发
  • Linux中实现线程池
  • CentOS6 编译安装 redis-3.2.3
  • cookie和session
  • CSS相对定位
  • Laravel 菜鸟晋级之路
  • Markdown 语法简单说明
  • mongodb--安装和初步使用教程
  • node 版本过低
  • October CMS - 快速入门 9 Images And Galleries
  • passportjs 源码分析
  • PHP的Ev教程三(Periodic watcher)
  • 产品三维模型在线预览
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 分类模型——Logistics Regression
  • 构造函数(constructor)与原型链(prototype)关系
  • 关于Java中分层中遇到的一些问题
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 前端技术周刊 2019-01-14:客户端存储
  • 我的zsh配置, 2019最新方案
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 阿里云重庆大学大数据训练营落地分享
  • #{} 和 ${}区别
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $$$$GB2312-80区位编码表$$$$
  • (1)bark-ml
  • (ros//EnvironmentVariables)ros环境变量
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (九)One-Wire总线-DS18B20
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (七)c52学习之旅-中断
  • (七)Java对象在Hibernate持久化层的状态
  • (三)Honghu Cloud云架构一定时调度平台
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (算法)Travel Information Center
  • (转)大型网站的系统架构
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • ******之网络***——物理***
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...