2

我在Ubuntu 16.04 LTS下使用arm-linux-gnueabi工具为Android ARM交叉编译了我的 C 应用程序。我用静态链接标志编译它。这个 C 应用程序很大,而且它有复杂的 makefile。它编译成功,没有任何错误。但它在 Android 手机和 Ubuntu PC 上的行为不同。更准确地说,我有两个问题:

  1. popen()system()功能在 Android 上不起作用。它们被执行但什么也不做,也没有给出任何错误。我用肮脏的黑客解决了这个问题。
  2. 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;
}

我的问题。

  1. 如何巧妙而正确地解决我的popen()问题system()?我想我必须与仿生库静态链接。这样对吗?我如何在没有 Android Studio 的情况下在控制台中执行此操作?我读到有必要使用NDK,但我不清楚如何使用。
  2. 为什么fgets()Android 和 Ubuntu 上的行为不相似?
4

0 回答 0