在init.rc文件里加载的服务


1、在init.rc文件里第一个初始化的服务是sh服务,如下:

## Daemon processes to be run by init.
##
service console /system/bin/sh
console
 
sh服务是控制台服务,其实它是从NetBSD移植过来的,因此它的命令也是比较有限的,不过作为嵌入式系统,使用shell的机会不多。
sh服务的代码在目录:Android-2.0/system/core/sh
sh服务使用flex工具生成词法分析代码,使用bison生成语法分析代码。
 
下面来分析这个服务主要代码,先从main函数开始,如下:
int
main(int argc, char **argv)
{
struct jmploc jmploc;
struct stackmark smark;
volatile int state;
char *shinit;
 
下面这行代码,就是我为了加入调试使用的。
/* caijs add debug */
out2str("caijs add debug/n");
 
#if PROFILE
monitor(4, etext, profile_buf, sizeof profile_buf, 50);
#endif
state = 0;
 
下面这段代码设置执行命令异常的处理。
if (setjmp(jmploc.loc)) {
/*
* When a shell procedure is executed, we raise the
* exception EXSHELLPROC to clean up before executing
* the shell procedure.
*/
switch (exception) {
case EXSHELLPROC:
rootpid = getpid();
rootshell = 1;
minusc = NULL;
state = 3;
break;
 
case EXEXEC:
exitstatus = exerrno;
break;
 
case EXERROR:
exitstatus = 2;
break;
 
default:
break;
}
 
if (exception != EXSHELLPROC) {
if (state == 0 || iflag == 0 || ! rootshell)
exitshell(exitstatus);
}
reset();
if (exception == EXINT
#if ATTY
&& (! attyset() || equal(termval(), "emacs"))
#endif
) {
out2c('/n');
flushout(&errout);
}
popstackmark(&smark);
FORCEINTON; /* enable interrupts */
if (state == 1)
goto state1;
else if (state == 2)
goto state2;
else if (state == 3)
goto state3;
else
goto state4;
}
handler = &jmploc;
#ifdef DEBUG
#if DEBUG == 2
debug = 1;
#endif
opentrace();
trputs("Shell args: "); trargs(argv);
#endif


rootpid = getpid();
这行代码通过调用函数getpid 获取进程标识。
 
rootshell = 1;
init();
初始化内部支持的命令。


setstackmark(&smark);


procargs(argc, argv);
这行代码根据命令行进行处理。


下面代码读取配置参数。
if (argv[0] && argv[0][0] == '-') {
state = 1;
read_profile("/etc/profile");
state1:
state = 2;
read_profile(".profile");
}
state2:
state = 3;
if (getuid() == geteuid() && getgid() == getegid()) {
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '/0') {
state = 3;
read_profile(shinit);
}
}
state3:
state = 4;
if (sflag == 0 || minusc) {
static int sigs[] = {
SIGINT, SIGQUIT, SIGHUP,
#ifdef SIGTSTP
SIGTSTP,
#endif
SIGPIPE
};
#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
int i;
 
for (i = 0; i < SIGSSIZE; i++)
setsignal(sigs[i], 0);
}
 
if (minusc)
evalstring(minusc, 0);
 
 
下面的代码调用函数cmdloop 来进入shell的命令处理。
if (sflag || minusc == NULL) {
state4: /* XXX ??? - why isn't this before the "if" statement */
cmdloop(1);
}
#if PROFILE
monitor(0);
#endif
 
最后退出shell的执行。
exitshell(exitstatus);
/* NOTREACHED */
}


2、adbd 服务
# adbd is controlled by the persist.service.adb.enable system property
service adbd /sbin/adbd
disabled
 
adbd服务的代码在目录:Android-2.0/system/core/adb
adbd服务使用c语言实现,它不但可以在虚拟机里运行,也可以在实际的设备里运行。adbd服务是adb调试系统中的一部分,整个adb调试系统包括有三部分:手机运行的adbd服务、PC运行的服务器、PC运行的客户端。当android启动时,就运行adbd服务,创建一个调试端口,这样就可以让开发机器上的服务器连接过来,通过这个连接就可以发送调试信息给服务器,也可以接收到外面发送过来的调试命令。
 
