linux设备驱动开发---平台设备驱动程序

文章目录

  • 1 平台驱动程序
  • 2 平台设备
    • 2.1 资源和平台数据
      • 1 设备配置---废弃的旧方法
        • 资源
        • 平台数据
        • 声明平台设备
      • 2 设备配置---推荐的新方法
  • 3 设备、驱动程序和总线匹配
    • OF风格
    • ACPI
    • ID表匹配
    • 匹配平台设备的名字和平台驱动的名字
    • 平台设备和平台驱动程序如何匹配
  • 4 Platfrom架构驱动程序

有些物理总线已为人熟知:USB、I2S、I2C、UART、SPI、PIC、SATA等。这种总线是名为控制器的硬件设备。由于它们是SoC的一部分,因此无法删除,不可发现,也称为平台设备。

从SoC的角度来看,这些设备(总线)内部通过专用总线连接,而且大部分时间是专用的,专门针对制造商。从内核的角度来看,这些是根设备,未连接到任何设备,也就是未连接到任何总线上。这就是伪平台总线的用途,伪平台总线也称为平台总线,是内核虚拟总线,该总线实际不存在,用于连接不在内核所知物理总线上的设备和驱动程序,也就是根设备和其相关的驱动程序。在下面的讨论中,平台设备是指依靠伪平台总线的设备。

处理平台设备实际上需要两个步骤:

  1. 注册管理设备的平台驱动程序(具有唯一的名称)。
  2. 注册平台设备(与驱动程序具有相同的名称)及其资源,以便内核获取设备位置。

1 平台驱动程序

在进一步介绍之前,请注意以下警告,并非所有平台设备都由平台驱动程序处理。平台驱动程序专用于不基于传统总线的设备。I2C设备或SPI设备是平台设备,但分别依赖I2C或SPI总线,而不是平台总线。对于平台驱动程序一切都需手工完成。平台驱动程序必须实现probe函数,在插入模块或设备声明时,内核调用它。在开发平台驱动程序时,必须填写主结构struct platform_driver,由它来代表平台驱动程序,并用专门函数把驱动程序注册到平台总线上。
struct platform_driver定义在include/linux/platform_device.h中

struct platform_driver {int (*probe)(struct platform_device *);	/* 设备和驱动匹配后调用的函数 */int (*remove)(struct platform_device *);	/* 驱动程序不再为设备所需而要删除时调用的函数 */void (*shutdown)(struct platform_device *);	/* 设备被关闭时调用的代码 */int (*suspend)(struct platform_device *, pm_message_t state);	/* 设备被挂起执行的函数 */int (*resume)(struct platform_device *);	/* 设备从挂起中恢复所执行的函数 */struct device_driver driver;		/* 设备驱动 */const struct platform_device_id *id_table;	/* 设备的ID表 */bool prevent_deferred_probe;
};/*** struct device_driver - The basic device driver structure* @name:	Name of the device driver.* @bus:	The bus which the device of this driver belongs to.* @owner:	The module owner.* @mod_name:	Used for built-in modules.* @suppress_bind_attrs: Disables bind/unbind via sysfs.* @probe_type:	Type of the probe (synchronous or asynchronous) to use.* @of_match_table: The open firmware table.* @acpi_match_table: The ACPI match table.* @probe:	Called to query the existence of a specific device,*		whether this driver can work with it, and bind the driver*		to a specific device.* @remove:	Called when the device is removed from the system to*		unbind a device from this driver.* @shutdown:	Called at shut-down time to quiesce the device.* @suspend:	Called to put the device to sleep mode. Usually to a*		low power state.* @resume:	Called to bring a device from sleep mode.* @groups:	Default attributes that get created by the driver core*		automatically.* @pm:		Power management operations of the device which matched*		this driver.* @p:		Driver core's private data, no one other than the driver*		core can touch this.** The device driver-model tracks all of the drivers known to the system.* The main reason for this tracking is to enable the driver core to match* up drivers with new devices. Once drivers are known objects within the* system, however, a number of other things become possible. Device drivers* can export information and configuration variables that are independent* of any specific device.*/
struct device_driver {const char		*name;struct bus_type		*bus;struct module		*owner;const char		*mod_name;	/* used for built-in modules */bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */enum probe_type probe_type;const struct of_device_id	*of_match_table;const struct acpi_device_id	*acpi_match_table;int (*probe) (struct device *dev);int (*remove) (struct device *dev);void (*shutdown) (struct device *dev);int (*suspend) (struct device *dev, pm_message_t state);int (*resume) (struct device *dev);const struct attribute_group **groups;const struct dev_pm_ops *pm;struct driver_private *p;
};

