当前位置:首页 > 嵌入式 > 嵌入式软件

Android平台是基于Linxu内核搭建的,Linux内核的优势在于大内存管理、进程管理、基于权限的安全模型、统一的驱动模型、共享库支持、代码开源等。

Android平台在设计过程中,针对移动终端资源有限的特点,对Linux进行了一定程度的裁剪:砍掉了原生的窗口系统、去除了对GNU Libc的支持(引入了更高效、针对优化过的Bionic)、裁剪掉了一些标准Linux工具的部分特性等。

另外Android针对移动终端的特点还对Linux内核在闹钟(Alarm)、Low Memory Killer、Ashmem、内核调试(Kernel Debugger)、进程间通信(Binder)、日志(Logger)、电源管理(Power Management)等方面做了大量的优化。

其中Low Memory Killer相对于Linux标准OOM(Out Of Memory)机制更加灵活,它可以根据需要杀死进程来释放需要的内存。Low Memory Killer的实现主要位于auroramsmmsm drivers/staging/android/lowmemorykiller.c文件中。

Ashmem为进程间提供大块共享内存,同时为内核提供回收和管理这个内存的机制。 Ashmem的实现位于systemcorelibcutilsashmem-dev.c文件中。

下面重点介绍进程间通信和电源管理的内容。

1.进程间通信

在多进程环境下,应用程序和后台服务间通常会运行在不同的进程中,彼此有着独立的地址空间,但是因为需要相互协作,彼此间又必须进行通信和数据共享,而传统的进程间通信(IPC,Internet Process Connection)却有着进程过载和安全漏洞等方面的风险。在Android中,引入了Binder的进程间通信机制,Binder的好处在于在驱动层面就对进程间通信提供了支持、通过SMD共享内存机制提高了进程间通信的性能、采用线程池的方式来处理进程请求、针对系统中的对象引入了引用计数机制和跨进程的对象引用映射机制、在进程间的同步调用。图1显示了Android的进程间通信过程。


图1 Android的进程间通信过程

为了进行进程间通信,Binder采用AIDL(Android Interface Definition Lanaguage)来描述进程间的接口。
在实际的实现中,Binder是作为一个特殊的字符型设备来存在的,其实现遵循Linux设备驱动模型,相关的主要代码位于auroramsmmsmdriversstagingandroid binder.c文件中。

在Binder驱动中,binder_thread_write()函数通过binder_transaction()函数来发送请求或返回结果,而binder_thread_read()函数用于读取结果,Binder主要通过binder_ioctl()函数与用户空间的进程交换数据。

Binder的私有数据结构binder_proc则被用来记录当前进程、进程ID、内存映射信息、Binder的统计信息和线程信息等。

如果收到请求,binder_transaction()函数会通过对象的句柄找到对象所在的进程,如果句柄为空就认为对象是 context_mgr,把请求发给context_mgr所在的进程。所有的Binder对象会全部放到一个RB树中。最后context_mgr把请求放到目标进程的事件队列中,等待目标进程读取。数据的解析工作放在binder_parse()中实现。

下面是Binder驱动中最重要的binder_ioctl()函数的实现:

代码1-1 binder_ioctl()函数的实现

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
struct binder_proc *proc=filp->private_data;
struct binder_thread *thread;
unsigned int size=_IOC_SIZE(cmd);
void __user *ubuf=(void __user *)arg;
/*printk(KERN_INFO "binder_ioctl: %d:%d %x %lxn", proc->pid, current->pid, cmd, arg);*/
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret)
return ret;
mutex_lock(&binder_lock);
thread=binder_get_thread(proc); //获取一个Binder线程
if (thread==NULL) {
ret=-ENOMEM;
goto err;
}
switch (cmd) {
case BINDER_WRITE_READ: {
struct binder_write_read bwr;
if (size!=sizeof(struct binder_write_read)) {
ret=-EINVAL;
goto err;
}
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { //从用户空间缓冲复制数据
ret=-EFAULT;
goto err;
}
if (binder_debug_mask & BINDER_DEBUG_READ_WRITE)
printk(KERN_INFO "binder: %d:%d write %ld at %08lx, read %ld at %08lxn",
proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer);
if (bwr.write_size > 0) {
ret=binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); //传递数据
if (ret < 0) {
bwr.read_consumed=0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) //将数据写回用户空间
ret=-EFAULT;
goto err;
}
}
if (bwr.read_size>0) {
ret=binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); //读取数据
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait); //唤醒挂起的线程
if (ret<0) {
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto err;
}
}
if (binder_debug_mask & BINDER_DEBUG_READ_WRITE)
printk(KERN_INFO "binder: %d:%d wrote %ld of %ld, read return %ld of %ldn",
proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size);
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
ret=-EFAULT;
goto err;
}
break;
}
case BINDER_SET_MAX_THREADS: 设置最大线程数
if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
ret=-EINVAL;
goto err;
}
break;
case BINDER_SET_CONTEXT_MGR: //设为上下文管理器
if (binder_context_mgr_node!=NULL) {
printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already setn");
ret=-EBUSY;
goto err;
}
if (binder_context_mgr_uid!=-1) {
if (binder_context_mgr_uid!=current->cred->euid) {
printk(KERN_ERR "binder:BINDER_SET_"
"CONTEXT_MGR bad uid %d!= %dn",
current->cred->euid,
binder_context_mgr_uid);
ret=-EPERM;
goto err;
}
} else
binder_context_mgr_uid=current->cred->euid;
binder_context_mgr_node=binder_new_node(proc, NULL, NULL);//新的RB树节点
if (binder_context_mgr_node==NULL) {
ret=-ENOMEM;
goto err;
}
binder_context_mgr_node->local_weak_refs++;
binder_context_mgr_node->local_strong_refs++;
binder_context_mgr_node->has_strong_ref = 1;
binder_context_mgr_node->has_weak_ref = 1;
break;
case BINDER_THREAD_EXIT: //销毁消除
if (binder_debug_mask & BINDER_DEBUG_THREADS)
printk(KERN_INFO "binder: %d:%d exitn",
proc->pid, thread->pid);
binder_free_thread(proc, thread); //释放线程
thread=NULL;
break;
case BINDER_VERSION: //获取Binder版本信息
if (size!=sizeof(struct binder_version)) {
ret=-EINVAL;
goto err;
}
if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
ret=-EINVAL;
goto err;
}
break;
default:
ret=-EINVAL;
goto err;
}
ret=0;
err:
if (thread)
thread->looper&=~BINDER_LOOPER_STATE_NEED_RETURN;
mutex_unlock(&binder_lock);
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret && ret !=-ERESTARTSYS)
printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %dn", proc->pid, current->pid, cmd, arg, ret);
return ret;
}

