Linux内核的pstore工具的源码逐行解析
时间: 2023-05-31 22:03:16 浏览: 179
Linux内核源代码导读
5星 · 资源好评率100%
pstore是一个用于存储内核崩溃数据的框架,它提供了一种将内核崩溃数据存储到持久化存储介质中的方法。在内核崩溃时,pstore会将崩溃数据写入到一个特定的存储介质中,比如硬盘或闪存,以便在下次启动时可以将这些数据恢复回来。
pstore的源代码包含在Linux内核源码中,下面我们将逐行解析pstore的源代码:
1. pstore.h头文件定义了pstore的相关数据结构和函数原型。
```c
#ifndef _LINUX_PSTORE_H
#define _LINUX_PSTORE_H
struct pstore_info {
char name[32]; /* Name of the backend */
void *data; /* Backend specific data */
struct device *dev; /* Device associated with backend */
struct list_head list; /* List of backends in use */
};
/* Register a backend with pstore */
int pstore_register(struct pstore_info *psi);
/* Unregister a backend from pstore */
void pstore_unregister(struct pstore_info *psi);
/* Write data to pstore */
int pstore_write(enum pstore_type_id type, const void *buf, size_t size);
/* Read data from pstore */
ssize_t pstore_read(enum pstore_type_id type, void *buf, size_t size);
#endif /* _LINUX_PSTORE_H */
```
2. pstore-core.c文件是pstore的核心实现文件,它定义了pstore的主要功能函数。
```c
static struct list_head pstore_backends;
/* Register a backend with pstore */
int pstore_register(struct pstore_info *psi)
{
if (!psi || !psi->name || !psi->dev)
return -EINVAL;
if (strlen(psi->name) >= sizeof(psi->name))
return -ENAMETOOLONG;
if (psi->data)
psi->dev->driver_data = psi->data;
list_add_tail(&psi->list, &pstore_backends);
return 0;
}
/* Unregister a backend from pstore */
void pstore_unregister(struct pstore_info *psi)
{
list_del(&psi->list);
}
/* Write data to pstore */
int pstore_write(enum pstore_type_id type, const void *buf, size_t size)
{
struct pstore_info *psi;
int rc;
list_for_each_entry(psi, &pstore_backends, list) {
if (psi->ops && psi->ops->write) {
rc = psi->ops->write(psi->dev, type, buf, size);
if (rc >= 0)
return rc;
}
}
return -ENODEV;
}
/* Read data from pstore */
ssize_t pstore_read(enum pstore_type_id type, void *buf, size_t size)
{
struct pstore_info *psi;
ssize_t rc;
list_for_each_entry(psi, &pstore_backends, list) {
if (psi->ops && psi->ops->read) {
rc = psi->ops->read(psi->dev, type, buf, size);
if (rc >= 0)
return rc;
}
}
return -ENODEV;
}
```
3. pstore-ram.c文件是pstore的一个后端实现,它将崩溃数据存储在内存中。
```c
struct pstore_ram_zone {
size_t max_size;
size_t curr_size;
void *data;
};
static struct pstore_ram_zone pstore_ram_zones[PSRAM_NUM_ZONES];
static int pstore_ram_write(struct device *dev, enum pstore_type_id type,
const void *buf, size_t size)
{
struct pstore_ram_zone *zone;
void *data;
size_t remaining, to_copy, new_size;
int i;
for (i = 0; i < PSRAM_NUM_ZONES; i++) {
zone = &pstore_ram_zones[i];
remaining = zone->max_size - zone->curr_size;
if (remaining < size)
continue;
/* Allocate a new buffer if needed */
if (!zone->data) {
new_size = max_t(size_t, size, PSRAM_ZONE_INIT_SIZE);
data = kmalloc(new_size, GFP_KERNEL);
if (!data)
return -ENOMEM;
zone->max_size = new_size;
zone->curr_size = 0;
zone->data = data;
} else {
data = zone->data;
}
/* Copy data into the buffer */
to_copy = min_t(size_t, remaining, size);
memcpy(data + zone->curr_size, buf, to_copy);
/* Update zone size and return success */
zone->curr_size += to_copy;
return to_copy;
}
return -ENOSPC;
}
static ssize_t pstore_ram_read(struct device *dev, enum pstore_type_id type,
void *buf, size_t size)
{
struct pstore_ram_zone *zone;
size_t remaining, to_copy, offset;
int i;
for (i = 0; i < PSRAM_NUM_ZONES; i++) {
zone = &pstore_ram_zones[i];
remaining = zone->curr_size;
if (remaining < size)
continue;
offset = remaining - size;
to_copy = min_t(size_t, remaining, size);
memcpy(buf, zone->data + offset, to_copy);
return to_copy;
}
return -ENODATA;
}
static struct pstore_info pstore_ram_info = {
.name = "ram",
.ops = &(struct pstore_ops) {
.write = pstore_ram_write,
.read = pstore_ram_read,
},
};
static int __init pstore_ram_init(void)
{
pstore_register(&pstore_ram_info);
return 0;
}
static void __exit pstore_ram_exit(void)
{
pstore_unregister(&pstore_ram_info);
}
module_init(pstore_ram_init);
module_exit(pstore_ram_exit);
MODULE_AUTHOR("Linux pstore maintainers");
MODULE_DESCRIPTION("pstore RAM backend");
MODULE_LICENSE("GPL");
```
4. pstore-ram.c文件中的pstore_ram_write函数将崩溃数据写入到一个内存缓冲区中,pstore_ram_read函数从缓冲区中读取崩溃数据。pstore_ram_init函数在模块初始化时将pstore_ram_info结构体注册到pstore中,pstore_ram_exit函数在模块退出时将pstore_ram_info结构体从pstore中注销。模块的作者、描述和许可证信息也包含在该文件中。
以上是对Linux内核的pstore工具的源码逐行解析。
阅读全文