Android disk management-Vold source code analysis (3)

Source: Internet
Author: User

Author: gzshun. Original Works. Reprinted, please indicate the source!


The netlinkmanager class is responsible for managing uevent events that capture the kernel. netlink socket is used here.

Netlink concept:
Netlink socket is a special inter-process communication (IPC) used to implement communication between user processes and kernel processes. It is also the most common interface for network applications to communicate with the kernel. Netlink sockets can be created using the standard socket APIs. Socket (), BIND (), sendmsg (), recvmsg () and close () are easily applied to Netlink.
Socket. Netlink is included in the header file Linux/Netlink. h.
Generally, the application layer does not use the Netlink socket.

In the main function in the main. cpp file, there is a preparation job to enable the thread that listens to the uevent event of the kernel. The source code is as follows:

if (nm->start()) {      SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));      exit(1);  }  

Nm is an object instantiated by the netlinkmanager class. The following is the source code of the START () function:

/*************************************** **************************************** * *** File: system/vold/netlinkmanager. CPP ** the initialization of some of the following sockets is similar to that of TCP/UDP on the Linux application layer. **************************************** **************************************** **/INT netlinkmanager:: Start () {struct sockaddr_nl nladdr; int SZ = 64*1024; memset (& nladdr, 0, sizeof (nladdr); nladdr. nl_family = af_netlink; nladdr. nl_pid = getpid (); nladdr. nl_groups = 0 xffffffff; If (msock = socket (pf_netlink, sock_dgram, netlink_kobject_uevent) <0) {sloge ("unable to create uevent socket: % S ", strerror (errno); Return-1;} If (setsockopt (msock, sol_socket, so_rcvbufforce, & SZ, sizeof (sz) <0) {sloge ("unable to set uevent socket options: % s", strerror (errno); Return-1 ;}if (BIND (msock, (struct sockaddr *) & nladdr, sizeof (nladdr) <0) {sloge ("unable to bind uevent socket: % s", strerror (errno); Return-1 ;} /*************************************** ****************************** * ************* Here, we first describe the inheritance relationship of the netlinkhandler class: ** netlinkhandler --> netlinklistener --> socketlistener (parent class) ** the START () function of the netlinkhandler class calls the socketlistener: startlistener () function. The source code is as follows. **************************************** **************************************** **/Mhandler = new netlinkhandler (msock ); if (mhandler-> Start () {sloge ("unable to start netlinkhandler: % s", strerror (errno); Return-1;} return 0 ;} /*************************************** **************************************** * *** file: system/vold/netlinkhandler. CPP ** this function uses the this pointer to call its own startlistener function. You can find that in NETL Inkhandler does not have the ** startlistener () function. This function is its parent class function socketlistener: startlistener; **************************************** **************************************** **/INT netlinkhandler:: Start () {return this-> startlistener ();} /*************************************** **************************************** * *** file: system/CORE/libsysutils/src/socketlistener. CPP ** the following function involves other aspects, not in vold. **************************************** **************************************** **/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) {sloge ("obtaining file descriptor socket '% s' failed: % s", msocketname, strerror (errno )); return-1 ;}} if (mlisten & listen (msock, 4) <0) {sloge ("unable to listen on socket (% s )", strerror (errno); Return-1 ;} Else if (! Mlisten) mclients-> push_back (New socketclient (msock); If (pipe (mctrlpipe) {sloge ("pipe failed (% s)", strerror (errno )); return-1 ;} /*************************************** **************************************** * ***** this function enables a listening thread. **************************************** **************************************** **/If (pthread_create (& mthread, null, socketlistener: threadstart, this) {sloge ("pthread_create (% s)", strerror (errno); Return-1;} return 0 ;} /*************************************** **************************************** * ***** this thread function is declared as a static function in the class: static void * threadstart (void * OBJ); ** therefore, you cannot call this pointer to point to your own function. The createfunction of the ead_create thread is used to pass ** a parameter and pass this pointer to it. ** here, the reinterpret_cast operator is used to process conversions between irrelevant types, ** it generates a new value, which has exactly the same bit as the original parameter (expressoin. **************************************** **************************************** **/Void * socketlistener:: threadstart (void * OBJ) {socketlistener * Me = reinterpret_cast <socketlistener *> (OBJ); me-> runlistener (); pthread_exit (null); return NULL ;} /*************************************** **************************************** * ***** this function is the real processing function, the select set, combined with the fd_set struct, can be used to determine whether the socket has the ** readable information. If not, return immediately without blocking. ** The MPs queue is used to determine whether the read end of the socket is readable. **************************************** **************************************** **/Void socketlistener:: runlistener () {While (1) {socketclientcollection: iterator it; fd_set read_fds; int rc = 0; int max = 0; fd_zero (& read_fds); If (mlisten) {max = msock; fd_set (msock, & read_fds);} fd_set (mctrlpipe [0], & read_fds); If (mctrlpipe [0]> MAX) max = mctrlpipe [0]; pthread_mutex_lock (& mclientslock); f Or (IT = mclients-> begin (); it! = Mclients-> end (); ++ it) {fd_set (* It)-> getsocket (), & read_fds); If (* It) -> getsocket ()> MAX) max = (* It)-> getsocket ();} pthread_mutex_unlock (& mclientslock); If (rc = select (MAX + 1, & read_fds, null) <0) {sloge ("select failed (% s)", strerror (errno); sleep (1); continue ;} else if (! RC) continue; If (fd_isset (mctrlpipe [0], & read_fds) break; If (mlisten & fd_isset (msock, & read_fds) {struct sockaddr ADDR; socklen_t Alen = sizeof (ADDR); int C; If (C = accept (msock, & ADDR, & Alen) <0) {sloge ("Accept failed (% s) ", strerror (errno); sleep (1); continue;} pthread_mutex_lock (& mclientslock); mclients-> push_back (New socketclient (c )); pthread_mutex_unlock (& mclientslock);} do {pt Hread_mutex_lock (& mclientslock); For (IT = mclients-> begin (); it! = Mclients-> end (); ++ it) {int FD = (* It)-> getsocket (); If (fd_isset (FD, & read_fds )) {pthread_mutex_unlock (& mclientslock ); /*************************************** **************************************** * *** ondataavailable is a pure virtual function declared by the socketlistener class, the netlinklistener subclass implements the ** ondataavailable function, which calls the onevent function of the netlinkhandler class. This function is a pure virtual function defined in the ** netlinklistener class, implemented in the netlinkhandler class of vold. **************************************** **************************************** **/If (! Ondataavailable (* It) {close (FD); pthread_mutex_lock (& mclientslock); Delete * it; it = mclients-> erase (it); pthread_mutex_unlock (& mclientslock );} fd_clr (FD, & read_fds); Continue ;}} pthread_mutex_unlock (& mclientslock) ;}while (0 );}} /*************************************** **************************************** * *** file: system/CORE/libsysutils/src/netlinklistener. CPP ** this function is used to process uevent events in the kernel and then call Use the onevent function to let the onevent function capture the information of these events. **************************************** **************************************** **/Bool netlinklistener:: ondataavailable (socketclient * cli) {int socket = cli-> getsocket (); int count; If (COUNT = Recv (socket, mbuffer, sizeof (mbuffer), 0 )) <0) {sloge ("Recv failed (% s)", strerror (errno); Return false;} netlinkevent * EVT = new netlinkevent (); If (! EVT-> decode (mbuffer, count) {sloge ("error decoding netlinkevent"); goto out;}/* next article introduces this function */onevent (EVT); out: delete EVT; return true ;}
Related Article

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.