一些关于Linux内核中的结构体函数指针的理解

news/2024/10/31 1:23:50/

一些关于Linux内核中常用的结构体函数指针的理解

动机

在看linux内核代码的时候经常能够看到一些结构体里面的成员跟我们以往见的到一些结构体不一样,常见的架构体如下面的代码:

struct a{int i;char b;struct c;
};

而内核中又见有这样的一些结构体:

const struct a{.a  = read,.b  = write,};

这种结构体我很少见,而且很多书籍上没有见过这样的结构体,搜索了一些资料,写下一些对这些结构体的理解

例子

首先放上三段代码作为一个例子
先放上第一段代码:

struct address_space_operations {int (*writepage)(struct page *page, struct writeback_control *wbc);int (*readpage)(struct file *, struct page *);/* Write back some dirty pages from this mapping. */int (*writepages)(struct address_space *, struct writeback_control *);/* Set a page dirty.  Return true if this dirtied it */int (*set_page_dirty)(struct page *page);int (*readpages)(struct file *filp, struct address_space *mapping,struct list_head *pages, unsigned nr_pages);int (*write_begin)(struct file *, struct address_space *mapping,loff_t pos, unsigned len, unsigned flags,struct page **pagep, void **fsdata);int (*write_end)(struct file *, struct address_space *mapping,loff_t pos, unsigned len, unsigned copied,struct page *page, void *fsdata);/* Unfortunately this kludge is needed for FIBMAP. Don't use it */sector_t (*bmap)(struct address_space *, sector_t);void (*invalidatepage) (struct page *, unsigned int, unsigned int);int (*releasepage) (struct page *, gfp_t);
}

这是第二段代码:

const struct address_space_operations v9fs_addr_operations = {.readpage = v9fs_vfs_readpage,.readpages = v9fs_vfs_readpages,.set_page_dirty = __set_page_dirty_nobuffers,.writepage = v9fs_vfs_writepage,.write_begin = v9fs_write_begin,.write_end = v9fs_write_end,.releasepage = v9fs_release_page,.invalidatepage = v9fs_invalidate_page,.launder_page = v9fs_launder_page,.direct_IO = v9fs_direct_IO,
};

这是第三段代码:

static int v9fs_vfs_readpage(struct file *filp, struct page *page)
{return v9fs_fid_readpage(filp->private_data, page);
}

首先,我们可以看到,我们常见的那种结构体形式就是第二段代码中的这种形式。而弄懂这种形式就是我们这个文章的目的。
我们先需要知道的是,这个结构体里面的东西是函数指针,也就是说,这个成员的变量是跟函数有关的。

我们先看第二段代码,第二段代码除了里面的东西以外,外面的那层还是我们熟悉的东西:结构体

const struct address_space_operations v9fs_addr_operations

看到这个,我们或许知道了v9fs_addr_operations是类型为结构体address_space_operations的变量。

好了,现在我们知道v9fs_addr_operations的类型是结构体address_space_operations,那我们就看看第一段代码:
第一段代码里面,我们看到了很多声明,例如

int (*readpage)(struct file *, struct page *);

这里就是声明了结构体中address_space_operations的一个readpage的函数指针,说明了结构体address_space_operations中有一个名为readpage的,入参为(struct file *, struct page *)的一个函数。

至此,我们就知道了这个结构体里面的声明是咋回事了。

然后我们再看回第二段代码,这时我们就知道了v9fs_addr_operations中的readpage是指向函数v9fs_vfs_readpage的了。但是v9fs_vfs_readpage又是什么东西呢?这个时候请看第三段代码。
这里就实现了v9fs_vfs_readpage。v9fs_vfs_readpage里面实际调用的是v9fs_fid_readpage(filp->private_data, page);这个函数。
因此,大体的流程我归纳如下:
v9fs_addr_operations.readpage(filp->private_data, page) -> v9fs_fid_readpage(filp->private_data, page);

那为什么要搞的这么复杂呢?
我个人认为,这种方法有点类似于面向对象的抽象。把一大类具有相同特征的操作抽象出来,用我们文章中的例子,对于地址空间的操作,基本就是读、写、设脏等等的操作,这样可以把这些操作抽象成一个对象,在这里用一个结构体struct address_space_operations来搞定,这样,address_space_operations就是这些操作的一个父类。

然后现在要对v9fs进行操作,我们只需要实例化一个具体针对v9fs的对象,这时候我们就生成一个类型为struct address_space_operations的对象v9fs_addr_operations。在里面将需要调用的操作指向我们具体的函数,就能实现对于多种函数实现的情景下统一接口拉


http://www.ppmy.cn/news/21388.html

相关文章

【MyBatis】| MyBatis查询语句专题(核心知识)

目录 一&#xff1a;MyBatis查询语句专题 1. 返回Car对象 2. 返回List<Car> 3. 返回Map 4. 返回List<Map> 5. 返回Map<String,Map> 6. resultMap结果映射 7. 返回总记录条数 一&#xff1a;MyBatis查询语句专题 前期准备&#xff1a; 模块名&#xf…

springboot+mongodb初体验

MongoDB 是一个基于分布式文件存储的数据库。由 C 语言编写&#xff0c;旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。 1、mongodb服务…

CMOS器件与TTL器件CMOS电平与TTL电平

常用的数字芯片&#xff0c;按制造工艺主要分为TTL器件和CMOS器件。TTL器件是指其内部主要逻辑单元为双极性晶体管&#xff0c;CMOS器件是指其内部的主要逻辑单元为MOS管。现在绝大部分数字芯片使用的工艺都是CMOS工艺&#xff0c;在一些比较老的74系列芯片中还使用的是TTL工艺…

智能驾驶 车牌检测和识别(五)《C++实现车牌检测和识别(可实时车牌识别)》

智能驾驶 车牌检测和识别&#xff08;五&#xff09;《C实现车牌检测和识别&#xff08;可实时车牌识别&#xff09;》 目录 智能驾驶 车牌检测和识别&#xff08;五&#xff09;《C实现车牌检测和识别&#xff08;可实时车牌识别&#xff09;》 1. 前言 2. 车牌检测模型&a…

LeetCode 2283. 判断一个数的数字计数是否等于数位的值

给你一个下标从 0 开始长度为 n 的字符串 num &#xff0c;它只包含数字。 如果对于 每个 0 < i < n 的下标 i &#xff0c;都满足数位 i 在 num 中出现了 num[i]次&#xff0c;那么请你返回 true &#xff0c;否则返回 false 。 示例 1&#xff1a; 输入&#xff1a;…

C++11 右值引用和移动语义

作者&#xff1a;小萌新 专栏&#xff1a;C进阶 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍C11的右值引用和移动语义 右值引用和移动语义基本概念左值和右值左值引用和右值引用右值引用的使用场景和意义左值引用的使用场景左…

03 python爬虫 (MySQL/MongoDB)

MySQL操作实例&#xff1a;MySQL数据库基本操作_Drw_Dcm的博客-CSDN博客_mysql数据库操作 MySQL是一种关系数据库管理系统&#xff0c;是一种开源软件4、MySQL 进入命令 mysql –h127.0.0.1 –uroot –p211574 –P3306MySQL数据库的安装 https://www.jb51.net/article/167782…

信息安全管理体系认证

​ISO信息安全管理体系认证 一、什么是ISO信息安全管理体系认证&#xff1f; ISO是信息安全管理体系认证&#xff0c;是由国际标准化组织&#xff08;ISO&#xff09;采纳英国标准协会BS-2标准后实施的管理体系&#xff0c;成为了“信息安全管理”的国际通用语言&#xff0c;企…