【转】 android vold浅析(1)

(2011-11-29 17:41:58)

标签:

android

杂谈

vold的全称是volume daemon。实际上是负责完成系统的CDROM,

USB大容量存储,MMC卡等扩展存储的挂载任务自动完成的守护进程。它提供的主要特点是支持这些存储外设的热插拔。这里有GNU/Linux

vold的介绍[http://vold.sourceforge.net/]。在Android上的这个vold系统和GNU/Linux的之间存在很大的差异,这里我们主要是分析Android上的vold系统的处理过程。

Vold处理过程大致分为三步:

1.创建链接:

vold作为一个守护进程,一方面接受驱动的信息,并把信息传给应用层;另一方面接受上层的命令并完成相应。所以这里的链接一共有两条:

(1)vold socket: 负责vold与应用层的信息传递;

(2)访问udev的socket: 负责vold与底层的信息传递;

这两个链接都是在进程的一开始完成创建的。

2.引导:

这里主要是在vold启动时,对现有外设存储设备的处理。首先,要加载并解析vold.conf,

并检查挂载点是否已经被挂载(注:这里检查挂载点的用意不是很清楚!); 其次,执行MMC卡挂载;

最后,处理USB大容量存储。

3.事件处理:

这里通过对两个链接的监听,完成对动态事件的处理,以及对上层应用操作的响应。

我们分析具体的代码

makefile文件位于/system/vold文件夹下的Android.mk

入口函数在main.cpp中

int main() {

VolumeManager *vm;

CommandListener *cl;

NetlinkManager *nm;

SLOGI("Vold 2.1 (the revenge) firing up");

mkdir("/dev/block/vold", 0755);

if (!(vm = VolumeManager::Instance())) {

SLOGE("Unable to create VolumeManager");

exit(1);

};

//创建一个VolumeManager实例,具体的构造函数位于文件VolumeManager.cpp中

if (!(nm = NetlinkManager::Instance())) {

SLOGE("Unable to create NetlinkManager");

exit(1);

};

//实例化一个NetlinkManager对象,具体的构造函数位于文件NetlinkManager.cpp中

cl = new CommandListener();

**************************************************

**********************

//构造一个CommandListener对象,这个类定义在文件CommandListener.h中,继承了类FrameworkListener,这个类定义在sysutils/FrameworkListener.h中

//这个类又继承了类SocketListener,这个类定义在文件SocketListener.h中,我们看文件/system/core/libsysutils/src/SocketListener.cpp

//SocketListener::SocketListener(const char *socketName, bool

listen) {

mListen = listen;

mSocketName = socketName;

mSock = -1;

pthread_mutex_init(&mClientsLock, NULL);

mClients = new SocketClientCollection();

//typedef android::List

*> SocketClientCollection;

SocketClientCollection是一个SocketClient类对象的集合

} */

//

//文件/system/core/libsysutils/src/FrameworkListener.cpp中定义了FrameworkListener类的构造函数

FrameworkListener::FrameworkListener(const char *socketName)

:

SocketListener(socketName, true) {

mCommands = new FrameworkCommandCollection();

//typedef android::List

*> FrameworkCommandCollection;

} */

//回头我们再看看CommandListener的构造函数

CommandListener::CommandListener() :

FrameworkListener("vold") {

registerCmd(new DumpCmd());

registerCmd(new VolumeCmd());

registerCmd(new AsecCmd());

registerCmd(new ShareCmd());

registerCmd(new StorageCmd());

registerCmd(new XwarpCmd());

} */

//这里会调用其继承类的protected成员函数registerCmd,其参数是一个指向类FrameworkCommand的指针。类CommandListener包含几个私有的内部类class

DumpCmd : public VoldCommand

// class VolumeCmd : public VoldCommand

class ShareCmd : public VoldCommand

class AsecCmd : public VoldCommand

class StorageCmd : public VoldCommand

class XwarpCmd : public VoldCommand

我们分析如何实例化一个DumpCmd

CommandListener::DumpCmd::DumpCmd() :

VoldCommand("dump") {

}

其父类在文件system/vold/VoldCommand.cpp中

VoldCommand::VoldCommand(const char *cmd) :

FrameworkCommand(cmd) {

}

其父类FrameworkCommand::FrameworkCommand(const char *cmd) {

mCommand = cmd;

}

同理创建VolumeCmd, AsecCmd, ShareCmd, StorageCmd, XwarpCmd

其mCommand私有成员分别取值为 dump, volume, asec, share, storage,

xwarp

我们看看怎么注册指令的

void FrameworkListener::registerCmd(FrameworkCommand *cmd)

{

mCommands->push_back(cmd);

}

mCommands指向FrameworkCommandCollection

而FrameworkCommandCollection是一个包含FrameworkCommand指针的链表

typedef android::List

*> FrameworkCommandCollection

因此这里是将创建的FrameworkCommand指针对象压入链表存储起来

**************************************************

*************************

vm->setBroadcaster((SocketListener *) cl);

nm->setBroadcaster((SocketListener *) cl);

if (vm->start()) {

SLOGE("Unable to start VolumeManager (%s)",

strerror(errno));

exit(1);

}

//vm->start()始终返回0,什么都不做

if (process_config(vm)) {

SLOGE("Error reading configuration (%s)... continuing anyways",

strerror(errno));

}

if (nm->start()) {

SLOGE("Unable to start NetlinkManager (%s)",

strerror(errno));

exit(1);

}

++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++

nm->start()会调用NetlinkManager类的start()方法

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 = 0xffffffff;

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;

}

