<!-- @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 */

}

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. GitHub 标星 2.5K+!教你通过玩游戏的方式学习 VIM!
  3. 如何在后台运行Linux命令?
  4. No.11 使用firewall配置的防火墙策略的生效模式
  5. Android(安卓)点击文字实现跳转
  6. [Android]使用RecyclerView替代ListView(三)
  7. andriod 获得机型信息
  8. 安卓布局应用学习代码附带效果图
  9. Android(安卓)Volley

随机推荐

  1. SQL Server成功与服务器建立连接但是在登
  2. 用注解编写创建表的SQL语句
  3. SqlServer查询和Kill进程死锁的语句
  4. SQL server 表数据改变触发发送邮件的方
  5. 在Sql Server中调用外部EXE执行程序引发
  6. 深入浅析SQL封装、多态与重载
  7. SQL Server 数据库分离与附加 就这么简单
  8. 详解DB2 sqlstate 57016 SQLCODE=-668 原
  9. SQL Server实现split函数分割字符串功能
  10. SQL Server实现将特定字符串拆分并进行插