Linux内核与驱动面试经典“小”问题集锦(6)
接前一篇文章:Linux内核与驱动面试经典“小”问题集锦(5)
问题8
问:如何判断一个数是否是2的幂次(假设最多32位)?
备注:此问题是笔者年前参加小米面试时遇到的一个问题,是属于面试中的笔试。原题是一语句实现y是否为2的若干次幂的判断。

答:
其实上图中已经提供了一些思路,先要观察规律(为了简化,以8位为例):
正例:
1:0x01即0b00000001,2的0次幂
2:0x02即0b00000010,2的1次幂
4:0x04即0b00000100,2的2次幂
……
128:0x80即0b10000000,2的7次幂
反例:
3:0x03即0b00000011
5:0x05即0b00000101
6:0x06即0b00000110
7:0x07即0b00000111
当时那为面试官还蛮有耐心,还提示到要从本数和其掩码的方面考虑。不过本人资质比较愚钝,一时也没有找到规律。他后来直接给出了答案,也就是上图中的那个:
#define is2pow(x) ((x & (x-1)) == 0)
验证:
- x=1时,x & (x-1)为0,返回真,说明是2的幂次。
- x=2时,x & (x-1)为0,返回真,说明是2的幂次。
- x=4时,x & (x-1)为0,返回真,说明是2的幂次。
- x=8时,x & (x-1)为0,返回真,说明是2的幂次。
- x=3时,x & (x-1)为2,返回假,说明不是2的幂次。
- x=5时,x & (x-1)为4,返回假,说明不是2的幂次。
- x=6时,x & (x-1)为4,返回假,说明不是2的幂次。
- x=7时,x & (x-1)为6,返回假,说明不是2的幂次。
总结:
这道题背后考察的不光是候选者的智商和数字敏感性,而更多地是考察内核的功力,因为Linux内核中有很多基于2的幂次的判断。对于此不熟悉,说明对于内核与驱动看得不够透彻、不够精通。
问题9
问:container_of内核中经常遇到吧,请写出其具体的代码实现?
备注:此问题是笔者年前参加小米面试时遇到的一个问题,是属于面试中的笔试。笔者几年之前参加位于北京玉泉慧谷的一家公司(公司名字已不记得了,只记得地点)面试的时候,也被问到过这个问题,不过当时只是和面试官说了思路,并没有直接写出完整代码。
答:
container_of(ptr, type, member)宏的作用是通过结构体成员的地址和结构体类型推导出结构体的地址,type是指结构体的类型,member是成员在结构体中的名字,ptr是该成员在type结构体中的地址。
实际上笔者多年来看内核的代码经常会遇到container_of,也花时间研究过代码,尤其是之前面试中被问到时,面试结束回来后曾经认真研究过一番。但是几次都是当时弄得很明白,时间一长就淡忘了。并不能做到信手拈来,这也应该是不经常玩内核的一种不足。
笔者在小米面试时被问到这个问题后,就努力在脑海中回忆container_of这个宏的具体实现。依稀记得是这样:
#define container_of(pointer, structure, member) (structure *)(pointer - (&((structure *)0)->member))
这是当时笔者第一时间想出来的。但是并不完全正确。
当时面试官说,要实现container_of宏,必须先实现offset_off宏,因此笔者就没有直接给出container_of的实现,而是按照面试官的思路即要求,先写出了offset_off宏,如下:
#define offset_off(structure, member) (&(((structure *)NULL)->member))
这样写完了之后,面试官指出了不足,应该将偏移强制转换为int类型,如下:
#define offset_off(structure, member) ((int)(&((structure *)NULL)->member))
完成了offset_off宏之后,进一步再实现container_of宏,我开始的实现是这样:
#define container_of(pointer, structure, member) ((int)(pointer) - offset_off(structure, member))
面试官又指出了一处不足,应该强制转换为void *类型,更正后实现如下:
#define container_of(pointer, structure, member) (void *)((int)(pointer) - offset_off(structure, member))
将offset_off宏完全展开后,最终得到:
#define container_of(pointer, structure, member) (void *)((int)(pointer) - ((int)(&((structure *)NULL)->member)))
和笔者最开始所构想的进行对比:
- 最初构想的:
#define container_of(pointer, structure, member) (structure *)(pointer - (&((structure *)0)->member))
- 最终实现的:
#define container_of(pointer, structure, member) (void *)((int)(pointer) - ((int)(&((structure *)0)->member)))
总结:
通过以上过程可以发现,虽然在大方向上能够答出,但在细节、精细度上和大公司那些人还是有一些差距,这是今后做技术需要弥补的。
在此顺带给出Linux内核中container_of宏的完整实现,在include/linux/container_of.h中(实际上内核中有多处实现,但最为“正宗”的是这一个),代码如下:
/*** container_of - cast a member of a structure out to the containing structure* @ptr: the pointer to the member.* @type: the type of the container struct this is embedded in.* @member: the name of the member within the struct.** WARNING: any const qualifier of @ptr is lost.*/
#define container_of(ptr, type, member) ({ \void *__mptr = (void *)(ptr); \static_assert(__same_type(*(ptr), ((type *)0)->member) || \__same_type(*(ptr), void), \"pointer type mismatch in container_of()"); \((type *)(__mptr - offsetof(type, member))); })
这个正宗的container_of的定义比较复杂,换一个相对比较好理解的版本,在tools/include/linux/kernel.h中,代码如下:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)/*** container_of - cast a member of a structure out to the containing structure* @ptr: the pointer to the member.* @type: the type of the container struct this is embedded in.* @member: the name of the member within the struct.**/
#define container_of(ptr, type, member) ({ \const typeof(((type *)0)->member) * __mptr = (ptr); \(type *)((char *)__mptr - offsetof(type, member)); })
对比:

