我使用 Ubuntu 16.04 LTS 下的 arm-linux-gnueabi 工具交叉编译 Android ARM 的C应用程序。我用静态链接标志编译它。这个C应用程序很大,并且它有复杂的makefile。它编译成功没有任何错误。但它在Android手机和Ubuntu PC上表现出不同。更确切地说,我有两个问题:
popen()
和system()
功能在Android上无效。它们被执行但什么都不做,不会给出任何错误。我用脏黑客解决了这个问题。fgets()
功能在Android上很奇怪。1。关于第一个问题。
我进行了小规模研究,发现Android不使用普通的 libc 库( glibc 或其他正确实现POSIX标准的库)。它使用 Bionic 库代替它(抱歉,Android是我的新操作系统)。我查看了popen()
和system()
函数代码,发现这些函数使用了_PATH_BSHELL
个宏。 _PATH_BSHELL
是实际系统shell的路径。此路径在Android上为“ / system / bin / sh ”,在Ubuntu上为“ / bin / sh ”。
当我理解它时,我试图挂钩popen()
和system()
函数。我从 Bionic 源复制了这些函数的代码,而不是我定义的宏#define _MY_PATH_BSHELL "/system/bin/sh"
,并通过execve(_MY_PATH_BSHELL, argp, environ);
调用替换了execve(_MY_PATH_BSHELL, argp, environ);
之类的调用。所以它开始正常工作。
2。关于第二个问题。
在Ubuntu上,这段代码可以正常运行:
is_received = false;
while(!is_received) {
FILE *cmd = popen(command, "r");
is_received = fgets(buf, sizeof(buf), cmd) == NULL ? false : true;
}
但在Android fgets()
上始终返回NULL
,此循环无限长。我尝试使用read()
函数而不是fgets()
并且它有效。
在Android上,read()
的代码正常运行:
is_received = false;
while(!is_received) {
FILE *cmd = hooked_popen(command, "r");
int fd = fileno(cmd);
is_received = read(fd, buf, sizeof(buf)) == 0 ? false : true;
}
我的问题。
popen()
和system()
的问题?我想我必须静态链接 Bionic 库。这样对吗?如何在没有Android Studio的情况下在控制台中执行此操作?我读到有必要使用 NDK ,但我不清楚如何。 fgets()
行为在Android和Ubuntu上不相似?