先来分析编译文件Android.mk,adbd相关内容如下:
# adbd device daemon
# =========================================================
 
# build adbd in all non-simulator builds
BUILD_ADBD := false
当设置为BUILD_ADBD为true时,就是编译运行在模拟器里的调试服务,否则就是运行到真实机器里的调试服务。 
ifneq ($(TARGET_SIMULATOR),true)
BUILD_ADBD := true
endif
 
如果运行在linux里模拟器,就需要使用下面的判断。
# build adbd for the Linux simulator build
# so we can use it to test the adb USB gadget driver on x86
#ifeq ($(HOST_OS),linux)
# BUILD_ADBD := true
#endif


ifeq ($(BUILD_ADBD),true)
include $(CLEAR_VARS)
 
LOCAL_SRC_FILES := /
adb.c /
fdevent.c /
transport.c /
transport_local.c /
transport_usb.c /
sockets.c /
services.c /
file_sync_service.c /
jdwp_service.c /
framebuffer_service.c /
remount_service.c /
usb_linux_client.c /
log_service.c /
utils.c
 
LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
 
# TODO: This should probably be board specific, whether or not the kernel has
# the gadget driver; rather than relying on the architecture type.
ifeq ($(TARGET_ARCH),arm)
LOCAL_CFLAGS += -DANDROID_GADGET=1
endif
 
LOCAL_MODULE := adbd
 
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
 
如果在模拟器里运行,就需要编译为线程模式,否则就需要连接静态库的方式。
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_STATIC_LIBRARIES := libcutils
LOCAL_LDLIBS += -lpthread
include $(BUILD_HOST_EXECUTABLE)
else
LOCAL_STATIC_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
endif


接着来分析程序入口函数main处理过程,它的代码如下:
int main(int argc, char **argv)
{


adb_trace_init();
这行代码主要获取环境变量,用来判断到底输出什么样信息。
 
下面这段代码根据编译选项来决定编译为PC机里的服务,还是设备运行的服务。
#if ADB_HOST
adb_sysdeps_init();
return adb_commandline(argc - 1, argv + 1);
这里是选择编译为PC里的服务器。
 
#else
 
这段是选择为设备里的服务进程。
if((argc > 1) && (!strcmp(argv[1],"recovery"))) {
adb_device_banner = "recovery";
recovery_mode = 1;
}
上面这段用来判断是否恢复模式。


start_device_log();
这行代码开始输出调试LOG。
 
return adb_main(0);
这行代码是进入adb服务进程处理。
 
#endif
}


3、servicemanager
service servicemanager /system/bin/servicemanager
user system
critical
onrestart restart zygote
onrestart restart media
servicemanager服务的代码在目录:
Android-2.0/frameworks/base/cmds/servicemanager
servicemanager服务的作用主要是服务管理,所谓的服务管理其实就是获取服务、检查服务、添加服务、枚举所有服务。服务管理器是一个容器管理器,方便服务添加、调用和删除。在应用层的程序,都向这个服务管理器获取需要使用的服务,而所有提供服务的程序,都向这个服务器管理器注册自己的服务。服务管理器是应用程序与服务沟通的桥梁。
下面来分析一下main函数的代码如下:
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
这行代码是设置管理器从0开始。
 
bs = binder_open(128*1024);
这行代码是调用binder_open函数打开binder设备,并分配内存空间。


if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s)/n", strerror(errno));
return -1;
}
调用binder_become_context_manager函数设置本服务作为服务管理器。


svcmgr_handle = svcmgr;
这行代码是设置服务管理器处理函数。
 
binder_loop(bs, svcmgr_handler);
这行代码是让服务管理器进入循环地处理服务相关的命令。
 
return 0;
}


