Android系統Recovery工作原理之使用update.zip升級過程分析(八)—解析並執行升級指令碼updater-script

來源:互聯網
上載者:User

       Android系統Recovery工作原理之使用update.zip升級過程分析(八)---升級程式update_binary的執行過程


一、update_binary的執行過程分析

       上一篇幅中的子進程所執行的程式binary實際上就是update.zip包中的update-binary。我們在上文中也說過,Recovery服務在做這一部分工作的時候是先將包中update-binary拷貝到記憶體檔案系統中的/tmp/update_binary,然後再執行的。update_binary程式的源碼位於gingerbread0919/bootable/recovery/updater/updater.c,源碼如下:

/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include "edify/expr.h"#include "updater.h"#include "install.h"#include "minzip/Zip.h"// Generated by the makefile, this function defines the// RegisterDeviceExtensions() function, which calls all the// registration functions for device-specific extensions.#include "register.inc"// Where in the package we expect to find the edify script to execute.// (Note it's "updateR-script", not the older "update-script".)#define SCRIPT_NAME "META-INF/com/google/android/updater-script"int main(int argc, char** argv) {    // Various things log information to stdout or stderr more or less    // at random.  The log file makes more sense if buffering is    // turned off so things appear in the right order.    setbuf(stdout, NULL);    setbuf(stderr, NULL);    if (argc != 4) {        fprintf(stderr, "unexpected number of arguments (%d)\n", argc);        return 1;    }    char* version = argv[1];    if ((version[0] != '1' && version[0] != '2' && version[0] != '3') ||        version[1] != '\0') {        // We support version 1, 2, or 3.        fprintf(stderr, "wrong updater binary API; expected 1, 2, or 3; "                        "got %s\n",                argv[1]);        return 2;    }    // Set up the pipe for sending commands back to the parent process.    int fd = atoi(argv[2]);    FILE* cmd_pipe = fdopen(fd, "wb");    setlinebuf(cmd_pipe);    // Extract the script from the package.    char* package_data = argv[3];    ZipArchive za;    int err;    err = mzOpenZipArchive(package_data, &za);    if (err != 0) {        fprintf(stderr, "failed to open package %s: %s\n",                package_data, strerror(err));        return 3;    }    const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME);    if (script_entry == NULL) {        fprintf(stderr, "failed to find %s in %s\n", SCRIPT_NAME, package_data);        return 4;    }    char* script = malloc(script_entry->uncompLen+1);    if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) {        fprintf(stderr, "failed to read script from package\n");        return 5;    }    script[script_entry->uncompLen] = '\0';    // Configure edify's functions.    RegisterBuiltins();    RegisterInstallFunctions();    RegisterDeviceExtensions();    FinishRegistration();    // Parse the script.    Expr* root;    int error_count = 0;    yy_scan_string(script);    int error = yyparse(&root, &error_count);    if (error != 0 || error_count > 0) {        fprintf(stderr, "%d parse errors\n", error_count);        return 6;    }    // Evaluate the parsed script.    UpdaterInfo updater_info;    updater_info.cmd_pipe = cmd_pipe;    updater_info.package_zip = &za;    updater_info.version = atoi(version);    State state;    state.cookie = &updater_info;    state.script = script;    state.errmsg = NULL;    char* result = Evaluate(&state, root);    if (result == NULL) {        if (state.errmsg == NULL) {            fprintf(stderr, "script aborted (no error message)\n");            fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");        } else {            fprintf(stderr, "script aborted: %s\n", state.errmsg);            char* line = strtok(state.errmsg, "\n");            while (line) {                fprintf(cmd_pipe, "ui_print %s\n", line);                line = strtok(NULL, "\n");            }            fprintf(cmd_pipe, "ui_print\n");        }        free(state.errmsg);        return 7;    } else {        fprintf(stderr, "script result was [%s]\n", result);        free(result);    }    if (updater_info.package_zip) {        mzCloseZipArchive(updater_info.package_zip);    }    free(script);    return 0;}

        通過上面的源碼來分析下這個程式的執行過程:

        ①函數參數以及版本的檢查:當前updater binary API所支援的版本號碼有1,2,3這三個。

        ②擷取管道並開啟:在執行此程式的過程中向該管道寫入命令,用於通知其父進程根據命令去更新UI顯示。

        ③讀取updater-script指令碼:從update.zip包中將updater-script指令碼讀到一塊動態記憶體中,供後面執行。

        ④Configure edify’s functions:註冊指令碼中的語句處理函數,即識別指令碼中命令的函數。主要有以下幾類

                   RegisterBuiltins():註冊程式中控制流程程的語句,如ifelse、assert、abort、stdout等。

                            RegisterInstallFunctions():實際安裝過程中安裝所需的功能函數,比如mount、format、set_progress、set_perm等等。

                   RegisterDeviceExtensions():與裝置相關的額外添加項,在源碼中並沒有任何實現。

                   FinishRegistration():結束註冊。

        ⑤Parsethe script:調用yy*庫函數解析指令碼,並將解析後的內容存放到一個Expr類型的python類中。主要函數是yy_scan_string()和yyparse()。

        ⑥執行指令碼:核心函數是Evaluate(),它會調用其他的callback函數,而這些callback函數又會去調用Evaluate去解析不同的指令碼片段,從而實現一個簡單的指令碼解譯器。

        ⑦錯誤資訊提示:最後就是根據Evaluate()執行後的傳回值,給出一些列印資訊。


            這一執行過程非常簡單,最主要的函數就是Evaluate。它負責最終執行解析的指令碼命令。而安裝過程中的命令就是updater-script。

            下一篇幅將介紹updater-script指令碼中的文法以及這個指令碼在具體升級中的執行流程。




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.