android--4.2 Vold Mount Management _commandlistener (ii)

Source: Internet
Author: User
Tags sendmsg strcmp

In the previous blog introduced a general structure android--4.2 Vold Mount Management _ main Building (a), according to the code sequence structure to analyze sequentially, here to see what commandlistener this class did.



Writing is not easy, reproduced please specify the source: http://blog.csdn.net/jscese/article/details/38434263

One: Commandlistener construction

Build an instance in the main function of/system/vold/main.cpp:

     CL = new Commandlistener ();    Vm->setbroadcaster ((SocketListener *) cl);    Nm->setbroadcaster ((SocketListener *) cl);    ..     /* * Now this we ' re up, we can respond to commands     */    if (Cl->startlistener ()) {        Sloge ("Unable to start Commandlistener (%s) ", Strerror (errno));        Exit (1);    }


The source code is located in/system/vold/commandlistener.cpp, with the following constructors:

Commandlistener::commandlistener ():                 frameworklistener ("Vold", True) {    registercmd (new Dumpcmd ());    Registercmd (New Volumecmd ());    Registercmd (New Aseccmd ());    Registercmd (New Obbcmd ());    Registercmd (New Storagecmd ());    Registercmd (New Xwarpcmd ());    Registercmd (New Cryptfscmd ());}

Constructs an instance of a parent class Frameworklistener

First look at the structure of Frameworklistener:

Frameworklistener::frameworklistener (const char *socketname, BOOL withseq):                            SocketListener (Socketname, True, WITHSEQ) {    init (socketname, WITHSEQ);}. void Frameworklistener::init (const char *socketname, bool withseq) {    mcommands = new Frameworkcommandcollection (); c3/>errorrate = 0;    Mcommandcount = 0;    Mwithseq = Withseq;}

You can see that the "Vold" passed in does not work in this class, it is for a higher layer of the structure, and then look at the/system/core/libsysutils/src/socketlistener.cpp:


Socketlistener::socketlistener (const char *socketname, BOOL listen, bool usecmdnum) {    init (socketname,-1, listen, Usecmdnum);} void Socketlistener::init (const char *socketname, int socketfd, BOOL listen, bool usecmdnum) {    Mlisten = listen;    Msocketname = Socketname;    Msock = SOCKETFD;    Musecmdnum = Usecmdnum;    Pthread_mutex_init (&mclientslock, NULL);    mclients = new Socketclientcollection ();}
The initialization thread lock mclientslock,new a socketclient container mclients.

Inheritance Relationship: Commandlistener-->frameworklistener-->socketlistener



II: Command Registration

The Commandlistener constructor in the above calls the registration function Register of the parent class, registering the Commad into the Frameworklistener mcommands container.

/system/core/libsysutils/src/frameworklistener.cpp registration is as follows:

void Frameworklistener::registercmd (Frameworkcommand *cmd) {    mcommands->push_back (cmd);}

You can see that the row parameter here is the Frameworkcommand type,

Because of the inheritance relationship of these command classes : Volumecmd-->voldcommand-->frameworkcommand


Here we take volumecmd as an example of learning:

Commandlistener::volumecmd::volumecmd ():                 voldcommand ("volume") {}

Voldcommand::voldcommand (const char *cmd):              frameworkcommand (cmd)  {}

Frameworkcommand::frameworkcommand (const char *cmd) {    mcommand = cmd;}

After registering the volume command in the Mcommands container, the purpose is to be frameworklisterer when the command is received from Slocketlistener.

The distribution is judged by the command in Mcommands, and the corresponding command execution class is called.



Three: Commandlistener operation

The role of Commandlistener, simply to communicate framwork and Vold, I draw a simple structure diagram, the general operation is as follows:




Turn on Commandlistener monitor Cl->startlistener ()

Both Commandlistener and Frameworklistener did not override this method, calling the parent class SocketListener directly:

int Socketlistener::startlistener () {if (!msocketname && msock = =-1) {Sloge ("Failed to start unbound        Listener ");        errno = EINVAL;    return-1; } else if (msocketname) {if ((Msock = Android_get_control_socket (msocketname)) < 0) {//Get socket file descriptor, here is get Vold The sloge of this socket ("Obtaining file Descriptor socket '%s ' failed:%s", Msocketname, Strerror (errno            ));        return-1;    } slogv ("Got Msock =%d for%s", Msock, Msocketname);        } if (Mlisten && Listen (Msock, 4) < 0) {Sloge ("Unable to listen on socket (%s)", Strerror (errno));    return-1;    } else if (!mlisten)//Whether the socket mclients->push_back is normally monitored (New socketclient (Msock, False, Musecmdnum));        if (pipe (mctrlpipe)) {//new pipe, save file Descriptor to array sloge ("Pipe failed (%s)", Strerror (errno));    return-1; } if (Pthread_create (&mthread, NULL, Socketlistener::threadstart, this)) {//Open a thread to process Sloge ("Pthread_create (%s) ", Strerror (errno));    return-1; } return 0;}

A new thread has been opened for listening:

void *socketlistener::threadstart (void *obj) {    SocketListener *me = Reinterpret_cast<socketlistener *> (obj) ,//threadstart is a static function, the above thread is created by the time this is passed, here need to convert a bit bit of the SocketListener pointer    me->runlistener ();// SocketListener the real execution function    pthread_exit (NULL);    return NULL;}

The following is the listener processing of the socket:

void Socketlistener::runlistener () {socketclientcollection *pendinglist = new Socketclientcollection ();//        Staging mclients in Socketclient while (1) {Socketclientcollection::iterator it;        Fd_set Read_fds;        int rc = 0;        int max =-1;            Fd_zero (&read_fds);//Clear File Description descriptor Read_fds if (mlisten) {max = Msock; Fd_set (Msock, &read_fds);//If you are listening properly, add the previously obtained Vold file descriptor to} fd_set (Mctrlpipe[0], &read_fds);//Add pipe to read        Fetch file descriptor if (Mctrlpipe[0] > max) max = mctrlpipe[0]; Pthread_mutex_lock (&mclientslock);//locking operation, multithreading security for (it = Mclients->begin (); It! = Mclients->end (); ++it)            {//Traversal mclients, get FD added to Read_fds int fd = (*it)->getsocket ();            Fd_set (FD, &read_fds);        if (FD > Max) max = FD; } pthread_mutex_unlock (&mclientslock);//Unlock SLOGV ("mlisten=%d, max=%d, msocketname=%s", Mlisten, Max, MSo Cketname);//linux underSocket programming Select, here to detect whether the Read_fds collection is readable, that is, there is no data, no data file descriptor will be removed from the Read_fds, where the select set time Out is null, blocking operation, until read                _fds the descriptor in the collection is changed if (rc = select (Max + 1, &read_fds, NULL, NULL, NULL)) < 0) {if (errno = = eintr)            Continue            Sloge ("Select failed (%s) mlisten=%d, max=%d", Strerror (errno), Mlisten, Max);            Sleep (1);        Continue        } else if (!RC) continue;        if (Fd_isset (mctrlpipe[0], &read_fds))//If the anonymous pipe has data readable, exit the break; if (Mlisten && fd_isset (Msock, &read_fds)) {//If it is normal to listen for Mlisten to True, then msock this descriptor has readable data, create a link,            The new asynchronous processing Socketclient is added to the Mclients container, where the Msock is vold the descriptor of the socket struct SOCKADDR addr;            Socklen_t Alen;            int C;                do {alen = sizeof (addr);                c = Accept (Msock, &addr, &alen);            SLOGV ("%s got%d from accept", Msocketname, C);       } while (c < 0 && errno = = eintr);     if (c < 0) {Sloge ("Accept failed (%s)", Strerror (errno));                Sleep (1);            Continue            } pthread_mutex_lock (&mclientslock);            Mclients->push_back (New Socketclient (C, True, Musecmdnum));        Pthread_mutex_unlock (&mclientslock);        }/* ADD all active clients to the pending list first */Pendinglist->clear ();        Pthread_mutex_lock (&mclientslock);  for (it = Mclients->begin (); it = Mclients->end (); ++it) {//Add the client with the requested link above to the Pendinglist container, followed by int            FD = (*it)->getsocket ();            if (Fd_isset (FD, &read_fds)) {pendinglist->push_back (*it);        }} pthread_mutex_unlock (&mclientslock); /* Process the pending list, since it is owned by the thread, * There are no need to lock it */while (!pend  Inglist->empty ()) {//Traversal processing/* Pop The first item from the list */          it = Pendinglist->begin ();            socketclient* C = *it;            Pendinglist->erase (IT);            /* Process It, if False is returned and we sockets is * connection-based, remove and destroy it */ if (!ondataavailable (c) && Mlisten) {//Call to Frameworklistener in ondataavailable processing socket Event/* Remove                The client from our array */SLOGV ("Going to zap%d for%s", C->getsocket (), msocketname);                Pthread_mutex_lock (&mclientslock);                        for (it = Mclients->begin (); It! = Mclients->end (); ++it) {if (*it = = c) {                    Mclients->erase (it);//After processing is complete, remove this socketclient break from the container;                }} pthread_mutex_unlock (&mclientslock);            /* Remove Our reference to the client */C->decref (); }}} delete pendinglist;}

This function is the core of SocketListener, the real processing function is ondataavailable, this is pure virtual function,/system/core/include/sysutils/ SocketListener.h:

    virtual bool ondataavailable (socketclient *c) = 0;

In its sub-class FrameworkListener.cppImplemented in:

BOOL Frameworklistener::ondataavailable (socketclient *c) {    char buffer[255];    int Len;    Len = Temp_failure_retry (Read (C->getsocket (), buffer, sizeof (buffer)));//Read socket contents are saved to buffer    if (Len < 0) { C4/>sloge ("Read () failed (%s)", Strerror (errno));        return false;    } else if (!len)        return false;    int offset = 0;    int i;    for (i = 0; i < len; i++) {        if (buffer[i] = = ' + ') {//one string at a time            */* Important:dispatchcommand () expects a zer o-terminated String *            /Dispatchcommand (c, buffer + offset);            offset = i + 1;        }    }    return true;}

Invoke the same command execution function Dispatchcommand

void Frameworklistener::d ispatchcommand (socketclient *cli, char *data) {    frameworkcommandcollection::iterator i;    int argc = 0;    Char *argv[frameworklistener::cmd_args_max];    Char tmp[255];...//parse to determine command buffer for    (i = Mcommands->begin (); I! = Mcommands->end (); ++i) {// The Frameworkcommand container        frameworkcommand *c = *i before the register to Frameworklistener is traversed;        if (!strcmp (Argv[0], C->getcommand ())) {//Where there are registered "Volume", if this is the command at the beginning of the Volume, then call, Volume constructed when the parent class Frameworkcommand in the RunCommand function            if (C->runcommand (CLI, argc, argv)) {                SLOGW ("Handler"% S ' Error (%s) ", C->getcommand (), strerror (errno));            }            goto out;}}    }


At the same time/system/core/include/sysutils/frameworkcommand.h:

    virtual int RunCommand (socketclient *c, int argc, char **argv) = 0;

Implementation in subclasses, or volume this runcommand as an example/system/vold/commandlistener.cpp:


int Commandlistener::volumecmd::runcommand (socketclient *cli,                                                      int argc, char **argv) {    Dumpargs (argc, argv, 1 );    if (ARGC < 2) {        cli->sendmsg (responsecode::commandsyntaxerror, "Missing Argument", false);        return 0;    }    Volumemanager *VM = Volumemanager::instance ();//Gets the Volumemanager instance that already exists ... else if (!strcmp (argv[1], "mount")) {// Determine the command content        if (argc! = 3) {            cli->sendmsg (responsecode::commandsyntaxerror, "Usage:volume Mount <path& gt; ", false);            return 0;        }        rc = Vm->mountvolume (argv[2]),//to Volumemanager to operate the volume    } ...}


The analysis of the commandlistener here, the main is how to receive the socket, the execution of the corresponding command, and finally how to pass to Volumemanager, with the upper Mountservice interactive follow-up analysis, Initialization of subsequent analysis Volumemanager!





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.