4、vold
service vold /system/bin/vold
socket vold stream 0660 root mount
vold服务的代码在目录:
Android-2.0/system/core/vold
vold服务的作用主要是负责完成系统的动态卷管理,比如CDROM、U盘、MMC卡等外存储的管理。当有这外存储设备插入时,就需要监视这种变化,并加载相应的驱动程序,然后报告给系统和应用程序有新存储设备可以使用。
Vold处理过程大致分为三步:
1.创建链接:
在vold作为一个守护进程,一方面接受驱动的信息,并把信息传给应用层;另一方面接受上层的命令并完成相应。所以这里的链接一共有两条:
(1)vold socket: 负责vold与应用层的信息传递;
(2)访问udev的socket: 负责vold与底层的信息传递;
这两个链接都是在进程的一开始完成创建的。
2.引导:
这里主要是在vold启动时,对现有外设存储设备的处理。首先,要加载并解析vold.conf,
并检查挂载点是否已经被挂载; 其次,执行MMC卡挂载; 最后,处理USB大容量存储。
3.事件处理:
这里通过对两个链接的监听,完成对动态事件的处理,以及对上层应用操作的响应。
 
下面来分析一下main函数的代码如下:
int main(int argc, char **argv)
{
int door_sock = -1;
int uevent_sock = -1;
struct sockaddr_nl nladdr;
int uevent_sz = 64 * 1024;
 
LOGI("Android Volume Daemon version %d.%d", ver_major, ver_minor);
 
/*
* Create all the various sockets we'll need
*/
 
// Socket to listen on for incomming framework connections
if ((door_sock = android_get_control_socket(VOLD_SOCKET)) < 0) {
LOGE("Obtaining file descriptor socket '%s' failed: %s",
VOLD_SOCKET, strerror(errno));
exit(1);
}
这段代码是创建一个负责vold与应用层的信息传递的SOCKET。
 
if (listen(door_sock, 4) < 0) {
LOGE("Unable to listen on fd '%d' for socket '%s': %s",
door_sock, VOLD_SOCKET, strerror(errno));
exit(1);
}
 
这里开始监听。
 
mkdir("/dev/block/vold", 0755);
创建相应的设备目录。
 
// Socket to listen on for uevent changes
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
nladdr.nl_groups = 0xffffffff;
 
if ((uevent_sock = socket(PF_NETLINK,
SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
LOGE("Unable to create uevent socket: %s", strerror(errno));
exit(1);
}
这段代码是 负责vold与底层的信息传递的SOCKET。


if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
sizeof(uevent_sz)) < 0) {
LOGE("Unable to set uevent socket options: %s", strerror(errno));
exit(1);
}
 
if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
LOGE("Unable to bind uevent socket: %s", strerror(errno));
exit(1);
}
 
/*
* Bootstrap
*/


bootstrap = 1;
// Volume Manager
volmgr_bootstrap();
 
// SD Card system
mmc_bootstrap();
 
// USB Mass Storage
ums_bootstrap();
 
// Switch
switch_bootstrap();
 
上面这段是在vold启动时,对现有外设存储设备的处理。
 
 
bootstrap = 0;
/*
* Main loop
*/
LOG_VOL("Bootstrapping complete");
while(1) {
fd_set read_fds;
struct timeval to;
int max = 0;
int rc = 0;
 
to.tv_sec = (60 * 60);
to.tv_usec = 0;
 
FD_ZERO(&read_fds);
FD_SET(door_sock, &read_fds);
if (door_sock > max)
max = door_sock;
FD_SET(uevent_sock, &read_fds);
if (uevent_sock > max)
max = uevent_sock;
 
if (fw_sock != -1) {
FD_SET(fw_sock, &read_fds);
if (fw_sock > max)
max = fw_sock;
}
 
if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
LOGE("select() failed (%s)", strerror(errno));
sleep(1);
continue;
}
 
if (!rc) {
continue;
}
 
if (FD_ISSET(door_sock, &read_fds)) {
struct sockaddr addr;
socklen_t alen;
 
alen = sizeof(addr);
 
if (fw_sock != -1) {
LOGE("Dropping duplicate framework connection");
int tmp = accept(door_sock, &addr, &alen);
close(tmp);
continue;
}
 
if ((fw_sock = accept(door_sock, &addr, &alen)) < 0) {
LOGE("Unable to accept framework connection (%s)",
strerror(errno));
}
LOG_VOL("Accepted connection from framework");
if ((rc = volmgr_send_states()) < 0) {
LOGE("Unable to send volmgr status to framework (%d)", rc);
}
}
 
