欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

前言

宜陽(yáng)網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)公司等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)成立與2013年到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。

Android底層服務(wù),即運(yùn)行在 linux 下的進(jìn)程,是 Android 系統(tǒng)運(yùn)行的基礎(chǔ),完成 Android 或者說(shuō)計(jì)算機(jī)最基本的功能。比如連接服務(wù)(包括 WIFI,BT 等等);比如 Android 的 adb 功能;比如存儲(chǔ)監(jiān)控等等。沒(méi)有這些底層服務(wù),上層也就沒(méi)有了對(duì)應(yīng)的功能。

Android 底層服務(wù)往往是常駐內(nèi)存,時(shí)刻運(yùn)行完成任務(wù)。底層服務(wù)進(jìn)程,往往具有更多的權(quán)限,可能和驅(qū)動(dòng)通信,可能和 linux 內(nèi)核通信,可能需要操作系統(tǒng)核心運(yùn)行文件以及節(jié)點(diǎn)等等。所以,底層服務(wù),可以幫你完成更多計(jì)算機(jī)基本功能。

本文所使用的 AOSP 是基于 Android 8.1。閱讀文本需要對(duì) Android 的架構(gòu)、編譯系統(tǒng)、AOSP工程和 SeAndroid 有基本認(rèn)識(shí)。

創(chuàng)建守護(hù)進(jìn)程

創(chuàng)建目錄編寫(xiě)代碼

創(chuàng)建目錄

我們?cè)?Android 系統(tǒng)通用守護(hù)進(jìn)程目錄下創(chuàng)建我們的守護(hù)進(jìn)程,當(dāng)然你也可以在其它目錄下放置你的守護(hù)進(jìn)程。

/system/core/

在上面的目錄下,創(chuàng)建守護(hù)進(jìn)程的文件夾 nativeservice,那么,我們的守護(hù)進(jìn)程就存在如下目錄,下文中稱簡(jiǎn)稱目錄代表如下目錄。

/system/core/nativeservice/

編寫(xiě)代碼

在目錄中創(chuàng)建主代碼文件 native_main.cpp。另外,我們需要編譯,那么就需要 mk 文件,創(chuàng)建一個(gè) Android.mk 文件。這時(shí),目錄架構(gòu)就是如下這個(gè)樣子

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

編寫(xiě)Android.mk

我在代碼中盡可能的注釋清楚重要語(yǔ)句的作用,讀者如果對(duì) Android AOSP 編譯不了解的,可以查閱更多 mk 語(yǔ)法的資料學(xué)習(xí)。

# Copyright 2013 The Android Open Source Project
# 當(dāng)前路徑
LOCAL_PATH := $(call my-dir)
#清除歷史變量
include $(CLEAR_VARS)

### nativeservice ###

#待編譯的源碼文件
LOCAL_SRC_FILES := \
 native_main.cpp \

common_c_includes := \
 bionic \
 system/core/include/sysutils \
#引用一些函數(shù)庫(kù)
common_shared_libraries := \
 libsysutils \
 libcutils \
 liblog \
 libutils \
 libbinder \
 libbase

LOCAL_C_INCLUDES := \
 $(common_c_includes)

#守護(hù)進(jìn)程的名字
LOCAL_MODULE := nativeservice
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
LOCAL_SHARED_LIBRARIES := \
 $(common_shared_libraries)
LOCAL_MODULE_TAGS := optional

#編譯守護(hù)進(jìn)程,也就是可執(zhí)行文件
#編譯后,在/system/bin/ 下,變多了 nativeservice 可執(zhí)行文件。
include $(BUILD_EXECUTABLE)

編寫(xiě)native_main.cpp

在 Linux 中,一個(gè)開(kāi)機(jī)啟動(dòng)的服務(wù),執(zhí)行完后會(huì)自動(dòng)退出,而我們是守護(hù)進(jìn)程,那么就需要一直運(yùn)行。讓程序一直運(yùn)行有很多種方法。在 native_main.cpp 中貼出了三種方式,它們分別是 epoll,有名管道(FIFO)和循環(huán)。

