把busybox移植到android下后想玩玩syslogd,于是先把busybox链接成一个syslogd以方便后续直接敲命令启动:
ln -s busybox syslogd
ls -l
lrwxrwxrwx root root 2013-01-06 19:38 syslogd -> busybox
OK,现在可以启动它了:
1|root@android:/data/data/test # ./syslogd
./syslogd
root@android:/data/data/test #
原以为执行成功了,但ps却发现并没有syslogd进程存在,怪了。于是加上-n参数让其在前台运行,看看会有什么提示:
root@android:/data/data/test # ./syslogd -n
./syslogd -n
syslogd: bind: No such file or directory
原来是绑定失败。接下来就只能通过查代码来进一步排查问题了。
busybox使用的是unix域socket通信的,默认使用的是/dev/log文件来做为socket文件,具体在create_socket函数中实现的:
static NOINLINE int create_socket(void) { 。。。 /* Unlink old /dev/log or object it points to. */ /* (if it exists, bind will fail) */ strcpy(sunx.sun_path, "/dev/log"); dev_log_name = xmalloc_follow_symlinks("/dev/log"); if (dev_log_name) { safe_strncpy(sunx.sun_path, dev_log_name, sizeof(sunx.sun_path)); free(dev_log_name); } 。。。
问题实际上就出在这里了。
因为在我的三星android手机上,本来就存在/dev/log,并且,这里log还是个文件夹,里面还有其它文件,导致导致上面的代码在调用bind时出错(代码的意思是/dev/log是一个socket文件)所以返回“Address already in use”错误。
问题原因清楚了就好改了。在Android下,只有/data目录是可读下的,例如,我的所有测试程序都被我放在/data/data/test目录下,所有的库放在/data/app目录下。
于是修改上面的目录为:/data/data/test/dev/log(要搜索代码,有好几个地方要改,但实际用到只有2处,其它都是打log的,但为了保持一致建议全部修改。
然后我在/data/data/test目录下创建dev目录后,再次执行syslogd成功。
root@android:/data/data/test # mkdir dev
mkdir dev
root@android:/data/data/test # ./syslogd
./syslogd
root@android:/data/data/test # ps|grep syslogd
ps|grep syslogd
root 27628 1 2196 240 c0c27c24 0000a86c S ./syslogd
root@android:/data/data/test #
上面修改完成后,syslogd可以正常启动了,但还是不能写syslog,原因?
经过使用strace跟踪发现有如下打印:
brk(0x32000) = 0x32000
gettimeofday({1357486044, 584293}, NULL) = 0
open("/etc/localtime", O_RDONLY) = -1 ENOENT (No such file or directory)
getpid() = 32223
socket(PF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_FILE, sun_path="/dev/log"}, 110) = -1 ECONNREFUSED (Connection refused)
close(3) = 0
open("/dev/console", O_WRONLY|O_NOCTTY) = -1 ENODEV (No such device)
exit_group(0) = ?
+++ exited with 0 +++
即,openlog、syslog这些函数,默认也是连/dev/log这个socket的,连不上的话也就无从写日志了。由于openlog、syslog这些是在libc库里面实现的,最坏的后果是修改libc库了看来。具体怎么改,还得研究研究。
从代码来看这个在libc库里面是通过宏_PATH_LOG定义的。具体对应的文件为:
bits/syslog-path.h
原以为修改这个头文件中的宏定义就可以解决问题,但发现实际上libc里面编的时候已经编成/dev/log了,所以必须重编libc才能使修改生效。