if (FD_ISSET(fw_sock, &read_fds)) {
if ((rc = process_framework_command(fw_sock)) < 0) {
if (rc == -ECONNRESET) {
LOGE("Framework disconnected");
close(fw_sock);
fw_sock = -1;
} else {
LOGE("Error processing framework command (%s)",
strerror(errno));
}
}
}
 
if (FD_ISSET(uevent_sock, &read_fds)) {
if ((rc = process_uevent_message(uevent_sock)) < 0) {
LOGE("Error processing uevent msg (%s)", strerror(errno));
}
}
} // while


}

上面这段代码是进入事件处理。


5、nexus
service nexus /system/bin/nexus
socket nexus stream 0660 root system
disabled


nexus服务的代码在目录:
Android-2.0/system/core/nexus
 
nexus服务主要作用就是监听网络命令,提供网络管理的功能。
下面来分析一下main函数代码,如下:
int main() {
LOGI("Nexus version 0.1 firing up");
 
CommandListener *cl = new CommandListener();
这段代码创建命令监听。
 
NetworkManager *nm;
if (!(nm = NetworkManager::Instance())) {
LOGE("Unable to create NetworkManager");
exit (-1);
};
这段代码创建网络管理器。


nm->setBroadcaster((SocketListener *) cl);
 
nm->attachController(new LoopController(nm->getPropMngr(), nm));
nm->attachController(new TiwlanWifiController(nm->getPropMngr(), nm, "/system/lib/modules/wlan.ko", "wlan", ""));
// nm->attachController(new AndroidL2TPVpnController(nm->getPropMngr(), nm));
nm->attachController(new OpenVpnController(nm->getPropMngr(), nm));
这段代码设置网络监听器。


if (NetworkManager::Instance()->run()) {
LOGE("Unable to Run NetworkManager (%s)", strerror(errno));
exit (1);
}
 
if (cl->startListener()) {
LOGE("Unable to start CommandListener (%s)", strerror(errno));
exit (1);
}
 
// XXX: we'll use the main thread for the NetworkManager eventually
 
while(1) {
sleep(1000);
}
这段代码启动网络监听器,并让网络监听器不断处理命令。
 
 
LOGI("Nexus exiting");
exit(0);
}


6、zygote
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
zygote服务的代码在目录:
Android-2.0/frameworks/base/cmds/app_process
 
zygote服务主要作用就是创建一个服务监听用户的命令,并且根据用户的命令创建应用程序运行。
它的主要入口函数代码如下:
int main(int argc, const char* const argv[])
{
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
 
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
 
AppRuntime runtime;
这里创建JAVA运行库对象。
 
const char *arg;
const char *argv0;
 
argv0 = argv[0];
 
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
 
// Everything up to '--' or first non '-' arg goes to the vm
 
int i = runtime.addVmArguments(argc, argv);
这里添加命令行参数。
 
// Next arg is parent directory
if (i < argc) {
runtime.mParentDir = argv[i++];
}
 
// Next arg is startup classname or "--zygote"
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
setArgv0(argv0, "zygote");
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
这里根据命令行参数来创建JAVA虚拟机,并从 com.android.internal.os.ZygoteInit开始运行,然后启动所有JAVA的服务。
 
} else {
set_process_name(argv0);
 
runtime.mClassName = arg;
 
// Remainder of args get passed to startup class main()
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
 
LOGV("App process is starting with pid=%d, class=%s./n",
getpid(), runtime.getClassName());
runtime.start();
}
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied./n");
app_usage();
return 10;
}
 
}


7、mediaserver
service media /system/bin/mediaserver
user media
group system audio camera graphics inet net_bt net_bt_admin
mediaserver服务的代码在目录:
Android-2.0/frameworks/base/media/mediaserver
 