epoll 的方式是 Android 系統(tǒng)比較常見(jiàn)的方式,系統(tǒng)的電池狀態(tài)變化、USB 接口狀態(tài)變化等守護(hù)進(jìn)程便是通過(guò) epoll 的方式,實(shí)時(shí)鑒定并讀取新?tīng)顟B(tài)。

有名管道,在 IPC 通信中比較簡(jiǎn)單、便捷,適合輕量級(jí)任務(wù)。

循環(huán),這個(gè)是最老套的方式。

三種方式在 native_main.cpp 都貼出來(lái)了,本文側(cè)重使用有名管道(FIFO)的方式,鑒于篇幅過(guò)長(zhǎng),其它方式就一筆帶過(guò)了,如果讀者對(duì) epoll 等較為興趣的,可以自行查閱更多資料學(xué)習(xí)。

下面是 native_main.cpp 的代碼,請(qǐng)認(rèn)真看注釋哦。

//
// Created familyyuan user on 18-4-20.
//

#include <errno.h>
#include <string.h>
#include <unistd.h>

#include <cutils/log.h>

#include <fcntl.h>
#include <android-base/logging.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <cutils/uevent.h>

#include <sys/ioctl.h>

#define MAX_EPOLL_EVENTS 40
//epoll方式的 epoll fd
static int epollfd;
//FIFO 方式的 fd
static int fifo_fd;
//epoll方式的 uevent fd
static int uevent_fd;

#define BUFFER_SIZE PIPE_BUF

int main(int argc, char *argv[]) {
 SLOGD("native_service start");
 //
 // 1、epoll 的方式,
 // 監(jiān)聽(tīng)一個(gè) socket,如果 socket 被連接,便激活程序讀取數(shù)據(jù)。
 // Android 驅(qū)動(dòng)和用戶態(tài)程序較多使用這種方式交互。
 //
/*
 int eventct = 5;
 struct epoll_event events[eventct];
 struct epoll_event ev;
 uevent_fd = uevent_open_socket(64*1024, true);

 //創(chuàng)建 epoll 通道,監(jiān)聽(tīng) socket fd
 epollfd = epoll_create(MAX_EPOLL_EVENTS);
 if (epollfd == -1) {
  SLOGD("native_service epoll_create failed");
 } else {
  SLOGD("native_service epoll_create success");
 }

 //
 fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
 ev.events = EPOLLIN;
 ev.data.fd=uevent_fd;
 //注冊(cè) epoll fd
 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) {
   SLOGD("native_service epoll_ctl failed");
 } else {
  SLOGD("native_service epoll_ctl success");
 }

 while(1){
  SLOGD("native_service epoll running");
  int nevents = 0;
  // 監(jiān)聽(tīng) socket 端口
  nevents = epoll_wait(epollfd, events, eventct, 100000);
  if (nevents == -1 || nevents == 0) {
   SLOGD("native_service epoll_wait failed");
  } else {
   SLOGD("native_service epoll_wait success");
  }
  epoll_ctl(epollfd, EPOLL_CTL_DEL, uevent_fd, &ev);
 }
 close(uevent_fd);
*/

 //
 // 2、 FIFO 的方式,
 // 在/mnt/下創(chuàng)建一個(gè)名為 nativeservice 的管道,
 // 監(jiān)聽(tīng)管道的數(shù)據(jù)變化,如果有數(shù)據(jù)寫(xiě)入管道,便讀取數(shù)據(jù)。
 // 
 int res;
 int bytes = 0;
 char buffer[BUFFER_SIZE + 1];
 // 創(chuàng)建 FIFO
 res = mkfifo("/mnt/nativeservice", 0777);
 if (res != 0){
  SLOGD("native_service create fifo exist or failed");
 } else{
  SLOGD("native_service create fifo success");
 }
 // 以阻塞的方式打開(kāi) FIFO,知道管道有數(shù)據(jù)寫(xiě)入,激活程序,往下執(zhí)行
 fifo_fd = TEMP_FAILURE_RETRY(open("/mnt/nativeservice",O_RDONLY));
 if (fifo_fd < 0) {
  SLOGD("native_service open failed");
 } else {
  SLOGD("native_service open success");
 }
 if (fifo_fd != -1){
  while(1){
   //讀取管道數(shù)據(jù),如果沒(méi)有數(shù)據(jù),阻塞等待數(shù)據(jù)被寫(xiě)入,激活
   res = read(fifo_fd, buffer, BUFFER_SIZE);
   bytes += res;
   SLOGD("native_service result=%s", buffer);
  }
 } else {
  SLOGD("native_service open failed");
 }
 //關(guān)閉管道資源。
 close(fifo_fd);

 //
 // 3、循環(huán)的方式
 // 這種方式代碼最簡(jiǎn)單,但是耗資源,沒(méi)有實(shí)時(shí)性。
 // 一個(gè)死循環(huán),每隔 5 秒運(yùn)行一次
 //
/* while(1){
  SLOGD("native_service runnig");
  sleep(5);
  SLOGD("native_service wake");
 }
*/
 SLOGD("native_service die");
 return 0;
}

