Android wakelock可以被核心空間和使用者空間 申請和釋放。申請的是非逾時鎖,需要相應的調用wake_unlock來釋放,而逾時鎖則不需要手工釋放(當然你也可以手工釋放),逾時後kernel系統會自動釋放鎖
在核心空間可以直接調用wake_lock, wake_lock_timeout 申請鎖
Android kernel為使用者空間提供了申請和釋放wakelock的介面,實現在kernel/power/userwakelock.c中,下面我們簡單的分析下這個檔案,userwakelock中僅僅涉及到使用者空間操作的鎖,所有鎖通過紅/黑樹狀結構進行管理,在這裡就不對紅/黑樹狀結構的操作進行分析了。
使用者空間提供者:
/sys/power/wake_lock
/sys/power/wake_unlock
129 ssize_t wake_lock_show(
130 struct kobject *kobj, struct kobj_attribute *attr, char *buf)
131 {
132 char *s = buf;
133 char *end = buf + PAGE_SIZE;
134 struct rb_node *n;
135 struct user_wake_lock *l;
136
137 mutex_lock(&tree_lock);
138
139 for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
140 l = rb_entry(n, struct user_wake_lock, node);
141 if (wake_lock_active(&l->wake_lock))
142 s += scnprintf(s, end - s, "%s ", l->name);
143 }
144 s += scnprintf(s, end - s, "\n");
145
146 mutex_unlock(&tree_lock);
147 return (s - buf);
148 }
顯示應用空間申請的所有啟用鎖(包括逾時鎖和非逾時鎖)
150 ssize_t wake_lock_store(
151 struct kobject *kobj, struct kobj_attribute *attr,
152 const char *buf, size_t n)
153 {
154 long timeout;
155 struct user_wake_lock *l;
156
157 mutex_lock(&tree_lock);
158 l = lookup_wake_lock_name(buf, 1, &timeout);
159 if (IS_ERR(l)) {
160 n = PTR_ERR(l);
161 goto bad_name;
162 }
163
164 if (debug_mask & DEBUG_ACCESS)
165 pr_info("wake_lock_store: %s, timeout %ld\n", l->name, timeout);
166
167 if (timeout)
168 wake_lock_timeout(&l->wake_lock, timeout);
169 else
170 wake_lock(&l->wake_lock);
171 bad_name:
172 mutex_unlock(&tree_lock);
173 return n;
174 }
申請一把鎖,名字以及逾時時間都包含在參數@buf中,lookup_wake_lock_name會解析出名字和逾時時間,如果逾時時間不存在說明申請的是非逾時鎖,否則是逾時鎖
167~170 調用wake_lock申請非逾時鎖;調用wake_lock_timeout申請非逾時鎖。
177 ssize_t wake_unlock_show(
178 struct kobject *kobj, struct kobj_attribute *attr, char *buf)
179 {
180 char *s = buf;
181 char *end = buf + PAGE_SIZE;
182 struct rb_node *n;
183 struct user_wake_lock *l;
184
185 mutex_lock(&tree_lock);
186
187 for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
188 l = rb_entry(n, struct user_wake_lock, node);
189 if (!wake_lock_active(&l->wake_lock))
190 s += scnprintf(s, end - s, "%s ", l->name);
191 }
192 s += scnprintf(s, end - s, "\n");
193
194 mutex_unlock(&tree_lock);
195 return (s - buf);
196 }
該函數顯示當前應用空間可申請的所有未啟用鎖(包括逾時鎖和非逾時鎖),列印出鎖的名字,返回給使用者空間。
187 遍曆整個RB樹,
198 ssize_t wake_unlock_store(
199 struct kobject *kobj, struct kobj_attribute *attr,
200 const char *buf, size_t n)
201 {
202 struct user_wake_lock *l;
203
204 mutex_lock(&tree_lock);
205 l = lookup_wake_lock_name(buf, 0, NULL);
206 if (IS_ERR(l)) {
207 n = PTR_ERR(l);
208 goto not_found;
209 }
210
211 if (debug_mask & DEBUG_ACCESS)
212 pr_info("wake_unlock_store: %s\n", l->name);
213
214 wake_unlock(&l->wake_lock);
215 not_found:
216 mutex_unlock(&tree_lock);
217 return n;
218 }
205 使用者空間介面按照RB(紅/黑樹狀結構)來組織wakelock鎖,這樣可以加快尋找速度,第三個參數為NULL,因為wake_unlock_store僅僅針對非逾時鎖,逾時鎖不需要unlock
214 調用wake_unlock釋放非逾時鎖
如果用命令
#echo "kaka 12" > /sys/power/wake_lock
申請一個逾時鎖,那麼在逾時後,執行
#cat /sys/power/wake_lock
kaka
顯示這個逾時鎖還存在,覺得這個介面有問題。