O Android está na moda. E não estamos falando de nenhum novo robozinho da Sony ou da Honda. Estamos falando do sistema operacional do Google (ou da Google, como preferirem), desenvolvido especialmente para dispositivos móveis.
Como é um sistema aberto (apesar de não ter necessariamente todo código-fonte disponível), todos querem embarcar o Android em seus dispositivos e se aproveitar de toda a infraestrutura de aplicações e serviços disponíveis no mercado.
Uma característica que ajuda na escolha deste sistema operacional é que ele usa o kernel do Linux. Mas o que isso significa? O Android é uma distribuição Linux? Como ele funciona internamente? É isso que veremos nesta série de artigos sobre a arquitetura interna do Android.
HISTÓRICO
Em 2005, uma empresa chamada Android Inc., que desenvolvia um sistema operacional móvel de mesmo nome, foi comprada pelo Google. Com a popularização do uso de smartphones trazida pelo iPhone da Apple, o Google sentiu que poderia expandir seu negócio de venda de anúncios também em dispositivos móveis.
Em 2007, para cuidar do projeto Android, o Google criou a Open Handset Alliance, um consórcio de empresas de tecnologia envolvidas no mercado de dispositivos móveis (HTC, Sony, Intel, Motorola, Sansumg, etc). No fim deste mesmo ano, é liberada a primeira versão do Android, juntamente com o SDK para o desenvolvimento de aplicações.
ARQUITETURA BÁSICA
O Android é um sistema operacional baseado no kernel do Linux. Apesar de ter sido desenvolvido inicialmente para smartphones, hoje é usado em diversas outras aplicações como tablets e até relógios.
Apesar de ser baseado no kernel do Linux, existe pouca coisa em comum com distribuições Linux convencionais (embarcadas ou não). À grosso modo, o Android é uma máquina virtual Java rodando sobre o kernel do Linux, dando suporte para o desenvolvimento de aplicações Java através de um conjunto de bibliotecas e serviços. Sua arquitetura tem basicamente 4 camadas:
Linux kernel: o Android usa o kernel do Linux com alguns patchs, que adicionam algumas funcionalidades através de módulos do kernel. Veremos mais adiante quais são estas funcionalidades.
Bibliotecas e serviços: aqui estão as bibliotecas básicas do sistema como a Bionic, aOpenGL/ES para trabalhar com gráficos, e a SQLite para trabalhar com banco de dados. Aqui também estão os serviços providos para as camadas superiores, incluindo a máquina virtual Java (Dalvik). A maior parte destas bibliotecas e serviços estão desenvolvidos em C e C++.
Framework: esta camada é desenvolvida quase toda em Java, e faz a interface com as aplicações Android. Ela provê um conjunto de bibliotecas para acessar os diversos recursos do dispositivo como interface gráfica, telefonia, localizador (GPS), banco de dados persistente, armazenamento no cartão SD, etc.
Aplicações: é aqui que ficam as aplicações (desenvolvidas em Java) para o Android. E é um dos grandes segredos do sucesso da plataforma, já que possui mais de 250.000 aplicações no Android Market, e continua crescendo cada dia que passa.
Para uma descrição mais completa da arquitetura do Android, dê uma olhada no guia de desenvolvimento Android disponibilizado pelo Google.
Parece simples, não? Nem tanto assim. Se olharmos para a arquitetura interna do Android, veremos o nível de complexidade deste sistema operacional:
Realmente muita coisa acontece quando rodamos uma simples aplicação. Vamos então tentar entender melhor tudo isso?
O KERNEL
Vimos que o Android usa uma versão modificada do kernel do Linux. Dentre as principais modificações, temos:
binder: sabemos que em todo sistema operacional com suporte à memória virtual, os processos rodam em diferentes regiões de memória. Isso significa que nenhum processo tem acesso à região de memória de outro processo. E por isso precisamos de um mecanismo de comunicação entre processos. Mas quem esta acostumado com o padrão System V IPCusado em sistemas Linux tradicionais para comunicação entre processos (message queues, semáforos e shared memory) vai precisar “voltar à escola”. O Android usa o Binder para a comunicação entre processos. Ele implementa um modulo no kernel em “drivers/misc/binder.c” para esta tarefa. Toda comunicação entre processos no Android passa pelo binder. Para o desenvolvedor de aplicações Android, o processo é transparente, já que é abstraído pelas bibliotecas do sistema.
ashmem: um novo mecanismo de compartilhamento de memória, onde dois processos podem se comunicar através desta região compartilhada de memória. É mais leve e simples de usar, e tem melhor suporte a dispositivos com pouca memória, já que tem a capacidade de descartar regiões de memória compartilhada de maneira segura em caso de pouca memória disponível. Sua implementação encontra-se em “mm/ashmem.c”.
logger: o Android possui um sistema global de logs, implementado através de um módulo do kernel. Ele cria 4 arquivos de dispositivo em “/dev/log”, cada um representando um buffer diferente:
Para as aplicações acessarem o sistema de log, basta abrir e ler ou escrever num destes arquivos de dispositivo. A implementação deste módulo no kernel encontra-se em “drivers/misc/logger.c”.
wakelocks: se um dispositivo Android ficar um tempo sem ser usado, entrará em modo de baixo consumo para garantir economia de bateria. O módulo de wakelock permite que as aplicações desabilitem o mecanismo de baixo consumo. Por exemplo, se você precisar executar um processo em background que não pode ser interrompido para entrar em modo de baixo consumo, este módulo possibilita a desativação temporária deste recurso até que seu processo finalize a execução. Sua implementação encontra-se em “kernel/power/wakelock.c”.
oom handling: implementado em “drivers/misc/lowmemorykiller.c”, controla o uso de memória do sistema e mata processos se verificar que a memória disponível esta abaixo de um valor mínimo aceitável.
timed GPIO: possibilita acionar saídas de I/O de forma temporizada. Está implementado em “drives/misc/timed_gpio.c”.
O SISTEMA DE ARQUIVOS
Esta é a árvore de diretórios de um sistema de arquivos para o Android:
Bem diferente de um sistema Linux convencional, não é verdade? Os dois principais diretórios são o “data”, que armazena os dados das aplicações, e o “system”, com as bibliotecas (system/lib), serviços (system/bin e system/xbin) e aplicações Java (system/app).
E por falar em bibliotecas do sistema, nada de glibc ou uClibc. O Android implementou uma biblioteca chamada Bionic para usar como biblioteca do sistema. Porque? Me parece que o Google tem algum problema com licenças GPL, e eles tiraram do user space todo e qualquer software com licença GPL. A Bionic usa a licensa BSD, e suporta as arquiteturas x86 e ARM.
Agora, se alguém do Google esta lendo este artigo, por favor me respondam, porque vocês não usaram o Busybox??? Bom, tenho quase certeza de que também tem a ver com a licensaGPL do Busybox. De qualquer forma, o Android usa o Toolbox, uma implementação no mesmo esquema do Busybox, que também traz um conjunto (mais limitado) de comandos e ferramentas úteis para gerenciar um sistema Android. Repare nos executáveis que fazem um link para o toolbox na listagem abaixo:
O Android ainda usa por padrão o SQLite como gerenciador de banco de dados para as aplicações e o OpenGl/ES como biblioteca gráfica, dentre outras bibliotecas disponíveis.
OS SERVIÇOS BÁSICOS
Se listarmos os processos rodando em um dispositivo com Android, a saída será mais ou menos essa:
Três pontos interessantes aqui:
1. O processo “init” é o pai de todos os processos que rodam em user space, como o “/sbin/ueventd” e o “/system/bin/mediaserver”.
2. O processo “kthreadd” é o pai de todas as threads do kernel como o “ksoftirqd” e o “khelper”.
3. O processo “zygote” é o pai de todas as aplicações rodando no Android, como o “android.process.media” e o “com.android.email”. Tudo que roda em cima de uma máquina virtual, tem como antecessor comum o processo “zygote”.
A MÁQUINA VIRTUAL DALVIK
E por falar em máquina virtual, o Android usa uma implementação da JVM chamada Dalvik. A Dalvik não consome bytecode Java, mas sim dexcode. Para isso, o Google desenvolveu uma ferramenta, chamada “dx”, que converte Java bytecodes (*.class) em dexcodes (*.dex).
Além disso, desde a versão 2.2 (Froyo), o Android possui uma implementação de JIT (Just-in-time), que compila dexcodes para a arquitetura-alvo em tempo de execução, tornando a execução dos processos consideravelmente mais rápidas, já que não precisa ficar interpretando dexcodes.
Junto com a máquina virtual Dalvik, o Android usa o framework Apache Harmony, desenvolvido pela Apache Software Fundation como biblioteca padrão de classes Java.
AS APLICAÇÕES
As aplicações são escritas em Java. Existem bibliotecas Java disponíveis para acessar todos os recursos do dispositivo.
Ao executar uma aplicação, o processo “zygote” cria uma instância da máquina virtual Dalvik para executá-la. E cada aplicação roda com um UID (user ID) diferente. Dê uma olhada na coluna “USER” da listagem de processos acima. Isso protege as aplicações umas das outras, e do sistema como um todo, limitando acesso aos arquivos do sistema e aos recursos do dispositivo através de permissões de usuário.
Fonte: Sergio Prado
Nenhum comentário:
Postar um comentário