推進(jìn)編譯系統(tǒng)

編寫(xiě)好 Android.mk 和 native_main.cpp 后,可以通過(guò)單邊命令 “mmm system/core/nativeservice” 編譯我們的守護(hù)進(jìn)程了。但是此時(shí)用 make 編譯整個(gè) AOSP 時(shí),卻不會(huì)編譯我們的 nativeservice。因此,需要告訴編譯系統(tǒng),編譯工程時(shí),同時(shí)編譯 nativeservice。修改如下

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

在 /build/make/target/product/core.mk 文件添加 nativeservice,當(dāng)然不限制添加在這個(gè)文件,很多廠商的工程,也會(huì)增加自己的 PRODUCT_PACKAGES 配置 mk 文件。

配置開(kāi)機(jī)啟動(dòng)

至此,編譯整個(gè)工程,守護(hù)進(jìn)程也可以被編譯了,這個(gè)時(shí)候,刷到手機(jī)是否就可以運(yùn)行了呢?不會(huì)的,我們還需要讓守護(hù)進(jìn)程在手機(jī)開(kāi)機(jī)的時(shí)候運(yùn)行起來(lái),且運(yùn)行中進(jìn)程死掉的話,也需要重新啟動(dòng)守護(hù)進(jìn)程。方法如下

在 system/core/rootdir/init.rc 文件中添加如下代碼

service healthd /system/bin/healthd
 class core
 critical
 group root system wakelock
#我們的代碼開(kāi)始
service nativeservice /system/bin/nativeservice
 class main #main類(lèi),屬于main的服務(wù)會(huì)開(kāi)機(jī)被運(yùn)行,且死掉會(huì)重啟
 group system #屬于 system 組
 #user system #以system用戶啟動(dòng),不設(shè)置以root用戶啟動(dòng)
 seclabel u:r:nativeservice:s0 #SeAndroid SContext,domain是nativeservice
 restorecon nativeservice
#我們的代碼結(jié)束
service console /system/bin/sh

讀者可以查看 AOSP 中 system/core/init/README.md 文件了解 init.rc 的語(yǔ)法和配置方法。對(duì)于 class core 等不同類(lèi)別的區(qū)別,讀者可以閱讀《Android加密之全盤(pán)加密》相關(guān)的闡述。

配置SeAndroid