//创建一个socket用于内核空间和用户空间的异步通信,监控系统的hotplug事件

mHandler = new NetlinkHandler(mSock);

if (mHandler->start()) {

SLOGE("Unable to start NetlinkHandler: %s",

strerror(errno));

return -1;

}

**************************************************

****************************

线程真正执行的函数:mListen成员用来判定是否监听套接字

Netlink套接字属于udp套接字,非监听套接字,该函数的主要功能体现在,如果该套接字有数据到来,就调用相关函数读取数据。android工程师

void SocketListener::runListener() {

while(1) {//无线循环,一直监听

SocketClientCollection::iterator it;

fd_set read_fds;

int rc = 0;

int max = 0;

FD_ZERO(&read_fds); //清空文件描述符集read_fds

if (mListen) {

max = mSock;

FD_SET(mSock, &read_fds); //添加文件描述符到文件描述符集read_fds

}

FD_SET(mCtrlPipe[0], &read_fds);

//添加管道的读取端文件描述符到read_fds

if (mCtrlPipe[0] > max)

max = mCtrlPipe[0];

pthread_mutex_lock(&mClientsLock);//对容器mClients的操作需要加锁

for (it = mClients->begin(); it !=

mClients->end(); ++it) {

FD_SET((*it)->getSocket(), &read_fds);

//遍历容器mClients的所有成员,调用内联函数getSocket()获取文件描述符,

并添加到文件描述符集read_fds

if ((*it)->getSocket() > max)

max = (*it)->getSocket();

}

pthread_mutex_unlock(&mClientsLock);

if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL))

< 0) { // 等待文件描述符中某一文件描述符或者说socket有数据到来

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)

{ //接收链接请求,建立连接,如果成功c即为建立链接后的数据交换套接字,

将其添加到mClient容器;

SLOGE("accept failed (%s)", strerror(errno));

sleep(1);

continue;

}

pthread_mutex_lock(&mClientsLock);

mClients->push_back(new SocketClient(c));

pthread_mutex_unlock(&mClientsLock);

}

do {//非监听套接字处理

pthread_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);

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);

}

}

分享:

喜欢

0

赠金笔

加载中,请稍候......

评论加载中,请稍候...

发评论

登录名: 密码: 找回密码 注册记住登录状态

昵   称:

评论并转载此博文

发评论

以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