mediaserver服务是多媒体服务的守护进程,负责多媒体/照相机/音频等三项服务。
它的主要入口函数代码如下:
using namespace android;
 
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
这行代码获取进程状态。
 
sp<IServiceManager> sm = defaultServiceManager();
获取服务管理器。
 
LOGI("ServiceManager: %p", sm.get());
 
AudioFlinger::instantiate();
这行代码创建音频实例。
 
MediaPlayerService::instantiate();
这行代码创建多媒体播放实例。
 
CameraService::instantiate();
这行代码创建照相机实例。
 
AudioPolicyService::instantiate();
 
下面开始启动线程池。
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}


8、bootanimation
service bootanim /system/bin/bootanimation
user graphics
group graphics
disabled
oneshot
bootanimation 服务的代码在目录:
Android-2.0/frameworks/base/cmds/bootanimation
 
bootanimation 服务是开机动画,主要用来加载动画资源。
它的主要入口函数代码如下:
int main(int argc, char** argv)
{
#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
#endif
这段代码设置进程的优先级。
 
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
这行代码从属性里获取是否显示开机动画,如果为1就不显示。
 
int noBootAnimation = atoi(value);
LOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
这段代码判断是否显示开机动画。
 
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
启动开机动画的线程。
 
// create the boot animation object
sp<BootAnimation> boot = new BootAnimation();
创建开机动画对象。
 
 
IPCThreadState::self()->joinThreadPool();
运行开机动画线程。
 
 
}
return 0;
}