至此,編譯整個(gè)工程,守護(hù)進(jìn)程也可以被編譯了,也配置了開(kāi)機(jī)自啟動(dòng)。這個(gè)時(shí)候,刷到手機(jī)是否就可以運(yùn)行守護(hù)進(jìn)程了呢?不可以,我們知道 Android 繼用了 SeLinux 安全機(jī)制,同時(shí)發(fā)展出 SeAndroid 機(jī)制,所有文件和進(jìn)程都需要配置 SeAndroid 才能有權(quán)限。因此,如果沒(méi)有給守護(hù)進(jìn)程以及守護(hù)進(jìn)程需要操作的目錄和文件賦予權(quán)限,都會(huì)被 SeAndroid 過(guò)濾或禁止。

由于 QCOM 和 Mediatek 的不同,在相關(guān)文件的放置路徑會(huì)不同,但是方法都是一樣的,不同的平臺(tái),找到對(duì)應(yīng)的路徑下的文件就可以了。本文以 MTK 平臺(tái)的為例。

1、在 device/mediatek/sepolicy/basic/non_plat/file_contexts 中添加如下代碼

/system/bin/nativeservice u:object_r:nativeservice_exec:s0

2、在 device/mediatek/sepolicy/basic/non_plat/ 中添加 nativeservice.te 文件,文件內(nèi)容如下

#守護(hù)進(jìn)程 domain 為 nativeservice
type nativeservice, domain;
typeattribute nativeservice coredomain;

type nativeservice_exec, exec_type, file_type;

init_daemon_domain(nativeservice)

#allow nativeservice self:netlink_kobject_uevent_socket create_socket_perms_no_ioctl;
#allow nativeservice tmpfs:file { getattr open read write ioctl create };
#允許 nativeservice 在mnt目錄讀寫(xiě)管道文件
allow nativeservice tmpfs:fifo_file rw_file_perms;
#允許 nativeservice 在mnt目錄創(chuàng)建管道文件
allow nativeservice tmpfs:fifo_file create_file_perms;
#允許 nativeservice 在mnt目錄讀寫(xiě)
allow nativeservice tmpfs:dir rw_dir_perms;
#允許 nativeservice 在mnt目錄創(chuàng)建目錄
allow nativeservice tmpfs:dir create_dir_perms;

刷機(jī)驗(yàn)證

至此,需要編譯整個(gè) AOSP 工程,當(dāng)然,如果有編譯過(guò),只需要增量編譯即可,很快就可以編譯完成。

1、刷機(jī)后在手機(jī)的 /system/bin/nativeservie 目錄下能看到守護(hù)進(jìn)程;

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

2、看一下 SeAndroid 的 SContext

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

3、看一下 FIFO 管道文件

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

4、prwx 前面的 p 代表是一個(gè)管道文件

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

5、管道文件 SeAndroid 的 tcontext

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

6、守護(hù)進(jìn)程啟動(dòng),啟動(dòng)后打開(kāi)管道,等待管道數(shù)據(jù)寫(xiě)入。由于守護(hù)進(jìn)程比抓 log 的工具啟動(dòng)還早,因此,開(kāi)機(jī)時(shí)前面的 log 無(wú)法抓取,如下 log 是手動(dòng) kill 掉守護(hù)進(jìn)程打印的 log

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

7、通過(guò)終端給管道寫(xiě)入數(shù)據(jù)

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

8、守護(hù)進(jìn)程激活,讀取數(shù)據(jù)

創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))

總結(jié)

Android 守護(hù)進(jìn)程可以做很多上層無(wú)法完成的功能,但是,為了安全,要運(yùn)用好 SeAndroid,以最小能力的原則去配置安全權(quán)限。創(chuàng)建守護(hù)進(jìn)程,要編寫(xiě)對(duì)應(yīng)代碼,配置 rc 文件,配置 SeAndroid。

以上這篇?jiǎng)?chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持創(chuàng)新互聯(lián)。

新聞標(biāo)題:創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))
網(wǎng)頁(yè)網(wǎng)址:http://chinadenli.net/article16/gioddg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)標(biāo)簽優(yōu)化、定制開(kāi)發(fā)、軟件開(kāi)發(fā)、App開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作