在内核中注册平台驱动程序很简单,只需在init函数中调用platform_driver_register()或platform_driver_probe()。这两个函数之间的区别如下:

  • platform_driver_register():注册驱动程序并将其放入由内核维护的驱动程序列表中,内核遍历注册的平台设备表,每当发现新的匹配时就可以按需调用其probe函数。为防止驱动程序在该列表中插入和注册,请使用下一个函数。
  • platform_driver_probe():调用该函数后,内核立即运行匹配循环,检查是否有平台设备名称匹配,如果匹配则调用驱动程序的probe,这意味着设备存在,否则,驱动程序将被忽略。此方法可防止延迟探测,因为它不会在系统上注册驱动程序

platform_driver_probe和 platform_driver_register的一点区别就是,如果设备是热插拔的,那么就使用 platform_driver_register函数,因为platform_driver_register将驱动注册到内核上,每当发现新的匹配时就可以按需调用其probe函数;如果设备不是热插拔的,例如dm368芯片中的USB接口,这种情况下usb控制器是在片内集成的,任何情况下都不会出现插拔情况,这种情况下可以使用函数 platform_driver_probe,platform_driver_probe被调用后,就开始匹配,如果没有匹配上,驱动程序将被忽略。

2 平台设备

实际上,应该叫伪平台设备,完成驱动程序后,必须向内核提供需要该驱动程序的设备。平台设备在内核中表示为struct platform_device的实例,定义在文件include/linux/platform_device.h中。如下所示:

struct platform_device {const char	*name; /* 用于和platform_driver进行匹配的名字 */int		id;	/* 设备ID */bool		id_auto;struct device	dev;u32		num_resources;		/* resource的个数*/struct resource	*resource;	/* 资源数组 */const struct platform_device_id	*id_entry;char *driver_override; /* Driver name to force a match *//* MFD cell pointer */struct mfd_cell *mfd_cell;/* arch specific additions */struct pdev_archdata	archdata;
};

对于平台驱动程序,在驱动程序和设备匹配之前,struct platform_device的name字段要和 struct platform_driver.driver.name相同,这样才能匹配上。

使用platform_device_register(struct platform_device *pdev)函数注册平台设备

2.1 资源和平台数据

在可热插拔的另一端,内核不知道系统上存在那些设备、它们能够做什么,或者需要什么才能运行。因为没有自主协商的过程,所以提供给内核的任何信息都会收到欢迎。有两种方法可以把相关设备所需的资源和数据通知内核

1 设备配置—废弃的旧方法

这种方法用于不支持设备树的内核版本,使用这种方法,驱动程序可以保持其通用性,使设备注册到与开发板相关的源文件中。

资源

资源代表设备在硬件方面的所有特征元素,以及设备所需的所有元素,以便设置使其正常运行,平台设备struct platform_devicestruct source *resource描述其资源。内核中只有6种类型的资源,全部列在include/linux/ioport.h中,并用标志来描述资源类型:

#define IORESOURCE_IO		0x00000100	/* PCI/ISA I/O ports */
#define IORESOURCE_MEM		0x00000200	/*内存区域 */
#define IORESOURCE_REG		0x00000300	/* Register offsets */
#define IORESOURCE_IRQ		0x00000400	/* IRQ线 */
#define IORESOURCE_DMA		0x00000800	/* DMA通道 */
#define IORESOURCE_BUS		0x00001000	/* 总线 */

