android下syslogd启动后出现“syslogd: bind: Address already in use”错误的解决方法

把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才能使修改生效。

你可能感兴趣的:(android下syslogd启动后出现“syslogd: bind: Address already in use”错误的解决方法)