android vold 挂载读写,【转】 android vold浅析(1)相关推荐

  1. android vold 挂载读写,Android——Vold磁盘挂载_主体构建(一)

    这段时间为了把mmc的一个block当成sdcard内置,学习了下android的vold磁盘挂载模块,记录一下(android 4.2.2). 一:Vold的编译及启动 vold的源码位置在andr ...

  2. android u盘读写权限,Android 外部SD卡/U盘无法写入解决方法(需要root)

    但今天我遇到一个问题,就是我买了只TF卡装上去以后发现:一般程序无法写入TF卡,而系统自带的文件工具能够写入. 什么原因呢? 好在这个平板已经是root的,马上调出rootexplorer文件管理器查 ...

  3. android跨进程读写内存,Android 跨进程内存泄露

    内存泄露的检测和修复一直是每个APP的重点和难点,也有很多文章讲述了如何检测和修复.本篇文章 结合最近开发的项目遇到的实例,讲述下Android Binder导致的内存泄露的一个案例. 发现问题 参与 ...

  4. android zip文件读写,【Android】Zip文件解压方法

    android中zip文件解压 public class ZipUtil { /** * 解压到指定路径 * * @param inputStream * @param outPathString * ...

  5. Android 9.0 Vold 挂载流程分析

    在Android 系统中所有的热插拔设备都是通过Vold 进程挂载的.通过kernel–>vold–>StorageManagerService这样的架构去逐级上报热插拔事件. 一.Vol ...

  6. android mnt asec,通过adb修改Android etc下的vold.fstab,调测vold.fstab

    一.修改vold.fstab /etc link到system/etc,需要修改/etc/vold.fstab,但vold.fstab为只读,在命令行下无法修改 使用adb来实现更改的目的,步骤: 1 ...

  7. android挂载usb设备,android usb挂载分析---MountService启动

    在android usb挂载分析----vold启动,我们的vold模块已经启动了,通信的机制也已经建立起来了,接下来我们分析一下MountService的启动,也就是我们FrameWork层的启动, ...

  8. android usb挂载分析---MountService启动

    在android usb挂载分析----vold启动,我们的vold模块已经启动了,通信的机制也已经建立起来了,接下来我们分析一下MountService的启动,也就是我们FrameWork层的启动, ...

  9. 使用RootTools实现对Android系统文件的读写

    使用RootTools实现对Android系统文件的读写  作者:          蒋东国  时间:     2016年11月2日 星期三  应用来源:     hqt APP(测试机型:华为荣耀4 ...

最新文章

  1. php 如何判断是否搜索出结果,搜索PHP - 如何调出搜索框没有结果
  2. 1.7 Python基础知识 - 模块初识
  3. cygwin下的gcc-4.7.1编译心得
  4. python多标签分类_如何通过sklearn实现多标签分类?
  5. hp打印机怎么连接电脑_hp打印机驱动怎么安装 惠普打印机驱动程序安装方法【详解】...
  6. Vivado入门创建工程之----流水灯
  7. PostScript —— 一种编程语言
  8. 攻防世界 pwn 二进制漏洞简单题练习区 答题(1-10题解)
  9. 【学习】03 淘宝爬虫-使用selenium采集关键词为电动车的数据
  10. 大数据可能带来三方面的伦理挑战
  11. 操作高通QXDM5,点击重置按钮出现报错
  12. Remoting技术
  13. 8.0强行转换后变成了7_南方Cass软件坐标转换方法!
  14. 小米6无限重启无服务器,网友投诉小米手机无限重启 官方客服已回复
  15. 【数据分析认知课(一):数据分析思维观】——读后感
  16. App登录方式和测试重点总结
  17. JAVA集合,TreeMap排序
  18. package.josn中^和~的区别
  19. IntellIdea+SpingMVC简单项目
  20. 通过配置文件修改PenMount中操作模式为Touch

热门文章

  1. 【英语】如何在一个星期之内学好英语?奥利给!
  2. rxjava 二:简单理解Disposable
  3. python求移动平均_如何用NumPy计算移动平均值?
  4. 姑娘在远方 - 柯柯柯啊
  5. c语言需要的软件,需要C语言的需要什么工具软件
  6. 软银CEO孙正义:愿景基金已经投出700亿美元
  7. 算法的暴力美学之贪心算法
  8. 数学是人与自然之间沟通很好的语言
  9. 微信小程序中清除定时器
  10. nuxt01-nuxt介绍