在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 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 proc(ProcessState::self());
这行代码获取进程状态。

sp 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 proc(ProcessState::self());
ProcessState::self()->startThreadPool();
启动开机动画的线程。

// create the boot animation object
sp 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

----

你可能感兴趣的:(在init.rc文件里加载的服务)