我在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
是实际系统外壳的路径。此路径在 Android 上为“ /system/bin/sh ”,在 Ubuntu 上为“ /bin/sh ”。
当我理解它时,我试图挂钩popen()
和system()
功能。我从仿生源复制了这些函数的代码,然后定义了宏#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()
?我想我必须与仿生库静态链接。这样对吗?我如何在没有 Android Studio 的情况下在控制台中执行此操作?我读到有必要使用NDK,但我不清楚如何使用。 - 为什么
fgets()
Android 和 Ubuntu 上的行为不相似?