linux 用户空间电源管理 (三)

2) 库和接口函数

       对于更上一层的应用程序而言,当其注册了自己的模块进入电源管理中之后,会调用一些接口来进行设置,那么我们该设置那些接口给应用层调用呢?(该部分在client中实现)

i)        获取定时器A的超时时间

ii)       设置定时器A的超时时间(注意锁)

iii)      设置是否允许进入电源管理,是否开启定时器B(由state文件锁的占有情况决定,见server思考)

iv)      实现应用程序状态通知到server的方法,由状态的变化决定state文件

v)        注册应用程序(链表),设置状态,如果状态为不允许进入休眠则调用库进行设置对应文件的操作(一般就电源NODE和下载的NODE

以上提到的接口就是提供给应用的一些思路,而对应中间的库函数则是client端和接口

之间的一层细化操作,也应该得到注意。

3) 应用的状态切换

根据应用程序的工作状态(根据文件锁决定)决定定时器B的开关涉及到一个状态机的设计。

如果必要的情况下,会维护一个线程装用于检测状态,这个在电源供电框架中提到。所以可以封装一个接口函数,进行两部分初始化

1、对省电模式处理部分进行初始化,注册电源管理节点

2、如果是电池供电,则启动电源状态维护线程,以便即时更新状态信息,进行一些必要的操作。

Server为每个应用程序维护一个电源管理状态有三种状态,如图:

 

 

 

五.电源供电框架(kernel)与电源管理 app

事实上,我们还遗漏了一个问题,对于使用电源供电和电池供电的电源管理分析。在前面提到过,client会为维护一个线程,用于处理应用与server之间的工作,同时提供库和接口。而电源状态的变化这个过程除了人为的设置之外,还受所使用的电源的影响。

 

       电源状态的监控是用uevent事件实现的。Linux内核中,供电部分的框架(drivers/power目录下,power_supply_corepower_supply_sysfs)提供了uevent机制,驱动可以在电源状态发生变化时发送uevent事件到用户空间,从而通知系统做相应的处理。(对于内核空间与用户空间的uevent通信,用的始终是NETLINK_KOBJECT_UEVENT这个socket通道)。

 

目前在下面这些情况下产生UEVENT事件:

(1)电池电量等级变化:电池电量等级包括满、高电量、普通电量、低电量、电量不足

(2)外电插入、拔出

(3)充电状态改变:包括充电中、禁止充电、不在充电、充饱等状态

所以,我们启动给一个电源状态维护线程,监控UEVENT事件发生,同时对不同的uevent事件调用不同的电源管理接口。比如在外电插入的情况下禁止进入休眠,在电池低电量的时候允许进入休眠等设置。

六.一些细节

1. 以前提到过系统调用的用法,在电源管理中定时器也用到了系统调用,下载timerfd.patch,实现部分如下,

#if defined(__arm__)

#define __NR_timerfd_create           (__NR_SYSCALL_BASE+350)

#define __NR_timerfd_settime         (__NR_SYSCALL_BASE+353)

#define __NR_timerfd_gettime         (__NR_SYSCALL_BASE+354)

#define TFD_TIMER_ABSTIME (1 << 0)

#endif

//#endif /* __NR_timerfd_create */

 

static int timerfd_create(int clockid, int flags)

{

    return syscall(__NR_timerfd_create, clockid, flags);

}

static int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr, struct itimerspec *otmr)

{

    return syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr);

}

 

2. __attribute__ ((constructor))

    Gcc为函数提供了几种类型的属性,其中有构造函数constructor和析构函数destructors

    Static void start(void) __attribute__ ((constructor))

    Static void stop(void) __attribute__ ((destructors))

带有构造函数属性的函数会在main函数之前执行,而析构函数会在_after_main()退出时执行,具体的问题分析可以参见

http://chongsoft.bokee.com/5738209.html

转载博客

 

__attribute__ ((__format__(__printf__,m,n)))

    This指针,继承概念

 

3. client中涉及到threadWakeup_fd,因为它是创建的一个事件fd,用于socket更新时,通知系统重新poll,所以比较简单

    调用threadWakeup_fd=eventfd(0);

           Fcntl(threadWakeup_fd,F_SETFD,FD_CLOEXEC);

    当需要通知系统重新poll时,只要向该fd中写入一些数据,原来的poll会有事件上报,在该处理函数中,通知重新poll

 

4. 关于用户空间定时器的一些操作

    内核空间的定时器的使用在linux内核一些机制中提到过。

    这里说的用户空间的定时器的操作,到最终的操作肯定为内核定时器。

    Timer_fd=timerfd_create(CLOCK_MONOTONIC,0); //

    Timerfd_settime(timer_fd,0,&tmr,NULL) //启动定时器

    定时时间在struct itimerspec tmr结构中,这个定时器不像内核定时器,可以在时间到时调用定时处理函数,所以我们需要将此fd加入select或者poll中,从而在时间超时时做相应的处理。

   

5.       static int close_socket(int fd)

{

    Shutdown(fd,SHUT_RDWR);

    Return close(fd);

}

读取一个文件有多少数据可读

Ioctl(fd,FIONREAD,&ibytestoread);

 

                    

                                                                                                      ---END---

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值