9、dbus
service dbus /system/bin/dbus-daemon --system --nofork
socket dbus stream 660 bluetooth bluetooth
user bluetooth
group bluetooth net_bt_admin
dbus服务的代码在目录:
Android-2.0/external/dbus/bus
dbus服务是android使用的一种特殊的进程间通讯系统。它具有面向对象接口的协议,以及应用程序之间互相发现和监视的守护进程。dbus设计用来作为用户与系统服务之间的分隔以及系统服务之间的通讯。因此,dbus通讯安全,但效率有点差。
它的主要入口函数代码如下:
int
main (int argc, char **argv)
{
DBusError error;
DBusString config_file;
DBusString addr_fd;
DBusString pid_fd;
const char *prev_arg;
int print_addr_fd;
int print_pid_fd;
int i;
dbus_bool_t print_address;
dbus_bool_t print_pid;
int force_fork;
 
初始化配置文件/文件句柄/进程ID。
if (!_dbus_string_init (&config_file))
return 1;
 
if (!_dbus_string_init (&addr_fd))
return 1;
 
if (!_dbus_string_init (&pid_fd))
return 1;
 
print_address = FALSE;
print_pid = FALSE;
force_fork = FORK_FOLLOW_CONFIG_FILE;
 
下面分析进程输入的参数。
prev_arg = NULL;
i = 1;
while (i < argc)
{
const char *arg = argv[i];
 
if (strcmp (arg, "--help") == 0 ||
strcmp (arg, "-h") == 0 ||
strcmp (arg, "-?") == 0)
usage ();
else if (strcmp (arg, "--version") == 0)
version ();
else if (strcmp (arg, "--introspect") == 0)
introspect ();
else if (strcmp (arg, "--nofork") == 0)
force_fork = FORK_NEVER;
else if (strcmp (arg, "--fork") == 0)
force_fork = FORK_ALWAYS;
else if (strcmp (arg, "--system") == 0)
{
check_two_config_files (&config_file, "system");
 
if (!_dbus_string_append (&config_file, DBUS_SYSTEM_CONFIG_FILE))
exit (1);
}
else if (strcmp (arg, "--session") == 0)
{
check_two_config_files (&config_file, "session");
 
if (!_dbus_string_append (&config_file, DBUS_SESSION_CONFIG_FILE))
exit (1);
}
else if (strstr (arg, "--config-file=") == arg)
{
const char *file;
 
check_two_config_files (&config_file, "config-file");
 
file = strchr (arg, '=');
++file;
 
if (!_dbus_string_append (&config_file, file))
exit (1);
}
else if (prev_arg &&
strcmp (prev_arg, "--config-file") == 0)
{
check_two_config_files (&config_file, "config-file");
 
if (!_dbus_string_append (&config_file, arg))
exit (1);
}
else if (strcmp (arg, "--config-file") == 0)
; /* wait for next arg */
else if (strstr (arg, "--print-address=") == arg)
{
const char *desc;
 
check_two_addr_descriptors (&addr_fd, "print-address");
 
desc = strchr (arg, '=');
++desc;
 
if (!_dbus_string_append (&addr_fd, desc))
exit (1);
 
print_address = TRUE;
}
else if (prev_arg &&
strcmp (prev_arg, "--print-address") == 0)
{
check_two_addr_descriptors (&addr_fd, "print-address");
 
if (!_dbus_string_append (&addr_fd, arg))
exit (1);
 
print_address = TRUE;
}
else if (strcmp (arg, "--print-address") == 0)
print_address = TRUE; /* and we'll get the next arg if appropriate */
else if (strstr (arg, "--print-pid=") == arg)
{
const char *desc;
 
check_two_pid_descriptors (&pid_fd, "print-pid");
 
desc = strchr (arg, '=');
++desc;
 
if (!_dbus_string_append (&pid_fd, desc))
exit (1);
 
print_pid = TRUE;
}
else if (prev_arg &&
strcmp (prev_arg, "--print-pid") == 0)
{
check_two_pid_descriptors (&pid_fd, "print-pid");
 
if (!_dbus_string_append (&pid_fd, arg))
exit (1);
 
print_pid = TRUE;
}
else if (strcmp (arg, "--print-pid") == 0)
print_pid = TRUE; /* and we'll get the next arg if appropriate */
else
usage ();
 
prev_arg = arg;
 
++i;
}
 
根据输入的参数进行初始化总线。
if (_dbus_string_get_length (&config_file) == 0)
{
fprintf (stderr, "No configuration file specified./n");
usage ();
}
 
print_addr_fd = -1;
if (print_address)
{
print_addr_fd = 1; /* stdout */
if (_dbus_string_get_length (&addr_fd) > 0)
{
long val;
int end;
if (!_dbus_string_parse_int (&addr_fd, 0, &val, &end) ||
end != _dbus_string_get_length (&addr_fd) ||
val < 0 || val > _DBUS_INT_MAX)
{
fprintf (stderr, "Invalid file descriptor: /"%s/"/n",
_dbus_string_get_const_data (&addr_fd));
exit (1);
}
 
print_addr_fd = val;
}
}
_dbus_string_free (&addr_fd);
 
print_pid_fd = -1;
if (print_pid)
{
print_pid_fd = 1; /* stdout */
if (_dbus_string_get_length (&pid_fd) > 0)
{
long val;
int end;
if (!_dbus_string_parse_int (&pid_fd, 0, &val, &end) ||
end != _dbus_string_get_length (&pid_fd) ||
val < 0 || val > _DBUS_INT_MAX)
{
fprintf (stderr, "Invalid file descriptor: /"%s/"/n",
_dbus_string_get_const_data (&pid_fd));
exit (1);
}
 
print_pid_fd = val;
}
}
_dbus_string_free (&pid_fd);
 
if (!bus_selinux_pre_init ())
{
_dbus_warn ("SELinux pre-initialization failed/n");
exit (1);
}
 
dbus_error_init (&error);
 
注册监视进程的服务函数。
context = bus_context_new (&config_file, force_fork,
print_addr_fd, print_pid_fd,
&error);
_dbus_string_free (&config_file);
if (context == NULL)
{
_dbus_warn ("Failed to start message bus: %s/n",
error.message);
dbus_error_free (&error);
exit (1);
}
 
setup_reload_pipe (bus_context_get_loop (context));
 
_dbus_set_signal_handler (SIGHUP, signal_handler);
_dbus_set_signal_handler (SIGTERM, signal_handler);
#ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX
_dbus_set_signal_handler (SIGIO, signal_handler);
#endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */
 
_dbus_verbose ("We are on D-Bus.../n");
 
进入服务循环。
_dbus_loop_run (bus_context_get_loop (context));
 
bus_context_shutdown (context);
bus_context_unref (context);
bus_selinux_shutdown ();
 
return 0;
}