资源在内核中表示为struct resource的实例:

struct resource {resource_size_t start;resource_size_t end;const char *name;unsigned long flags;unsigned long desc;struct resource *parent, *sibling, *child;
};
  • start/end:这代表资源的开始结束位置。对于I/O或内存区域,它表示开始结束位置。对于中断线、总线或DMA通道,开始结束必须具有相同的值。
  • flags:这是表示资源类型的掩码,例如IORESOURCE_BUS
  • name:标识或描述资源

一旦提供了资源,就需要在驱动中获取使用它们。probe功能是获取它们的好地方。嵌入在struct platform_device中的struct resource可以通过platform_get_resource函数进行检索:

struct resource *platform_get_resource(struct platform_device *dev,unsigned int type,unsigned int num);

第一个参数是平台设备自身的实例。第二个参数说明需要什么样的资源。对于内存,它应该是IORESOURCE_MEM。num是一个索引,表示需要那个资源类型,0表示第一个,以此类推。

平台数据

所有类型不属于上一部分所列举资源的其他数据都属于这里(如GPIO)。无论它们是什么类型,struct platform_device都包含struct device字段,该字段又包含struct platform_data字段。通常,应该将数据嵌入结构中,将其传输到platform_data字段中。

声明平台设备

用设备的资源和数据注册设备,在这个废弃的方法中,它们声明在单独的模块中或者arch/<arch>/mach-xxx/yyy.c的开发板init文件中,在函数platform_device_register()内实现声明:

static struct platform_device my_device = {//进行初始化
};
platform_device_register(&my_device);

2 设备配置—推荐的新方法

在第一种方法中,任何修改都需要重构整个内核。如果内核必须包含所有应用程序/开发板特殊配置,则其大小将会大大增加。为了简单起见,从内核源中分离设备声明,并引入一个新的概念:设备树(DTS)。设备树(DTS)的主要目的是从内核中删除特定且从未测试过的代码。使用设备树,平台数据和资源时同质的。设备树是硬件描述文件,其格式类似于树形结构,每个设备用一个结点表示,任何数据、资源或配置数据都表示为结点的属性。这样,在做一些修改只需重新编译设备树。

3 设备、驱动程序和总线匹配

在匹配发生之前,Linux会调用platform_match(struct device *dev,struct device_driver *drv) 。平台设备(struct platform_device的实例)通过字符(name字段)与驱动程序匹配(struct platform_driver.driver.name)。根据Linux设备模型,总线元素是最重要的部分。每个总线都维护一个注册的驱动程序和设备列表。总线驱动程序负责设备和驱动程序的匹配。每当连接新设备或者向总线添加新的驱动程序时,总线都会启动匹配循环

现在,假设使用I2C核心提供的函数注册新的I2C设备。内核提供如下方法触发I2C总线匹配循环:调用由I2C总线驱动程序注册的I2C核心匹配函数,以检查是否有已注册的驱动程序与该设备匹配。如果没有匹配,则什么都不做;如果发现匹配,则内核通知设备管理器(udev/mdev),由它加载与设备匹配的驱动程序。一旦设备驱动程序加载完成,其probe()函数将立即执行。不仅I2C这样运行,而且每个总线自己的匹配机制都大致于此相同。总线匹配循环在每个设备或驱动程序注册时被触发。

内核负责平台设备和驱动程序匹配功能的函数在/drivers/base/platform.c中,定义如下:

/*** platform_match - bind platform device to platform driver.* @dev: device.* @drv: driver.** Platform device IDs are assumed to be encoded like this:* "<name><instance>", where <name> is a short description of the type of* device, like "pci" or "floppy", and <instance> is the enumerated* instance of the device, like '0' or '42'.  Driver IDs are simply* "<name>".  So, extract the <name> from the platform_device structure,* and compare it against the name of the driver. Return whether they match* or not.*/
static int platform_match(struct device *dev, struct device_driver *drv)
{struct platform_device *pdev = to_platform_device(dev);struct platform_driver *pdrv = to_platform_driver(drv);/* When driver_override is set, only bind to the matching driver */if (pdev->driver_override)return !strcmp(pdev->driver_override, drv->name);/* Attempt an OF style match first */if (of_driver_match_device(dev, drv))return 1;/* Then try ACPI style match */if (acpi_driver_match_device(dev, drv))return 1;/* Then try to match against the id table */if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;/* fall-back to driver name match */return (strcmp(pdev->name, drv->name) == 0);
}

该函数的描述如下:

平台设备 ID 假定编码如下:“<name><instance>”,其中\ <name>是设备类型的简短描述,如“pci”或“floppy”,<instance> 是 设备的枚举实例,如“0”或“42”。 驱动程序 ID只是“<name>”。 因此,从 platform_device 结构中提取 <name>,并将其与驱动程序的名称进行比较。返回它们是否匹配。

对于平台驱动程序,在驱动程序和设备匹配之前,struct platform_device的name字段要和 struct platform_driver.driver.name相同,这样才能匹配上。

匹配顺序如下:

  1. 平台设备设置 driver_override 时,仅绑定到匹配的驱动程序
  2. 尝试OF(Open Firmware,开放固件)风格匹配
  3. 尝试ACPI风格匹配
  4. 尝试ID表匹配
  5. 匹配平台设备的名字和平台驱动的名字

OF风格

/*** of_driver_match_device - Tell if a driver's of_match_table matches a device.* @drv: the device_driver structure to test* @dev: the device structure to match against*/
static inline int of_driver_match_device(struct device *dev,const struct device_driver *drv)
{return of_match_device(drv->of_match_table, dev) != NULL;
}

of_driver_match_device判断驱动程序的 of_match_table 是否与设备匹配。

ACPI

ACPI基于ACPI表,不讨论

ID表匹配

ID表基于struct device_id结构。所有设备ID结构都在include/linux/mod_devicetable.h中定义。要找到正确的结构名称,需要在device_id前加上设备驱动程序所在的总线名称。例如:对于I2C,结构名称是struct i2c_device_id,而平台设备是struct platform_device_id,SPI设备是spi_device_id

if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;static const struct platform_device_id *platform_match_id(const struct platform_device_id *id,struct platform_device *pdev)
{while (id->name[0]) {if (strcmp(pdev->name, id->name) == 0) {pdev->id_entry = id;return id;}id++;}return NULL;
}

平台驱动的id_table是 平台驱动的ID表,类似是platform_device_id

struct platform_device_id {char name[PLATFORM_NAME_SIZE];kernel_ulong_t driver_data;
};

name字段必须与注册设备时所指定的设备名称相同,platform_match_id函数会找到平台驱动的ID表,然后遍历ID表中的ID,将每个ID的name字段与平台设备的name作比较,如果相同,则平台设备的id_entry 等于ID,然后返回该ID,如果没有ID的name字段和平台设备的name相同,返回NULL。

无论如何,如果ID表已经注册,则每当内核运行匹配函数为止或新的平台设备查找驱动程序时,都会遍历ID表。如果匹配成功,则调用已匹配驱动程序的probe函数。

匹配平台设备的名字和平台驱动的名字

现在大多数平台驱动程序根本不提供任何ID表,它们只在程序名称字段中填写驱动程序本身的名称。但是仍然可行,因为platform_match函数,在最后会回到名字匹配,比较驱动程序名称和设备名称。

	/* fall-back to driver name match */return (strcmp(pdev->name, drv->name) == 0);

平台设备和平台驱动程序如何匹配

