Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Программирование и алгоритмические языки в Linux

Крошечное "облако" в системе Android

Оригинал: "A tiny cloud in Android"
Автор: Bill Zimmerly
Дата публикации: 17 ноября 2009 г.
Перевод: Н.Ромоданов
Дата перевода: 29 ноября 2009 г.

Краткое содержание: Для облачных вычислений необходимы как минимум два компонента: клиентское программное обеспечение, которое работает на портативном устройстве, и серверное программное обеспечение, которое обычно работает на сетевом сервере. В настоящей статье предлагается создать сервис на базе системы Android, эмулирующий сетевой сервер, что расширяет возможности локального компьютера уникальным и неожиданным образом. Разместите крошечное "облако" в вашем телефоне с системой Android и с пользой поэкспериментируйте с локальным веб сервером.

Android – специальный дистрибутив операционной системы Linux, созданный для управления самой разнообразной функциональностью самых сложных смартфонов. Что касается программиста, то все, что есть в Linux – устройство, таблица или любимая песня – рассматривается как файл. Т.е. имеются общие способы открытия, выбора, обработки и сохранения информационного содержимого этих разнообразных и абстрактных сущностей. И эта общность формирует основной принцип философии UNIX: все – есть файл.

Файлы группируются в удобные иерархии, называемые файловыми системами. Сотовый телефон на базе Android обычно имеет две файловые системы: долговременную память сотового телефона и подключаемую к нему флеш-карточку SD. Оба вида памяти являются ветвями корневой директории (/). Инструмент, который позволяет просматривать эти файловые системы, может оказаться полезным. В настоящем проекте разрабатывается небольшая программа, написанная на языке C (нативном для системы Android), которая работает как веб сервер и позволит вам просматривать файловые системы сотового телефона Android либо с вашей инструментальной машины, либо с помощью браузера, встроенного непосредственно в сотовый телефон. Будут выдаваться страницы с гиперссылками, так что Вы можете перемещаться вверх или вниз по иерархическому дереву файловой системы. Если Вы выберете файл конкретного типа, увидите его содержимое.

Настройка среды разработки

Во-первых, удостоверьтесь в том, что у вас сотовый телефон с системой Android, который позволяет получать доступ в режиме root. Это нужно для того, чтобы Вы могли запустить программу Terminal, выполнить команду su и получить все привилегии пользователя root. Если вы не знаете, как получить такую возможность на вашем телефоне, поищите инструкции в сети интернет. Обратите внимание на то, что этот процесс иногда называется "разлочкой" (jail-breaking) вашего телефона.

Прим.пер.: Процесс разлочки может лишить вас гарантии на телефон. Кроме того, если разлочка выполняется неумело или неаккуратно, то это может привести к потере работоспособности вашего телефона.

В сообществе разработчиков Android изначально используются два варианта SDK. Наиболее известен высокоуровневый Android SDK, который позволяет вам писать код приложений на языке Java и, в общем случае, использовать оболочку Eclipse для написания кода, его тестирования и отладки. Другой, менее известный SDK, - исходный код ядра Android, который запоминается в виде того, что называется git репозитарием.

Прим.пер.: В настоящее время имеется пакет Android 1.6 NDK, который позволяет программировать на языке C.

Поскольку настоящая статья фокусируется на создании низкоуровневого веб сервера, который обычно размещается в директории system/bin вашего сотового телефона, важно загрузить и установить весь код ядра системы Android и использовать для его сборки инструментарий GNU. На страничке проекта Android Kernel Source приведены простые инструкции по загрузке всей платформы с помощью скрипта, называемого repo.

Облачная программа cloud будет создаваться на вашей инструментальной машине с помощью кросс компиляции под платформу ARM, так что удостоверьтесь, что установлены все необходимые инструментальные средства. Чтобы установить эти средства, используйте команду apt-get так, как это показано на листинге 1.

Листинг 1. Установка инструментальных средств кросс-компиляции:

$ sudo apt-get install git-core gnupg \
    sun-java5-jdk flex bison gperf libsdl-dev \
    libesd0-dev libwxgtk2.6-dev build-essential \
    zip curl libncurses5-dev zlib1g-dev

Структура дерева разработки

