Android Boot ServiceManager boot

Source: Internet
Author: User

In fact, after the Init process starts, the ServiceManager process starts much earlier than the zygote because the ServiceManager process service is needed to start the zygote process. ServiceManager is a daemon that maintains the binder communication between the system service and the client.

The most common communication mechanism in Android is that Binder,binder is primarily composed of client, Server, ServiceManager, and binder drivers. Where the client, service, and ServiceManager run in user space, and the binder driver runs in kernel space. The core component is the binder driver , and ServiceManager provides the function of auxiliary management, whether the client or service to communicate before the first to contact with ServiceManager. ServiceManager is a daemon that manages the server and provides the client with the ability to query the server.

declarations in the init.rcThe ServiceManager is started as a service in init.rc.
Service Servicemanager/system/bin/servicemanagerclass coreuser systemgroup systemcriticalonrestart Restart Zygoteonrestart Restart Mediaonrestart Restart Surfaceflingeronrestart restart DRM
the main function of ServiceManagerThe source location is in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/SERVICE_MANAGER.C, and its main function is as follows:
int main (int argc, char **argv) {    struct binder_state *bs;    Macro: #define Binder_service_manager ((void*) 0). Indicates that the servicemanager corresponds to a handle of 0, and the surface itself is the Server Manager. The other server process handle values are greater than 0.    void *svcmgr = Binder_service_manager;    Open Binder device, map 128K of memory address space    bs = Binder_open (128*1024);    Tell the binder driver that itself is the binder context manager    if (Binder_become_context_manager (BS)) {        Aloge ("Cannot become context Manager (%s) \ n ", Strerror (errno));        return-1;    }        ServiceManager the corresponding handle assignment value    svcmgr_handle = svcmgr;    Enter a wireless loop that acts as a server role, waiting for client requests    Binder_loop (BS, Svcmgr_handler);    return 0;}
Binder_open functionBinder_open (unsigned mapsize) function source location in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/BINDER.C
The Binder_open (unsigned mapsize) function eventually returns the type binder_state*, which records the binder driver file handle that was just opened and the final destination address that the mmap () maps to.
struct Binder_state {         int fd;   File descriptor, open/dev/binder device         void* mapped;  Map the device file/dev/binder to the start address of the process space         unsigned mapsize;//Map the size of the memory space};
This structure is also defined in the BINDER.C. The Binder_open (unsigned mapsize) function code is as follows:
struct Binder    _state *binder_open (unsigned mapsize) {struct binder_state *bs;    BS = malloc (sizeof (*BS));        if (!bs) {errno = Enomem;    return 0;    }//Open/dev/binder Drive File BS->FD = open ("/dev/binder", O_RDWR);        if (BS->FD < 0) {fprintf (stderr, "Binder:cannot Open device (%s) \ n", Strerror (errno));    Goto Fail_open;    }//Set the space size to be mapped 128*1024 bs->mapsize = mapsize;    Start mapping bs->mapped = Mmap (NULL, Mapsize, Prot_read, Map_private, BS->FD, 0); if (bs->mapped = = map_failed) {fprintf (stderr, "Binder:cannot MAP device (%s) \ n", Strerror (errno        ));    Goto Fail_map;    }/* Todo:check version */return bs;fail_map:close (BS->FD); Fail_open:free (BS); return 0;} 

The parameter mapsize indicates how many bytes of binder-driven files it wants to map to the local space. You can see that the binder size mapped by the service Manager service and the normal process is not the same. It maps 128K bytes of binder-driven files to memory space, while normal processes map binder_vm_size (that is, 1M minus 8K) bytes in binder files. the specific mapping action is done by Mmap (), which maps a portion of the binder driver file to the process space. The function prototype for mmap () is as follows:

void* mmap (void * addr, size_t len, int prot, int flags, int fd, off_t offset);

The parameter addr is used to indicate that the file should be mapped to the start address of the process space, which is generally specified as a null pointer, at which point the kernel determines the start address.

The parameter len is the length of the mapped bytes.
The parameter PROT indicates access to this mapping space, which can be prot_read (readable), prot_write (writable), prot_exec (executable), Prot_none (inaccessible).
Parameter fd to be mapped by the binder driver file.

The parameter offset is the starting position of the offset.

Binder_become_context_manager functionBinder_become_context_manager (struct binder_state *bs) function source location in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/BINDER.C

This function is to make the current process the only context manager in the entire system, the service Manager. The code is very simple, just sending the binder_set_context_mgr to the binder driver. The source code is as follows:

int Binder_become_context_manager (struct binder_state *bs) {    return ioctl (BS->FD, binder_set_context_mgr, 0);}

Binder_loop function

Binder_loop (struct binder_state *bs, binder_handler func) function source location in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/BINDER.C. At this point, it has formally entered the loop and become a server. Note the parameters of this function: BS is the descriptor of the file/dev/binder, and Func is the function Svcmgr_handler.

void Binder_loop (struct binder_state *bs, binder_handler func) {int res;    struct Binder_write_read BWR;    unsigned readbuf[32];    bwr.write_size = 0;    bwr.write_consumed = 0;        Bwr.write_buffer = 0;    Readbuf[0] = Bc_enter_looper;    Binder_write (BS, readbuf, sizeof (unsigned)); for (;;)        {bwr.read_size = sizeof (READBUF);        bwr.read_consumed = 0;        Bwr.read_buffer = (unsigned) readbuf;//sends data to BINDER driver res = IOCTL (BS-&GT;FD, Binder_write_read, &AMP;BWR) via device descriptor;            if (Res < 0) {Aloge ("Binder_loop:ioctl failed (%s) \ n", Strerror (errno));        Break        }//Parse drive data, call callback function func res = binder_parse (BS, 0, Readbuf, bwr.read_consumed, func); if (res = = 0) {aloge ("binder_loop:unexpected reply?!            \ n ");        Break            } if (Res < 0) {aloge ("Binder_loop:io error%d%s\n", Res, strerror (errno));        Break }    }}
binder_parse function

This function source location in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/BINDER.C

This function is mainly to parse the binder file and execute the corresponding instructions. The big head of this function is actually the Svcmgr_handler function that passes over all the way, that is the parameter func.

int binder_parse (struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, Binder_hand    Ler func) {int r = 1;    uint32_t *end = ptr + (SIZE/4);        while (PTR < end) {uint32_t cmd = *ptr++;            ...//Note this br_transaction case br_transaction: {struct BINDER_TXN *txn = (void *) ptr;                if ((end-ptr) * sizeof (uint32_t) < sizeof (struct BINDER_TXN)) {Aloge ("Parse:txn too small!\n");            return-1;            } binder_dump_txn (TXN);                if (func) {unsigned RDATA[256/4];                struct Binder_io msg;                struct BINDER_IO reply;                int res;                Bio_init (&reply, Rdata, sizeof (Rdata), 4);                Bio_init_from_txn (&msg, TXN);                res = func (BS, TXN, &msg, &reply);            Binder_send_reply (BS, &reply, Txn->data, res); } ptr + = sizeof (*TXn)/sizeof (uint32_t);        Break    }     ...    } return r;}

Svcmgr_handler function

This function source location in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/SERVICE_MANAGER.C

int Svcmgr_handler (struct binder_state *bs,                   struct binder_txn *txn,                   struct binder_io *msg,                   struct binder_ Io *reply) {...    Switch (Txn->code) {//Client gets service request case    Svc_mgr_get_service: Case    svc_mgr_check_service:        s = bio_get_ String16 (msg, &len);        ptr = Do_find_service (BS, S, Len, txn->sender_euid);        if (!ptr) break            ;        Bio_put_ref (reply, ptr);        Return 0;//service-side Request Add service case    Svc_mgr_add_service:        s = bio_get_string16 (msg, &len);        ptr = Bio_get_ref (msg);        allow_isolated = Bio_get_uint32 (msg)? 1:0;        if (Do_add_service (BS, S, Len, PTR, Txn->sender_euid, allow_isolated))            return-1;        Break, ...    }    Bio_put_uint32 (reply, 0);    return 0;}

svclist Linked list

A linked list is declared in Service_manager.c svclist

struct Svcinfo *svclist = 0;

Svclist Records all the "service agent" information added to the system, which is organized into a one-way list. The Svclist linked list node type is Svcinfo, as follows:

struct Svcinfo {    struct svcinfo *next;    void *ptr;//records the binder handle value corresponding to the system service    struct Binder_death death;    int allow_isolated;    unsigned len;    uint16_t the name of the name[0];//system service};

When the application calls GetService () to get the proxy interface for the system service, ServiceManager searches for the svclist linked list, as described below.

Do_add_service function

This function source location in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/SERVICE_MANAGER.C

int Do_add_service (struct binder_state *bs, uint16_t *s, unsigned len, void *ptr, Unsi    gned uid, int allow_isolated) {struct Svcinfo *si; Alogi ("Add_service ('%s ',%p,%s) uid=%d\n", Str8 (s), PTR,//allow_isolated?    "allow_isolated": "!allow_isolated", UID); if (!ptr | | (len = = 0) | |        (Len > 127))    return-1;             See if the service has registration permissions if (!svc_can_register (UID, s)) {Aloge ("Add_service ('%s ',%p) uid=%d-permission denied\n",        Str8 (s), PTR, UID);    return-1;    }//Find service in the list of services Si = Find_svc (s, Len); See if the service has registered if (SI) {if (si->ptr) {Aloge ("Add_service ('%s ',%p) Uid=%d-already registered, OV            Erride\n ", Str8 (s), PTR, UID);        Svcinfo_death (BS, SI);    } si->ptr = ptr;        } else {//If not registered, create one and add to the top of the table of Svclist Services list.        Si = malloc (sizeof (*SI) + (len + 1) * sizeof (uint16_t)); if (!si) {Aloge ("Add_service ('%s '),%p) Uid=%d-out of Memory\n ", Str8 (s), PTR, UID);        return-1;        } si->ptr = ptr;        Si->len = Len;        memcpy (Si->name, S, (len + 1) * sizeof (uint16_t));        Si->name[len] = ' + ';        Si->death.func = Svcinfo_death;        Si->death.ptr = si;        si->allow_isolated = allow_isolated;        Si->next = svclist;    Svclist = si;    }//Notify binder device that there is a service registration in.    Binder_acquire (BS, PTR);    Binder_link_to_death (BS, PTR, &si->death); return 0;}

Do_find_service function

This function source location in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/SERVICE_MANAGER.C

void *do_find_service (struct binder_state *bs, uint16_t *s, unsigned len, unsigned uid) {    struct svcinfo *si;    The previous function also called the function    si = find_svc (s, len);//    Alogi ("Check_service ('%s ') ptr =%p\n", Str8 (s), Si si->ptr:0); 
   if (si && si->ptr) {        if (!si->allow_isolated) {            //If this service doesn ' t allow access from Isola Ted processes,            //Then check the UID to see if it is isolated.            unsigned appid = uid% Aid_user;            if (AppID >= aid_isolated_start && appid <= aid_isolated_end) {                return 0;            }        }        Return si->ptr;    } else {        return 0;    }

find_svc function

This function source location in FRAMEWORKS/BASE/CMDS/SERVICEMANAGER/SERVICE_MANAGER.C

struct Svcinfo *find_svc (uint16_t *s16, unsigned len) {    struct svcinfo *si;    Traverse Svclist, find service for    (si = svclist; si; si = si->next) {        if (len = = Si->len) &&            !memcmp (s16, si ->name, Len * sizeof (uint16_t)) {            return si;        }    }    return 0;}

Summary

The daemon ServiceManager loops the data from the binder device file, and then resolves and responds to the request, including the service side's Add service request and the client's query to get the service request.




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.