RH_KABI_RESERVE的使用
struct mm_struct {
..........
#if defined(__GENKSYMS__) || !defined(CONFIG_SPAPR_TCE_IOMMU)
/* We're adding a list_head, so we need to take two reserved
* fields, unfortunately there are no handy RH_KABI macros for
* that case */
RH_KABI_RESERVE(1)
RH_KABI_RESERVE(2)
#else
struct list_head iommu_group_mem_list;
#endif #ifdef CONFIG_X86_INTEL_MPX
RH_KABI_USE(3, void __user *bd_addr)
#else
/* RHEL7: consumed by x86, avoid re-use by other arches */
RH_KABI_RESERVE(3)
#endif
/* This would be in rss_stat[MM_SHMEMPAGES] if not for kABI */
RH_KABI_USE(4, atomic_long_t mm_shmempages) #if IS_ENABLED(CONFIG_HMM)
/* HMM need to track few things per mm */
RH_KABI_USE(5, struct hmm *hmm)
#else
RH_KABI_RESERVE(5)
#endif RH_KABI_RESERVE(6)
RH_KABI_RESERVE(7)
RH_KABI_RESERVE(8)
};
在struct mm_struct 或者 task_struct 之类的结构中,我们经常能看到 RH_KABI_RESERVE 这种成员,这种成员其实就是为了增加扩展性所留的一手。
这个可以类比tcp协议头,也有tcp_option,原理也是类似的,那么,怎么使用这些成员呢?
比如我想在task里面,记录一些私有的数据,这个数据由于类型只有 unsigned long 类型,所以这个既可以直接用来记录普通数据,也可以用来存放一个指针,然后再指向一个地址,这样存放的内容就多了。
#define _RH_KABI_RESERVE(n) unsigned long rh_reserved##n
#define _RH_KABI_RESERVE_P(n) void (*rh_reserved##n)(void)
#define RH_KABI_RESERVE(n) _RH_KABI_RESERVE(n);
举个栗子:
/* This would be in rss_stat[MM_SHMEMPAGES] if not for kABI */
RH_KABI_USE(4, atomic_long_t mm_shmempages)
没有用的变量,是 RH_KABI_RESERVE,那么已经使用的,则是 RH_KABI_USE ,我们看到 mm_shmempages 使用的是4号位置。
之后,就可以直接对 mm_shmempages 成员进行赋值了。
比如在 mm_init 中正常使用 mm_shmempages
static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
{
atomic_set(&mm->mm_users, 1);
atomic_set(&mm->mm_count, 1);
init_rwsem(&mm->mmap_sem);
INIT_LIST_HEAD(&mm->mmlist);
mm->core_state = NULL;
atomic_long_set(&mm->nr_ptes, 0);
memset(&mm->rss_stat, 0, sizeof(mm->rss_stat));
atomic_long_set(&mm->mm_shmempages, 0);-----------正常当成员使用,因为 RH_KABI_USE 这个宏已经帮我们替换好了。
不过需要注意的是,要及时清理,比如我们使用了task_struct里面的RH_KABI_RESERVE,但是在fork的时候忘了清理该成员,导致了一些问题。
RH_KABI_RESERVE的使用的更多相关文章
随机推荐
- [UE4]增加观察者
角色死亡以后,让控制器控制另外一个只能移动,没有实体的Character角色 使用“Possess”函数让控制器控制新生成的观察者对象.如上图所示要使用Delay延迟1秒再生成观察者,是因为死亡的时候 ...
- [UE4]游戏中服务器切换地图,控制台命令Execute console Command
Execute console Command ServerTravel {地图名称}?listen 在服务器执行了这个命令,所有连接到该服务器的客户端都会跟着服务器同时切换到指定的地图. 1.创建一 ...
- [UE4]UI之间传递数据
通过创建对方UI类型的变量引用,初始本控件时赋值该变量,就可以对方UI内的方法了.
- laravel插入数据时报 502 Bad Gateway
前提:model中$timestamp = true; 但数据表中created_at 和updated_at 是默认为当前时间 造成冲突. 原因:用create方法时 created_at 和u ...
- Linux上面的MTU含义
问题场景描述: 最近在搞一个很菜的程序--FTP上传文件. 但是这个 很菜的程序搞的我脑袋疼了 半个月. 在linux上面部署了我的程序,上传文件在1KB以下顺利上传,但是1KB以上上传不上去. 程序 ...
- 使用LiteOrm删除数据对象失败的坑
使用 LiteOrm.newSingleInstance(BaseApplication.getInstance(), Constant.DB_NAME); 在不同进程中创建了两次对象,在保存和删除的 ...
- ZooKeeper的安装和API
Zookeeper的分布式安装和API介绍: 安装教程 在datanode1.datanode2和datanode3三个节点上部署Zookeeper. 步骤 解压zookeeper安装包到/opt/m ...
- 你创建的OpenStack高性能虚拟机能实现“零损耗”么?
使用默认参数创建的虚拟机,虚拟机的VCPU在物理CPU不同核心之间动态调度,另外,由于Linux还可能会将软中断,内存交换等进程调度到虚拟机正在使用的物理核心上,这些因素导致这些虚拟机相对于物理机的计 ...
- python初探 socket
1.什么是socket? Socket中文译作:套接字,但是大家一般约定俗称的都用:socket.我想在解释socket是什么之前,先说它是用来干嘛的:socket是来建立‘通信’的基础,建立连接,传 ...
- JVM总结-java基本类型
为什么要引进基本类型? Java 引进了八个基本类型,来支持数值计算.Java 这么做的原因主要是工程上的考虑,因为使用基本类型能够在执行效率以及内存使用两方面提升软件性能. Java 虚拟机的 bo ...