栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux电源管理 — RPM

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux电源管理 — RPM

一. 简介
  • RPM全称Runtime Power Management,即运行时电源管理。主要是用于设备运行时的电源管理,由kernel统一管理。当设备处于空闲状态时,挂起设备;而当设备需要被使用时,使设备恢复进入正常工作状态。
  • 在文件 /include/linux/pm.h 中,dev_pm_ops结构体下有与runtime pm相关的三个回调函数;以及使用rpm_status枚举表示设备的状态。
struct dev_pm_ops {
	......
	int (*runtime_suspend)(struct device *dev);	//挂起
	int (*runtime_resume)(struct device *dev);	//恢复
	int (*runtime_idle)(struct device *dev);	//空闲
};
enum rpm_status {
	RPM_ACTIVE = 0,		//运行状态
	RPM_RESUMING,		//正在恢复成运行状态
	RPM_SUSPENDED,		//挂起状态
	RPM_SUSPENDING,		//正在挂起状态
};
  • runtime pm的相关API接口函数在文件 /include/linux/pm_runtime.h下。
二. 运行机制
  • 每个设备都有一个usage_count变量,记录设备的使用情况。
  • 当该变量大于0时,表示设备正在被使用,处于active状态;当该变量等于0时,表示设备没有被使用,处于suspend状态。
  • 当要使用设备时,使用pm_runtime_get_sync/pm_runtime_get将usage_count变量+1,每次+1都会去根据当前设备状态判断是否需要resume;当需要resume时,就会调用runtime_resume回调函数。
  • 当使用完设备时,使用pm_runtime_put_sync/pm_runtime_put将usage_count变量-1,为0时suspend设备;suspend设备时先调用runtime_idle回调函数,然后在合适时机调用runtime_suspend回调函数。
三. 相关操作
  • 查看当前设备状态
cat /sys/devices/$dev/power/runtime_status
  • 增加/减少设备计数
echo on > /sys/devices/$dev/power/control
echo auto > /sys/devices/$dev/power/control
  • 查看设备在active/suspend状态的时间
cat /sys/devices/$dev/power/runtime_active_time
cat /sys/devices/$dev/power/runtime_suspend_time
四. 伪代码示例
struct TestDev_t
{
	dev_t dev_num;					//设备号
	struct cdev TestCdev;			//使用Linux内核下cdev结构体,描述一个字符设备
	struct class *TestClass; 		//创建LedClass类指针
	struct device *TestDevice;		//设备节点指针
	struct platform_device *p_dev;  //platform设备指针
};


static int test_open(struct inode *inode, struct file *filp)
{
	struct TestDev_t *p_TestDev = container_of(inode->i_cdev, struct TestDev_t, TestCdev);
	filp->private_data = p_TestDev;
	pm_runtime_get(&p_TestDev->p_dev->dev);
	return 0;
}

static int test_release(struct inode *inode, struct file *filp)
{
	struct TestDev_t *p_TestDev = (struct TestDev_t *)filp->private_data;
	pm_runtime_put(&p_TestDev->p_dev->dev);
	retuen 0;
}

static struct file_operations TestDevFops = {
	.owner 		= THIS_MODULE,	
	.open 		= test_open,
	.read 		= test_read,
	.write 		= test_write,
	.unlocked_ioctl = test_ioctl,
	.release 	= test_release,
};


static int test_probe(struct platform_device *pdev)
{
	struct TestDev_t* p_TestDev = (struct TestDev_t*)kmalloc(sizeof(struct TestDev_t), GFP_KERNEL);
	
	alloc_chrdev_region(TestDev.dev_num, 0, 1, "TestDev");
	
	cdev_init(&TestDev.TestCdev, &TestDevFops);
	cdev_add(&TestDev.TestCdev, TestDev.dev_num, 1);
	
	TestDev.TestClass = class_create(THIS_MODULE, "TestDev");
	TestDev.TestDevice = device_create(TestDev.TestClass, NULL, TestDev.dev_num, NULL, "TestDev");
	
	pm_runtime_enable(&pdev->dev);
	
	p_TestDev->p_dev = pdev;
	platform_set_drvdata(pdev, p_TestDev);
	return 0;
}


static int test_remove(struct platform_device *pdev)
{
	struct TestDev_t* p_TestDev = platform_get_drvdata(pdev);
	
	cdev_del(&TestDev.TestCdev);
	
	unregister_chrdev_region(TestDev.dev_num, 1);
	
	device_destroy(TestDev.TestClass, TestDev.dev_num);
	class_destroy(TestDev.TestClass);
	
	pm_runtime_disable(&pdev->dev);
	Kfree(p_TestDev);
	return 0;
}


static int test_runtime_suspend(struct device *dev)
{
	printk("dev runtime suspendrn");
	
	return 0;
}


static int test_runtime_resume(struct device *dev)
{
	printk("dev runtime resumern");
	
	return 0;
}


static int test_runtime_idle(struct device *dev)
{
	printk("dev runtime idlern");
	return 0;
}


static const dev_pm_ops test_rpm_ops = {
	SET_RUNTIME_PM_OPS(test_runtime_suspend, test_runtime_resume, test_runtime_idle);
};


static const struct of_device_id test_of_match[] = {
	{ .compatible = "xxxxxx" },			
	{  }
};


static struct platform_driver test_driver = {
	.driver		= {
		.name	= "xxxxxxxxx",			 
		.of_match_table	= test_of_match, 
		.pm = &test_rpm_ops,			 
	},
	.probe		= test_probe,
	.remove		= test_remove,
};

*模块加载函数*/
static int __init test_init(void)
{
	return platform_driver_register(&test_driver);
}


static void __exit test_exit(void)
{
	platform_driver_unregister(&test_driver);
}

module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");


五. 参考资料
  • 《Linux设备驱动开发详解:基于最新的Linux4.0内核》
  • http://www.wowotech.net

以上是我在学习过程中的总结,不当之处请在评论区指出。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/603754.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号