10、installd
service installd /system/bin/installd
socket installd stream 600 system system
installd 服务的代码在目录:
Android-2.0/frameworks/base/cmds/installd
 
installd服务是提供安装dex文件的服务。
它的主要入口函数代码如下:
int main(const int argc, const char *argv[]) {
char buf[BUFFER_MAX];
struct sockaddr addr;
socklen_t alen;
int lsocket, s, count;
 
创建一个控制的SOCKET。
lsocket = android_get_control_socket(SOCKET_PATH);
if (lsocket < 0) {
LOGE("Failed to get socket from environment: %s/n", strerror(errno));
exit(1);
}
 
监听这个SOCKET。
if (listen(lsocket, 5)) {
LOGE("Listen on socket failed: %s/n", strerror(errno));
exit(1);
}
fcntl(lsocket, F_SETFD, FD_CLOEXEC);
 
循环里处理接收到的SOCKET连接。
 
for (;;) {
alen = sizeof(addr);
s = accept(lsocket, &addr, &alen);
if (s < 0) {
LOGE("Accept failed: %s/n", strerror(errno));
continue;
}
fcntl(s, F_SETFD, FD_CLOEXEC);
 
从新连接里接收到命令并处理。
LOGI("new connection/n");
for (;;) {
unsigned short count;
if (readx(s, &count, sizeof(count))) {
LOGE("failed to read size/n");
break;
}
if ((count < 1) || (count >= BUFFER_MAX)) {
LOGE("invalid size %d/n", count);
break;
}
if (readx(s, buf, count)) {
LOGE("failed to read command/n");
break;
}
buf[count] = 0;
if (execute(s, buf)) break;
}
LOGI("closing connection/n");
close(s);
}
 
return 0;
}


11、keystore 
service keystore /system/bin/keystore /data/misc/keystore
user keystore
group keystore
socket keystore stream 666
keystore服务的代码在目录:
Android-2.0/frameworks/base/cmds/keystore
 
keystore服务是加解密储存键值的服务。它主要作用就是验证应用程序与签名文件是否一致。
它的主要入口函数代码如下:
int main(int argc, char **argv)
{
 
获取加密服务的SOCKET。
int control_socket = android_get_control_socket("keystore");
if (argc < 2) {
LOGE("A directory must be specified!");
return 1;
}
if (chdir(argv[1]) == -1) {
LOGE("chdir: %s: %s", argv[1], strerror(errno));
return 1;
}
if ((the_entropy = open(RANDOM_DEVICE, O_RDONLY)) == -1) {
LOGE("open: %s: %s", RANDOM_DEVICE, strerror(errno));
return 1;
}
 
监听这个服务。
if (listen(control_socket, 3) == -1) {
LOGE("listen: %s", strerror(errno));
return 1;
}
 
signal(SIGPIPE, SIG_IGN);
if (access(MASTER_KEY_FILE, R_OK) == 0) {
state = LOCKED;
}
 
接收到连接。
while ((the_socket = accept(control_socket, NULL, 0)) != -1) {
struct timeval tv = {.tv_sec = 3};
struct ucred cred;
socklen_t size = sizeof(cred);
int8_t request;
 
setsockopt(the_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
setsockopt(the_socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
 
if (getsockopt(the_socket, SOL_SOCKET, SO_PEERCRED, &cred, &size)) {
LOGW("getsockopt: %s", strerror(errno));
} else if (recv_code(&request)) {
 
接收到请求后,就开始进行加密验证处理。
int8_t old_state = state;
int8_t response;
uid = cred.uid;
 
if ((response = process(request)) > 0) {
send_code(response);
response = -response;
}
 
LOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d",
cred.uid, request, -response, old_state, state, retry);
}
close(the_socket);
}
LOGE("accept: %s", strerror(errno));
return 1;

----

源自:http://blog.csdn.net/caimouse

----

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页