MODULE_DEVICE_TABLE(type,name)宏让驱动程序公开其ID表,该表描述它可以支持那些设备。同时,如果驱动程序可以编译成模块,则平台驱动实例的driver.name字段要与模块名称匹配。如果不匹配,模块则不会自动加载,除非已经使用MODULE_ALIAS宏为模块添加了另一个名称。编译时,从所有驱动程序中提取该消息,以构建设备表。当设备和驱动程序匹配时,内核遍历设备表。如果找到的条目与添加的设备兼容,并与设备/供应商ID或名称匹配,则加载提供该匹配的模块,运行模块的init函数,调用probe函数。

MODULE_DEVICE_TABLE宏在linux/module.h中定义:

/* Creates an alias so file2alias.c can find device table. */
#define MODULE_DEVICE_TABLE(type, name)					\
extern const typeof(name) __mod_##type##__##name##_device_table		\__attribute__ ((unused, alias(__stringify(name))))
  • type:这可以是i2c、spi、acpi、of、platform、usb、pci。也可以是在include/linux/mod_devicetable.h中找到的其他任何总线
  • name:这是XXX_device_id数组上的指针,用于设备匹配。对于I2C设备。结构是i2c_device_id。对于设备树的Open Firmware(开放固件,OF)匹配机制,必须使用of_device_id。

4 Platfrom架构驱动程序

代码原文章:https://www.toutiao.com/article/6874918991081505283/?log_from=d62ff69d6ea06_1651283905265

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/slab.h>#define BUFFER_MAX    (10)
#define OK            (0)
#define ERROR         (-1)struct cdev *gDev;
struct file_operations *gFile;
dev_t  devNum;
unsigned int subDevNum = 1;
int reg_major  =  232;    
int reg_minor =   0;
char *buffer;
#define LEDBASE	0x56000010
#define LEDLEN	0x0cint hello_open(struct inode *p, struct file *f)
{printk(KERN_INFO "hello_open\r\n");return 0;
}ssize_t hello_write(struct file *f, const char __user *u, size_t s, loff_t *l)
{printk(KERN_INFO "hello_write\r\n");return 0;
}
ssize_t hello_read(struct file *f, char __user *u, size_t s, loff_t *l)
{printk(KERN_INFO "hello_read\r\n");      return 0;
}static int  hellodev_probe(struct platform_device *pdev)
{printk(KERN_INFO "hellodev_probe\n");devNum = MKDEV(reg_major, reg_minor);if(OK == register_chrdev_region(devNum, subDevNum, "helloworld")){printk(KERN_INFO "register_chrdev_region ok \n"); }else {printk(KERN_INFO "register_chrdev_region error n");return ERROR;}printk(KERN_INFO " hello driver init \n");gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);gFile->open = hello_open;gFile->read = hello_read;gFile->write = hello_write;gFile->owner = THIS_MODULE;cdev_init(gDev, gFile);cdev_add(gDev, devNum, 1);return 0;
}
static int hellodev_remove(struct platform_device *pdev)
{printk(KERN_INFO "hellodev_remove \n");cdev_del(gDev);kfree(gFile);kfree(gDev);unregister_chrdev_region(devNum, subDevNum);return;
}static void hello_plat_release(struct device *dev)
{return;
}
static struct resource hello_dev_resource[] = {[0] = {.start = LEDBASE,.end   = LEDBASE + LEDLEN - 1,.flags = IORESOURCE_MEM,}
};struct platform_device hello_device = {.name		  = "hello-device",.id		  = -1,.num_resources	  = ARRAY_SIZE(hello_dev_resource),.resource	  = hello_dev_resource,.dev = {.release = hello_plat_release,}
};
static struct platform_driver hellodev_driver = {.probe		= hellodev_probe,.remove		= hellodev_remove,.driver		= {.owner	= THIS_MODULE,.name	= "hello-device",},
};int charDrvInit(void)
{platform_device_register(&hello_device);return platform_driver_register(&hellodev_driver); 
}void __exit charDrvExit(void)
{platform_device_unregister(&hello_device);platform_driver_unregister(&hellodev_driver);return;
}
module_init(charDrvInit);
module_exit(charDrvExit);
MODULE_LICENSE("GPL");