2.电源管理

在目前的移动终端中,系统承载的功能越来越多,同时为了获得更好的用户体验,GUI的设计越来越华丽,但这都不可避免地增加了系统的功耗,导致目前的智能移动终端普遍待机时间较短。在目前电池技术尚无法有大的突破情况下,电源管理显得尤为重要,需要在满足用户需求的前提下,尽可能地减少功耗。电源管理策略是一个系统工程,应用程序、内核框架、设备驱动、硬件设备都涉及其中。

对半导体器件而言,功耗分为静态功耗、动态功耗。静态功耗主要是指待机状态下的泄漏电流,动态功耗才是电源管理要解决的主要问题。

Android的电源管理机制是建立在标准的Linux电源管理机制ACPI (Advanced Configuration and Power Interface)之上的,同时针对移动终端的特点采取了更积极的电源管理策略,支持休眠模式、动态电压和调频调节、电源管理质量服务(PM QoS)、唤醒锁等。

休眠模式、动态电压和调频调节等策略这里就不再多做介绍了。下面简要介绍PM QoS和唤醒锁的实现。

1)PM QoS

在初始化阶段,Android定义的PM QoS参数有3个:cpu_dma_latency(CPU DMA延迟)、network_latency(网络延迟)、 network_throughput(网络吞吐量)。供驱动、子系统、用户空间应用等注册PM QoS请求。默认的参数级别有延迟、超时(Aurora中暂时不用)、吞吐量等。

在Aurora(auroramsmmsmkernelpm_qos_params.c)中, PM QoS有4个参数:PM_QOS_CPU_DMA_LATENCY、PM_QOS_NETWORK_LATENCY、PM_QOS_NETWORK_ THROUGHPUT和PM_QOS_SYSTEM_BUS_FREQ等,分别针对CPU DMA延迟、网络延迟、网络吞吐量、系统总线频率等性能指标。参数集的实现在pm_qos_power_init()函数中进行,使用pm_qos_init()函数在内核里可以增加新的参数。在系统中,PM QoS主要用来管理CPU空闲管理、WiFi应用等。

在内核空间,通过pm_qos_add_requirement()函数可以注册PM QoS请求;通过pm_qos_update_requirement()函数可以更新已注册的PM QoS请求;通过pm_qos_remove_requirement()函数可以删除已注册的PM QoS请求。图2显示了注册PM QoS请求的过程。


图2 注册PM QoS请求的过程

在用户空间,仅进程可以注册PM QoS请求,为了注册PM QoS请求,进程必须打开/dev/[cpu_dma_latency, network_latency, network_throughput]设备,默认的PM QoS请求名为“process_<PID>”。其中PID值在系统调用中获得。

2)唤醒锁

通过支持多种类型的唤醒锁(wake locks),Android支持组件在电源管理方面的请求。需要注意的是,在使用唤醒锁时需要相当小心。图3显示了创建唤醒锁的过程。


图3 创建唤醒锁的过程

在实际的开发过程中,为了测试各应用电量消耗的情况,电量分析软件powerTop不可或缺,它可以分析出每个具体的应用对电量的消耗情况。

Android电源管理的实现主要位于auroramsmmsmkernelpower目录下,主要的文件包括earlysuspend.c、consoleearlysuspend.c、fbearlysuspend.c、wakelock.c、userwakelock.c等。

在Java层,Android封装了一个PowerManager类来进行电源的管理。

3.驱动

驱动的实现与硬件平台密切相关,由于在Linux Kernel 2.6中引入了Linux设备驱动模型,Linux的驱动开发变得十分简单。在auroramsmmsmdrivers目录中,Qualcomm提供了非常多的硬件驱动,如BT、i2C、USB、FM、音频、视频等。下面简要介绍部分驱动的情况。

●显示驱动(Display Driver):常用基于Linux的帧缓冲( Buffer)驱动。
●照相机驱动(Camera):常用基于Linux的V4L2驱动。
●音频驱动:常用基于ALSA(高级Linux音频架构,Advanced Linux Sound Architecture)驱动。
●WIFI驱动:基于IEEE 802.11标准的驱动程序。Aurora支持的WIFI标准为802.11 bgn。对WAPI的支持则需要硬件平台厂商的支持。
●Binder IPC驱动:Android的一个特殊的驱动程序,具有单独的设备节点,实现进程间通信的功能。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