相关文章:
Linux内核与驱动面试经典“小”问题集锦(6)
接前一篇文章:Linux内核与驱动面试经典“小”问题集锦(5) 问题8 问:如何判断一个数是否是2的幂次(假设最多32位)? 备注:此问题是笔者年前参加小米面试时遇到的一个问题,…...
【zabbix】(四)-钉钉告警企业微信配置
前提条件: 已经安装了Python3环境(脚本需要requests模块)。Centos7.x自带Python2(不含requests模块) 钉钉告警配置 一 安装Python3 参考该优秀文档部署 查看Python的模块:pip list / pip3 list 报错 …...
python-自动化篇-办公-一键将word中的表格提取到excel文件中
文章目录 代码 工作中,经常需要将Word文档中的表格粘贴到Excel文件中,以便汇总及分析。一个一个复制粘贴,非常不方便,还是Python自动化操作,省心省力。要求如下图所示,即将word中的所有表格,转存…...
C#,数值计算,矩阵的行列式(Determinant)、伴随矩阵(Adjoint)与逆矩阵(Inverse)的算法与源代码
本文发布矩阵(Matrix)的一些初级算法。 一、矩阵的行列式(Determinant) 矩阵行列式是指矩阵的全部元素构成的行列式,设A(a)是数域P上的一个n阶矩阵,则所有A(a)中的元素组成的行列式称为矩阵A的行列式&…...
人工智能|推荐系统——基于tensorflow的个性化电影推荐系统实战(有前端)
代码下载: 基于tensorflow的个性化电影推荐系统实战(有前端).zip资源-CSDN文库 项目简介: dl_re_web : Web 项目的文件夹re_sys: Web app model:百度云下载之后,把model放到该文件夹下recommend: 网络模型相…...
Hive SQL编译成MapReduce任务的过程
目录 一、架构及组件介绍 1.1 Hive底层架构 1.2 Hive组件 1.3 Hive与Hadoop交互过程 二、Hive SQL 编译成MR任务的流程 2.1 HQL转换为MR源码整体流程介绍 2.2 程序入口—CliDriver 2.3 HQL编译成MR任务的详细过程—Driver 2.3.1 将HQL语句转换成AST抽象语法树 词法、语…...
【C++】快速上手map、multimap、set、multiset
文章目录 一、前言二、set / multiset1. 常见应用2. 核心操作 三、map / multimap1. 常见应用2. 核心操作 一、前言 S T L STL STL 中的关联式容器分为树型结构和哈希结构,树型结构主要有四种: s e t set set、 m u l t i s e t multiset multiset、 m a…...
【分享】图解ADS+JLINK调试ARM
文章是对LPC2148而写的,但是对三星的44B0芯片同样适用,只需要在选择时将相应的CPU选择的S3C44B0就可以了。 JLINK在ADS下调试心得 前两天一个客户用jlink在ADS下调试LPC2148总报错,这个错误我之前在调试LPC2200的时候也碰到过,后…...
反无人机系统技术分析,无人机反制技术理论基础,无人机技术详解
近年来,经过大疆、parrot、3d robotics等公司不断的努力,具有强大功能的消费级无人机价格不断降低,操作简便性不断提高,无人机正快速地从尖端的军用设备转入大众市场,成为普通民众手中的玩具。 然而,随着消…...
Kotlin和Java 单例模式
Java 和Kotlin的单例模式其实很像,只是Kotlin一部分单例可以用对象类和委托lazy来实现 Java /*** 懒汉式,线程不安全*/ class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (insta…...
软考 系统分析师系列知识点之信息系统战略规划方法(9)
接前一篇文章:软考 系统分析师系列知识点之信息系统战略规划方法(8) 所属章节: 第7章. 企业信息化战略与实施 第4节. 信息系统战略规划方法 7.4.5 信息工程方法 信息工程(Information Engineering,IE&…...
政安晨:示例演绎TensorFlow的官方指南(一){基础知识}
为什么要示例演绎? 既然有了官方指南,咱们在官方指南上看看就可以了,为什么还要写示例演绎的文章呢? 其实对于初步了解TensorFlow的小伙伴们而言,示例演绎才是最重要的。 官方文档已经假定了您已经具备了相当合适的…...
node - 与数据库交互
在Web开发中,与数据库交互是常见的需求,用于持久化存储、检索和操作数据。不同的后端技术和数据库类型(如关系型数据库和非关系型数据库)有着不同的交互方式。下面介绍几种常见的数据库交互方法。 关系型数据库 关系型数据库(如MySQL、PostgreSQL、SQLite)使用结构化查…...
速盾:2024年cdn在5g时代重要吗
在2024年,随着5G技术的普及与应用,内容分发网络(Content Delivery Network,CDN)在数字化时代中的重要性将进一步巩固和扩大。CDN是一种用于快速、高效地分发网络内容的基础设施,它通过将内容部署在全球各地…...
微信小程序(四十一)wechat-http的使用
注释很详细,直接上代码 上一篇 新增内容: 1.模块下载 2.模块的使用 在终端输入npm install wechat-http 没有安装成功vue的先看之前的一篇 微信小程序(二十)Vant组件库的配置- 如果按以上的成功配置出现如下报错先输入以下语句 …...
所有设计模式大全及学习链接
文章目录 创建型设计模式结构型设计模式行为型设计模式 创建型设计模式 一种创建对象的设计模式,它们提供了一种灵活的方式来创建对象,同时隐藏了对象的创建细节。以下是常见的创建型设计模式: 工厂方法模式(Factory Method Patte…...
【Java程序设计】【C00264】基于Springboot的原创歌曲分享平台(有论文)
基于Springboot的原创歌曲分享平台(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的原创歌曲分享平台 本系统分为平台功能模块、管理员功能模块以及用户功能模块。 平台功能模块:在平台首页可以查看首…...
2024年,要特别注意这两个方位
家居风水对每个家庭都非常重要,可在无形中影响到人们的事业、财富以及健康运势。俗话说:“风水轮流转”,2024年为甲辰龙年,斗转星移、九宫飞星将改变宫位,新一年的磁场即将启动,方位的吉凶也会重新变动&…...
【Chrono Engine学习总结】5-sensor-5.1-sensor基础并创建一个lidar
由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。 1、Sensor模块 Sensor模块是附加模块,需要单独安装。参考:【Chrono Engine学习总结】1-安装配置与程序运行 Sensor Module Tutorial Sensor …...
springboot/ssm学生信息管理系统Java学生在线选课考试管理系统
springboot/ssm学生信息管理系统Java学生在线选课考试管理系统 开发语言:Java 框架:springboot(可改ssm) vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