Makefile:

ifneq ($(KERNELRELEASE),)
obj-m := helloDev.o
else
PWD := $(shell pwd)
#KDIR:=/home/jinxin/linux-4.9.229
#KDIR:= /lib/modules/4.4.0-31-generic/build
KDIR := /lib/modules/`uname -r`/build
all:make -C $(KDIR) M=$(PWD)
clean:	rm -rf *.o *.ko *.mod.c *.symvers *.c~ *~
endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/379543.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

标题:乘积尾零

标题&#xff1a;乘积尾零 如下的10行数据&#xff0c;每行有10个整数&#xff0c;请你求出它们的乘积的末尾有多少个零&#xff1f; 5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 9937 1173 6866 3397 4759 7557 3070…

Robots.txt指南

Robots.txt指南当搜索引擎访问一个网站时&#xff0c;它首先会检查该网站的根域下是否有一个叫做robots.txt的纯文本文件。Robots.txt文件用于限定搜索引擎对其 网站的访问范围&#xff0c;即告诉搜索引擎网站中哪些文件是允许它进行检索(下载)的。这就是大家在网络上常看到的“…

fwrite函数的用法示例_C语言中的fwrite()函数(带有示例)

fwrite函数的用法示例C中的fwrite()函数 (fwrite() function in C) Prototype: 原型&#xff1a; size_t fwrite(void *buffer, size_t length, size_t count, FILE *filename);Parameters: 参数&#xff1a; void *buffer, size_t length, size_t count, FILE *filenameRetu…

标题:递增三元组

标题&#xff1a;递增三元组 给定三个整数数组 A [A1, A2, … AN], B [B1, B2, … BN], C [C1, C2, … CN]&#xff0c; 请你统计有多少个三元组(i, j, k) 满足&#xff1a; 1 < i, j, k < NAi < Bj < Ck 【输入格式】 第一行包含一个整数N。 第二行包含N个整…

伙伴算法、slab机制、内存管理函数

文章目录1 伙伴算法页框操作alloc_pages()2 slabslab机制要解决的问题使用高速缓存3 内存管理函数kmallockzallocvmallocvzalloc区别参考文章内核使用struct page结构体描述每个物理页&#xff0c;也叫页框。内核在很多情况下&#xff0c;需要申请连续的页框&#xff0c;而且数…

eval 函数 代替函数_eval()函数以及JavaScript中的示例