Для установки исходного кода ядра Android используйте директорий с именем mydroid. Вся работа будет происходить в рамках директории с этим именем, так что переходите в домашнюю директорию и набирайте команду mkdir mydroid. Затем используйте команду cd mydroid, а затем - команду repo sync.

После того, как с помощью команды repo sync будет загружен весь исходный код системы Android, будут созданы несколько поддиректорий, среди них обратите внимание на следующие:

  • В директории mydroid/external вам следует создать директорию cloud. Здесь будет находиться исходный код нашего проекта (cloud.c).
  • После того, как долго выполняющаяся команда make создаст систему Android, ее бинарный файл вместе с нашим облачным проектом cloud будет помещен в директорий out/target/product/generic/system/bin.

Облачный проект cloud в системе Android

Когда программа cloud запускается, она сразу проверяет, были ли ей переданы какие-либо параметры командной строки. Предполагается, что можно задать два параметра – номер порта, который будет слушать программа, и домашний директорий, откуда программа начнет работу. Если ни один из параметров не указан, то программа по умолчанию будет использовать порт 80, а в качестве домашнего директория будет использоваться директорий, откуда была запущена программа.

После запуска программа инициализирует сокет TCP/IP, который должен "слушать" обращения к программе через вышеупомянутый порт, а затем она переходит в режим процесса-демона, ожидая обращения от браузера и обрабатывая их. Когда браузер вызывает начальную "страницу" этого крошечного облачного сервера, программа в ответ возвращает список элементов, имеющихся в вышеупомянутом "домашнем" директории. Перечисляются имена файлов либо без гиперссылок, либо с гиперссылками в зависимости от того, являются ли они файлами известных типов или поддиректориями. То, что тип файла известен (в мире WWW) означает, что файл имеет соответствующий тип MIME. Например, внутри сотового телефона, работающего под системой Android, аудиофайлы рингтонов запоминаются как файлы .ogg. Если браузер правильно сконфигурирован, то тип MIME audio/ogg указывает браузеру на то, что этот файл воспроизводится через динамики как звуковой.

Еще одна гиперссылка, которая находится вверху списка файлов, является ссылкой на "родительский" директорий (ссылка Parent Directory). Выбирая эту ссылку, Вы будете перемещаться вверх по иерархии файловой системы до тех пор, пока это будет возможно, т.е. до директория root. Попутно будут в виде гиперссылок отображаться имена других поддиректорий; если их выбрать, то Вы перейдете по иерархии вниз, попадете внутрь соответствующей поддиректории и сможете изучить ее содержимое.

Итак, приложение cloud будет полезно для изучения файловой системы сотового телефона, а его исходный код будет хорошей заготовкой, которую Вы можете изменить с тем, чтобы достичь необходимой функциональности. В конце настоящей статьи предлагаются направления модификации этого кода. Вы также можете откомпилировать код и выполните его на своей инструментальной машине – тогда Вы будете просматривать файловую систему этой машины.

Исходный код на языке C

В исходном коде программы следует указать, как минимум, название программы и ее автора. Это указывается в листинге 2 вместе с инклюдами и необходимыми константами.

Листинг 2. Атрибутика программы, инклюды и необходимые константы:

    // Android Cloud Application by Bill Zimmerly.
    // Based on "NWEB" by Nigel Griffiths.

    #include <dirent.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>

    #define TRUE      -1
    #define FALSE     0
    #define SBUF      1048576
    #define LBUF      4096
    #define LAPN      64
    #define ERROR     1
    #define LOG       2
    #define LOGGING   FALSE

В листинге 3 задано общее рабочее пространство памяти, доступное всем функциям, определяемыми в этой программе. Когда браузер вызывает программу cloud, то выделяется память для большей части указателей на буфера. После того, как содержимое будет оправлено браузеру, выделенная память будет возвращена сотовому телефону. В компьютерах с ограниченными ресурсами такая практика очень важна.

Листинг 3: Общее рабочее пространство памяти:

    char* about="</pre>Cloud is a simple application that enables "
                "web-based browsing of the Android file system "
                "and is intended for use by people who like to "
                "explore the lowest levels of their device. It "
                "runs on a rooted Android phone and is only for "
                "browsing the file system. See the IBM "
                "developerWorks article for a full description "
                "of this application.<pre>";

    char* mainbuf;
    char* theDir;
    char* thePort[8];
    char* theList;
    char* fstr;

    char logDir[LBUF];

    int ret;

