Android培训班(30)
<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } -->
在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 */
}