eval 函数 代替函数eval()函数 (eval() function) eval() function is a predefined global function in JavaScript and it is used to evaluate (execute) an expression, which is passed to the function as a parameter. It can also evaluate any JavaScript code. eval(…

F# ≥ C#(活动模式 和枚举)

F#提供了一个叫"活动模式"的有趣功能。它把输入的数据转换成其他不同的东西。 一个有趣的使用实例就是代替枚举。但我编程枚举的时候&#xff0c;我总不高兴去链接枚举项到它的定义。例如&#xff0c;下面的枚举定义了 数字枚举&#xff0c; enum Numbers{Odd,Even,}…

关于java的classpath设置

今天晚上实验室的另一个人在编译一个java程序&#xff0c;需要用到一个jar文件&#xff0c;所以在命令行编译的时候需要添加jar的路径&#xff0c;例如&#xff1a; java -classpath demo.jar hello 但是设置了path之后java就不会搜索当前目录&#xff0c;也就是所如果hello在当…

C语言uthash的用法

文章目录1 定义一个哈希表键值UT_hash_handle2 哈希操作声明添加查找删除获取哈希表中元素个数迭代排序3 案例键的使用官网解释&#xff1a;https://troydhanson.github.io/uthash/userguide.html 在使用之前&#xff0c;我们必须包含uthash.h的头文件&#xff0c;你需要将该头…

Javascript Paste Keyboard Shortcuts Hijack

author : kj021320 team : I.S.T.O 这样的攻击手段也算是极其无耻 猥琐之极! 所以防御措施一定要做好 首先说一下通过Javascript Paste Keyboard Shortcuts Hijack能做什么???能够读取你本地机器任何文件! 没错!也就是说 你中了任何一个XSS 加上你按了粘贴快捷键后,你就有可…

python 生成器表达式_Python中的列表理解与生成器表达式

python 生成器表达式The list is a collection of different types of elements and there are many ways of creating a list in Python. 该列表是不同类型元素的集合&#xff0c;并且有许多方法可以在Python中创建列表。 清单理解 (List Comprehension) List comprehension…

Javaweb---监听器

1.什么是监听器 监听器就是监听某个对象的状态变化的组件。 事件源&#xff1a;被监听的对象 ----- 三个域对象 request session servletContext 监听器&#xff1a;监听事件源对象 事件源对象的状态的变化都会触发监听器 ---- 62 注册监听器&#xff1a;将监听器与事件源进行…

Linux中的Ramdisk和Initrd

Ramdisk简介先简单介绍一下ramdisk&#xff0c;Ramdisk是虚拟于RAM中的盘(Disk)。对于用户来说&#xff0c;能把RAM disk和通常的硬盘分区&#xff08;如/dev/hda1&#xff09;同等对待来使用&#xff0c;例如&#xff1a;redice # mkfs.ext2 /dev/ram0mke2fs 1.38 (30-Jun-200…

slab下kmalloc内核函数实现

文章目录kmalloc的整体实现获取高速缓存高速缓存获取index总结https://blog.csdn.net/qq_41683305/article/details/124554490&#xff0c;在这篇文章中&#xff0c;我们介绍了伙伴算法、slab机制和常见的内存管理函数&#xff0c;接下来&#xff0c;我们看看kmalloc内核函数的…

PHP array_merge_recursive()函数与示例

PHP array_merge_recursive()函数 (PHP array_merge_recursive() function) array_merge_recursive() function is used to merge two or more arrays, it returns a new array with merged elements. The only difference between array_merge() and array_merge_recursive() …

标题:三羊献瑞

标题&#xff1a;观察下面的加法算式&#xff1a; 其中&#xff0c;相同的汉字代表相同的数字&#xff0c;不同的汉字代表不同的数字。 请你填写“三羊献瑞”所代表的4位数字&#xff08;答案唯一&#xff09;&#xff0c;不要填写任何多余内容。 思路分析&#xff1a; 首先…

hdu 1069

地址&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1069 题意&#xff1a;给定若干个木块长宽高&#xff0c;长宽高可以自己调整&#xff0c;求堆积起来最高的高度。 mark&#xff1a;枚举所有木块长宽高可能情况&#xff0c;简单dp。 代码&#xff1a; #include <…

简明 Python 编程规范

简明 Python 编程规范编码 所有的 Python 脚本文件都应在文件头标上 # -*- coding:utf-8 -*- 。设置编辑器&#xff0c;默认保存为 utf-8 格式。注释 业界普遍认同 Python 的注释分为两种的概念&#xff0c;一种是由 # 开头的“真正的”注释&#xff0c;另一种是 docstri…

进程虚拟地址管理

文章目录1 地址分布实际使用中的内存区域2 进程的虚拟地址描述用户空间mmap线程之间共享内存地址的实现机制1 地址分布 现在采用虚拟内存的操作系统通常都使用平坦地址空间&#xff0c;平坦地址空间是指地址空间范围是一个独立的连续空间&#xff08;比如&#xff0c;地址从0扩…

java两个文件夹比较路径_比较Java中两个文件的路径

java两个文件夹比较路径Given the paths of the two files and we have two compare the paths of the files in Java. 给定两个文件的路径&#xff0c;我们有两个比较Java中文件的路径。 Comparing paths of two files 比较两个文件的路径 To compare the paths of two file…