В этой программе используется простая таблица, отображающая расширения файлов в типы MIME, которые браузеру нужно знать для того, чтобы правильно обрабатывать содержимое файлов. Структура, приведенная в листинге 4, используется функцией mimeokay для единственной цели: установить глобальный указатель строки fstr на тип MIME, соответствующий расширению файла fext. Зная эту информацию, программа cloud может изображать имя файла либо с гиперссылкой, либо как обычный текст без ссылки. Второе ее назначение – передать тип MIME, когда содержимое файла посылается в браузер.

Листинг 4. Определение типов MIME:

    struct
    {
      char *ext;
      char *mimetype;
    }

    mimes [] = 
    {
      {".htm",  "text/html"  },  
      {".html", "text/html"  },
      {".xml",  "text/xml"   },
      {".gif",  "image/gif"  },  
      {".jpg",  "image/jpeg" }, 
      {".jpeg", "image/jpeg" },
      {".png",  "image/png"  },  
      {".log",  "text/plain" },
      {".conf", "text/plain" },
      {".rc",   "text/plain" },
      {".sh",   "text/plain" },
      {".prop", "text/plain" },
      {".txt",  "text/plain" },
      {".TXT",  "text/plain" },
      {".cpp",  "text/plain" },  
      {".c",    "text/plain" },  
      {".h",    "text/plain" },
      {".ogg",  "audio/ogg" },
      {0,0} 
    };

    void mimeokay(char* fext)
    {
      int buflen;
      int len;
      long i;

      buflen=strlen(fext);
      fstr = (char*) 0;
  
      for(i=0; mimes[i].ext != 0; i++)
      {
        len = strlen(mimes[i].ext);
    
        if(!strncmp(&fext[buflen-len], mimes[i].ext, len))
        {
          fstr=mimes[i].mimetype;
          break;
        }
      }
    }

В листинге 5 приводится дополнительный код, с помощью которого в процессе отладки и тестирования будут регистрироваться все действия активности cloud в системе Android. Поскольку программа cloud работает на сравнительно медленном "железе", то правильно оставлять эту функциональность отключенной до тех пор, пока вам действительно не потребуется знать, что случилось в коде после того, как Вы его изменили. Если Вы хотите регистрировать работу программы, то константа LOGGING, приведенная в листинге 1, должна быть равна TRUE, но когда программа будет работать на сотовом телефоне, установите ее в FALSE, поскольку важна скорость работы программы.

Листинг 5. Регистрация действий программы:

    void aclog(int type, char *s1, char *s2, int num)
    {
      int fd ;
      char aclogbuffer[LBUF];
      char logFile[LBUF];
    
      if(!LOGGING)
        return;
    
      switch(type)
      {
        case ERROR: 
          sprintf(aclogbuffer, "ERROR: %s:%s Error Number=%d, PID=%d", 
                  s1, s2,
                  errno, getpid());
          break;
        case LOG:
          sprintf(aclogbuffer, "INFO: %s:%s:%d", s1, s2, num);
          break;
      }	
    
      strcpy(logFile, logDir);
      strcat(logFile, "/cloud.log");
      
      if((fd = open(logFile, O_CREAT | O_WRONLY | O_APPEND,
                    0644)) >= 0)
      {
        ret=write(fd, aclogbuffer, strlen(aclogbuffer)); 
        ret=write(fd, "\n", 1);      
        close(fd);
      }
    
      if(type == ERROR)
        exit(3);
    }

В листинге 6 приведены несколько функций, предназначенных для создания выходного потока программы cloud в формате HTML. Заметьте, что каждая страница хорошо спроектированного веб сайта должна иметь приличный внешний вид и этот внешний вид задается в функции buildbuf.

Листинг 6. Генерация выходного потока в формате HTML:

    void apname(void)
    {
      strcat(mainbuf, "Android Cloud Application");
    }
    
    void buildbuf(char* data)
    {
      mainbuf[0]=0;
      strcat(mainbuf, "<html>\n<head>\n<title>");
      apname();
      strcat(mainbuf, "</title>\n</head>\n");  
      strcat(mainbuf, "<body>\n<h3>");
      apname();
      strcat(mainbuf, "</h3>\n");
      strcat(mainbuf, "<a href=\"/About_\">About</a><br>\n");
      strcat(mainbuf, "<a href=\"/Home_\">Home</a><br>\n");
      strcat(mainbuf, "<hr>\n");
      strcat(mainbuf, "Dir: ");
      strcat(mainbuf, theDir);
      strcat(mainbuf, "<br>\n<hr>\n<pre>\n");
      strcat(mainbuf, data);
      strcat(mainbuf, "\n</pre>\n");
      strcat(mainbuf, "</body>\n</html>\n");
    }
    
    void htmlout(int fd, char* data)
    {
      fstr=mimes[0].mimetype;
      sprintf(mainbuf, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n", fstr);
      ret=write(fd, mainbuf, strlen(mainbuf));
      buildbuf(data);
      ret=write(fd, mainbuf, strlen(mainbuf));
    }
    
    void error404(int fd)
    {
      fstr=mimes[0].mimetype;
      sprintf(mainbuf, "HTTP/1.0 404 OK\r\nContent-Type: %s\r\n\r\n", fstr);
      ret=write(fd, mainbuf, strlen(mainbuf));
      buildbuf("404 Error - File not found!");
      ret=write(fd, mainbuf, strlen(mainbuf));
    }

В листинге 7 показано, как программа cloud передает содержимое файла вместе с определенным типом MIME. Обратите внимание, что браузер ожидает, что сервер пошлет тип MIME как строку a Content-Type:. Когда в браузере Вы выбираете ссылки, сгенерированные программой cloud, вызывается эта функция и возвращает содержимое выбранного файла. Однако если в адресной строке браузера будет записана неверная ссылка, либо она будет как-то неправильно отредактирована, то об этом пользователя проинформирует функция error404 (приведенная выше).

Листинг 7. Передача в браузер содержимого файла:

    void retfile(int fd, int hit)
    {
      int file_fd;
      long ret;
    
      mimeokay(mainbuf);
    
      if(fstr == 0)
      {
        error404(fd);
        return;
      }
    
      if((file_fd = open(&mainbuf[4], O_RDONLY)) == -1)
      {
        error404(fd);
      }
      else
      {  
        aclog(LOG, "SEND", &mainbuf[4], hit);
    
        sprintf(mainbuf, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n", fstr);
        ret=write(fd, mainbuf, strlen(mainbuf));
    
        while((ret=read(file_fd, mainbuf, SBUF)) > 0 )
        {
          ret=write(fd, mainbuf, ret);
        }
      }
    }

В листинге 8 показано, как программа cloud строит список элементов с гиперссылками. Операция hyper используется несколько раз, поэтому она предварительно была выделена в отдельную функцию. Значение переменной isDir добавляется к началу текста /CD_ перед полным путем к имени файла, поэтому программа cloud знает, что она должна изображать содержимое этого директория. Функция fileList является самым главным элементом данного приложения.

Листинг 8. Функции выдачи списка элементов директория:

    void hyper(int isDir, char* name)
    {
      strcat(theList, "<a href=\"");
    
      if(isDir)
        strcat(theList, "/CD_");
    
      strcat(theList, (char*) theDir);
    
      if(strcmp(theDir, "/"))
        strcat(theList, "/");
    
      strcat(theList, name);
      strcat(theList, "\">");
      strcat(theList, name);
      strcat(theList, "</a>");
      strcat(theList, "\n");
    }

    char* fileList(void)
    {
      struct dirent **namelist;
      int n;
      long i;
      long j;
    
      theList[0]=0;
    
      n=scandir(".", &namelist, 0, (void*) alphasort);
    
      if (n < 0)
        perror("scandir");
      else
      {
        for(i=0; i<n; i++)
        {
          if(namelist[i]->d_type == DT_DIR)
          {
            if(!strcmp(namelist[i]->d_name, "."))
            {
              // strcat(theList, namelist[i]->d_name);
            }
            else if(!strcmp(namelist[i]->d_name, ".."))
            {
              if(strcmp(theDir, "/"))
              {
                strcat(theList, "<a href=\"");
                strcat(theList, "/CD_");
                strcat(theList, (char*) theDir);
    
                j=strlen(theList);
    
                while(j--)
                {
                  if(theList[j] == '/')
                  {
                    theList[j]=0;
                    j=1;
                  }
                }
                
                if(!strcmp(&theList[strlen(theList)-4], "/CD_"))
                {
                  strcat(theList, "/");
                }
    
                strcat(theList, "\">Parent Directory</a>");          
                strcat(theList, "\n");
              }
            }
            else
              hyper(TRUE, namelist[i]->d_name);
          }
          else
          {
            mimeokay(namelist[i]->d_name);
        
            if(fstr == 0)
            {
              strcat(theList, namelist[i]->d_name);
              strcat(theList, "\n");
            }
            else
              hyper(FALSE, namelist[i]->d_name);
          }
    
          free(namelist[i]);
        }  
    
        free(namelist);
      }
      
      return theList;
    }           

В листинге 9 определяется функциональность функции child – крошечного сервера cloud. Эта функциональность отрабатывает всякий раз, когда сервер получит запрос от браузера, функциональность простая – выделить буфера, необходимые для обработки запроса, обработать запрос, затем – освободить память с тем, чтобы памятью можно снова воспользоваться, когда это потребуется. На сотовом телефоне память, как ресурс, всегда в дефиците, так что когда ваша программа обработает запрос, память необходимо вернуть в систему.

Листинг 9. Функциональность демона child:

	
    void child(int fd, int hit)
    {
      long i;
      long ret;
      char* cret;
    
      mainbuf=malloc(SBUF+1);
      theList=malloc(SBUF+1);
      theDir=malloc(LBUF+1);
      cret=getcwd(theDir, LBUF);
      
      ret=read(fd, mainbuf, SBUF);
    
      if(ret == 0 || ret == -1)
      {
        error404(fd);
      }
      else
      {
        if(ret > 0 && ret < SBUF)
          mainbuf[ret]=0;
        else
          mainbuf[0]=0;
    
        for(i=0; i<ret; i++)
          if(mainbuf[i] == '\r' || mainbuf[i] == '\n')
            mainbuf[i]='*';
    
        aclog(LOG, "request", mainbuf, hit);
    
        for(i=4; i < SBUF; i++)
        {
          if(mainbuf[i] == ' ')
          {
            mainbuf[i]=0;
            break;
          }
        }
    
        if(!strncmp(&mainbuf[0], "GET /\0", 6) ||
           !strncmp(&mainbuf[0], "get /\0", 6))
        {
          htmlout(fd, fileList());
        }
        else
        {
          if(!strncmp(&mainbuf[5], "About_", 6))
          {
            htmlout(fd, about);
          }
          else if(!strncmp(&mainbuf[5], "Home_", 5))
          {
            htmlout(fd, fileList());
          }    
          else if(!strncmp(&mainbuf[5], "CD_", 3))
          {
            if(chdir(&mainbuf[8]) == -1)
            {
              error404(fd);
            }
            else
            {
              if(strcmp(theDir, &mainbuf[8]))
                strcpy(theDir, &mainbuf[8]);
                
              htmlout(fd, fileList());
            }
          }
          else
          {
            retfile(fd, hit);
          }
        }
      }
    
      free(theDir);
      free(theList);  
      free(mainbuf);  
      sleep(1);
      exit(1);
    }      

В листинге 10 определена функция main (главная функция программы) приложения cloud. В ней выделяется сокет TCP/IP, который будет слушать запросы от браузера. Затем инициализируется несколько глобальных переменных, таких как theDir – директория, откуда должна начать работу программа cloud. И, наконец, программа перейдет в состояние резидентной программы (называемой демоном), так чтобы отрабатывать запросы от браузера в фоновом режиме и не мешать работе остальных программ.

Листинг 10. Функция Main:

    int main(int argc, char **argv)
    {
      char* str;
      char* cret;
    
      static struct sockaddr_in cli_addr;
      static struct sockaddr_in serv_addr;
    
      socklen_t length;
    
      int i;
      int port;
      int pid;
      int listenfd;
      int socketfd;
      int hit;
    
      cret=getcwd(logDir, LBUF);
    
      if(argc < 2)
      {
        strcpy((char*) thePort, "80");
        port=atoi((char*) thePort);
      }
      else
      {
        if(!strcmp(argv[1], "-?"))
        {
          printf("Usage: cloud [Port Directory]\n");
          exit(0);
        }
        strcpy((char*) thePort, argv[1]);
        port=atoi((char*) thePort);
    
        if(port < 0 || port > 60000)
          aclog(ERROR, "Invalid port number (try 1 --> 60000)", argv[1], 0);
    
        if(chdir(argv[2]) == -1)
        {
          printf("ERROR: Invalid directory %s\n", argv[2]);
          exit(4);
        }
      }
    
      if(fork() != 0)
        return 0;
    
      signal(SIGCHLD, SIG_IGN);
      signal(SIGHUP, SIG_IGN);
    	
      for(i=0; i<32; i++)
        close(i);
    	
      setpgrp();
    
      aclog(LOG, "Cloud Port/PID=", (char*) thePort, getpid());
        
      if((listenfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)
        aclog(ERROR, "syscall", "socket", 0);
    	
      serv_addr.sin_family      = AF_INET;
      serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
      serv_addr.sin_port        = htons(port);
    
      if(bind(listenfd, (struct sockaddr*) &serv_addr,
              sizeof(serv_addr)) < 0)
        aclog(ERROR, "syscall", "bind", 0);
    
      if(listen(listenfd, 64) <0)
        aclog(ERROR, "syscall", "listen", 0);
    
      for(hit=1; ;hit++)
      {
        length=sizeof(cli_addr);
        
        if((socketfd=accept(listenfd,
                            (struct sockaddr*) &cli_addr,
                            (socklen_t*) &length)) < 0)
          aclog(ERROR, "syscall", "accept", 0);
    
        if((pid=fork()) < 0)
        {
          aclog(ERROR, "syscall", "fork", 0);
        }
        else
        {
          if(pid == 0)
          {
            close(listenfd);
            child(socketfd, hit);
          }
          else
          {
            close(socketfd);
          }
        }
      }
    }

Компиляция, установка и тестирование приложения

Вам нужно создать еще один файл для того, чтобы правильно построить приложение cloud с помощью команды makefile при пересборке ядра Android из исходных кодов. Создайте файл, называемый Android.mk, и скопируйте в него содержимое листинга 11. Этот файл также есть в исходных кодах, которые можно загрузить (в оригинале статьи).

Листинг 11. Android.mk:

    ifneq ($(TARGET_SIMULATOR),true)
    
    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    LOCAL_SRC_FILES:= cloud.c
    LOCAL_MODULE := cloud
    LOCAL_STATIC_LIBRARIES := libcutils libc
    include $(BUILD_EXECUTABLE)
    
    endif  # TARGET_SIMULATOR != true

Перейдите в внешний директорий исходных кодов ядра Android, создайте поддиректорий с именем cloud и поместите в него файлы cloud.c и Android.mk. Теперь все готово для создания нового ядра системы с крошечным приложением cloud внутри него.

Перейдите в корневой директорий исходных кодов ядра Android, наберите make, а затем отправляйтесь пить кофе. Этот процесс займет некоторое время, так что расслабьтесь и дайте системе сделать свою работу.

Если все пройдет без ошибок и система завершит операцию make, то в директории out/target/product/generic/system/bin Вы должны обнаружить бинарный файл приложения cloud. В действительности вам не нужно преодолевать все проблемы с установкой полного дистрибутива на вашем разлоченном сотовом телефоне Android. Просто скопируйте бинарный файл cloud на флеш-карточку SD. В листинге 12 показано, как это Вы можете сделать на хост компьютере (предполагается, что в директории mydroid содержится весь исходный код системы Android).

Листинг 12: Создание ядра с приложением cloud:

    $ cd mydroid/external
    $ mkdir cloud
    $ cd cloud
    $ cp ~/src/tinycloud/cloud.c .
    $ cp ~/src/tinycloud/Android.mk .
    $ cd ../..
    $ make
    
    --- Android system "make" messages scroll up the screen for a long time. ---
    
    $ cd out/target/product/generic/system/bin
    $ cp cloud /media/ANDROIDSDCARD/.

Предполагается , что в сотовом телефоне есть директория /media/ANDROIDSDCARD, т.е. флеш-карточка подключена и смонтирована. Кроме того, может быть другим имя вашей карточки SD. Правильное имя найдите в поддиректории /media (если Вы работаете в Ubuntu Linux).

Если запустить одну из бесплатных программ Terminal, которые можно найти в Android Market, то Вы сможете открывать сессии в самом телефоне Android. Приложение cloud следовало бы разместить в директории system/bin, но это делать не будем. Для удобства тестирования разместим его в другом директории. Создайте в директории /data новый директорий и назовите его cloud. Скопируйте бинарный файл cloud из директории /sdcard в /data/cloud. Затем запустите команду chmod для того, чтобы сделать программу cloud исполняемой, и наберите cloud. В листинге 13 показано, как это надо делать.

Листинг 13. Тестирование приложения cloud на вашем сотовом телефоне Android:

    $ su
    # cd data
    # mkdir cloud
    # cd cloud
    # cp /sdcard/cloud .
    # chmod 777 cloud
    # ./cloud
    # ps
    
    --- Listing of resident daemons, and "./cloud" should be one of them. ---

Нажмите кнопку Home, запустите браузер и перейдете по URL http://localhost. В браузере Вы должны увидеть результат работы крошечного приложения cloud. Вы можете выбирать ссылки и перемещаться по файловой системе вашего сотового телефона.

В добавок, если ваш телефон Android подключен к вашей Wi-Fi сети, то для того, чтобы подключится к приложению cloud, Вы можете использовать компьютер. Для того, чтобы это сделать, вам нужно знать IP адрес вашего сотового телефона в сети Wi-Fi. Есть много способов определить этот адрес, в том числе - просмотреть журнальные файлы вашего Wi-Fi маршрутизатора. Еще один способ – вернуться в программу Terminal и набрать команду netstat -r; Вы увидите результат, похожий на то, что изображено на листинге 14

Листинг 14. Использование команды Netstat для получения IP адреса сотового телефона:

    # netstat -r
    Proto Recv-Q Send-Q  Local Address    Foreign Address    ... 
    .
    .
    .
    tcp        0      0  192.168.0.3:80   192.168.0.5:58744  ...
    .
    .
    .

В адресной строке вашего браузера наберите http://192.168.0.3/ (IP адрес вашего сотового телефона). Вы моментально должны увидеть листинг файловой системы вашего сотового телефона Android, выдаваемого программой cloud.

Развитие проекта

Пока есть люди с идеями, существует много вариантов развития проекта, но есть несколько предложений, которые Вы, возможно, захотите попробовать:

  • Добавьте конкретный элемент меню, называемый Java, с помощью которого можно будет перейти в директорий, где расположены файлы классов языка Java, а затем выбирать их с целью их изучения (файлы классов являются, в действительности, заархивированными директориями и будут квалифицироваться как гиперссылки). Вы можете сделать это для любой другой директории, в которой размещен интересный для вас код.
  • Добавьте в верхней части страницы фрагмент, изображающий информацию из директория /proc, которая будет сама обновляться приблизительно один раз в минуту.
  • Напишите код, который позволит вам делать запросы с веб страниц к базам данных SQLite.
  • На флеш-карте SD можно размещать целые презентации, сделанные на HTML, а мобильность сотового телефона является замечательным свойством, так что с помощью веб браузера, имеющегося в большинстве современных презентационных систем, Вы сможете показывать свое презентационное слайд шоу со своего сотового телефона.

Когда Вы примите решение о том, как улучшать свое крошечное облако, то для добавления новой функциональности следуйте трем основным этапам, приведенным ниже:

  1. Измените функцию buildbuf в листинге 6: введите новый элемент меню, который представляет новую функциональность, которую Вы хотите добавить.
  2. Измените функцию child в листинге 9 так, чтобы она обслуживала новую функциональность. Например, изучите как в этих обеих функциях (buildbuf и child), работает элемент меню About_ и Вы увидите, как просто в нашу крошечную программу добавлять новую функциональность.
  3. Напишите функцию, которая будет обслуживать элемент меню и вставьте в функцию child вызов этой новой функции.

Заключение

Всегда хорошо знать как можно больше об устройстве, которое Вы используете. Кроме того, инструментальные средства, с помощью которых Вы изучаете устройство, могут сами по себе оказаться интересными. Создание крошечного облачного приложения и подключение его к вашему сотовому телефону с системой Android – больше для удовольствия и краткого ознакомления, которое подвигнет вас к более детальному изучению того, что находится " под капотом" этих удивительных устройств.