LINUX.ORG.RU

Поясните применения статических либсов в Android NDK

 , ,


0

2

Я использую в Application.mk - APP_PLATFORM := android-21 Но при этом не гарантируется работа на платформах, ниже чем 21, так как , похоже используются разделяемая библиотека libc.so. Но когда я ее удаляю из папки «platforms\android-21\arch-arm\usr\lib», там остается статическая библиотека libc.a. При компиляции проекта со статической библиотекой, строится файл (пусть будет out_jni.so) уже большего размера, чем при компиляции с разделяемой библиотекой, то есть весь нужный код с libc.a переносится в out_jni.so - и она идет даже на теле с 10 API. Знаю что делаю бредово, поэтому зашел сюда спросить - как все это сделать по нормальному, с нужными ключами или опциями в файлах (чтобы не переносить libs.so вручную каждый раз )) )



Последнее исправление: FreakMurderer (всего исправлений: 1)

Оно что, правда работает?
Разве можно в одном процессе использовать 2 разных libc?

mittorn ★★★★★
()
Ответ на: комментарий от FreakMurderer

Как это?
Ведь app-process слинкованный и запущенный с системной через dlopen подгружает стороннюю.
Если больше одного потока - упадёт

mittorn ★★★★★
()
Ответ на: комментарий от FreakMurderer

Когда запускается андройдовое приложение, запускается форк app_process (собственно java-рантайм), слинкованный с системной libc, который и загружает dalvikvm и jni- библиотеки.
Тут же ты пихаешь в библиотеку статическую libc, при этом во время линковки все символы разрешаются статически через неё и всегда функции, вызванные из библиотеки будут выполняться именно из неё. Но весь остальной системный код будет по прежнему использовать системную версию.
Т.к libc на это не расчитана, можно наткнуться на странные баги, вылеты и дыры. Наиболее вероятно что будет полностью поломана работа с потоками. С android лучше не экспериментировать т.к на одном устройстве программа может нормально заработать, на другом вылетит, а третье - вообще в кирпич превратит, если очень уж не повезёт. Уже были прецеденты с nine patch (где-то на хабре писали).

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

Тут же ты пихаешь в библиотеку статическую libc, при этом во время линковки все символы разрешаются статически через неё и всегда функции, вызванные из библиотеки будут выполняться именно из неё.

Поэтому и поддерживаются , старые устройства , так ведь ?

А если такой момент, допустим я создам свою libc (там дополню все символы (функции), которых нет ниже 21 API, скомпилю ее), и назову ее mylibc.a, и сделаю ее статически зависимой для out_jni.so . Это будет не то же самое ? Если это будет то же самое, то как тогда поддерживать старые устройства то , вот например нет функции getgrnam_r, я пишу ее самостоятельно , добавляю ее в либу mylibc.a, подключаю либу к out_jni.so - и что так нельзя делать что-ли - будут глюки. Так как тогда делать, то ?

FreakMurderer
() автор топика
Ответ на: комментарий от FreakMurderer

По сути да.
Для безопасности тебе лучше реализовать только недостающие функции в коде (при этом разумеется можно копировать код из libc, ведь оно под BSD). Тогда будешь уверен, что там не возникнет конфликтов. Только не стоит использовать внутренние функции, они могут исчезать от версии к версии. Уже наткнулся на исчезнувший в 4.3 _vfprintf.

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

По сути да.

Что именно да ?

недостающие функции в коде

В каком именно коде ? В коде для out_jni.so или в коде mylibc.a ? Если в коде для mylibc.a , то как бы получается что я должен подключать mylibc.a к out_jni.so. Далее получается , что если я могу подключать mylibc.a к out_jni.so, то зачем мне ее писать , если все уже написано в libc.a, которую я и подключаю, во избежание лишней работы ? Пожалуйста ответьте конкретно на этот вопрос ...

можно копировать код из libc [/qoute] где лежат официальные исходники 21-й libs. ?

FreakMurderer
() автор топика
Ответ на: комментарий от FreakMurderer

В out_jni.so (именно те, которых не хватает в старых версиях).
Переписывать, чтобы случайно не захватывать функции, уже существующие в старых версиях. И файл будет меньше и меньше шансов наткнуться на проблемы. К тому же не переписывать, а просто скопировать реализацию.
Что за функции хоть такие, которых не было в старой версии?
Может лучше использовать CrystaX NDK, где всё это уже скорее всего сделано?

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

В out_jni.so (именно те, которых не хватает в старых версиях).

так все таки создать mylib с отсутствующими функциями можно или нет ? И какая она должна быть .a или .so ? Я вот не хочу писать все в out_jni.so? потому что потом будет out_jni1.so, out_jni2.so ... и что туда постоянно копировать код ?

Что за функции хоть такие, которых не было в старой версии?

Да их немерянно.. и функции и заголовки , вот сейчас вернул libc.so на место , и запустил приложение на 19-м теле, пожалуйста

CANNOT LINK EXECUTABLE: cannot locate symbol «posix_fadvise» referenced by

Может лучше использовать CrystaX NDK

, так какая разница, там тоже идет разделение на платформы , от 3 - 21 , это тоже самое что и NDK (только там есть то что нет у другого и наоборот), смысла особого не вижу в Crystal NDK (по крайней для поддержки старых платформ ).... И опять такие же libc.a как и NDK (как уже говорил, отличающиеся друг от друга, а толку ? ) Смысл ? У меня уже голова ходуном от всего этого ...

FreakMurderer
() автор топика
Ответ на: комментарий от FreakMurderer

Можно. Про .so не уверен, можешь попробовать. Сделать статическую библиотеку (.a) - то же самое, что дописать в код.
И вообще используй syscall для такой функции, это стабильнее.
Там вся функция - вызов syscall.

Не забудь прочитать man 2 syscall:

   Требования, зависящие от архитектуры
       Каждый  ABI  архитектуры  имеет свои собственные требования по передаче
       аргументов системного вызова в ядро.  Для  системных  вызовов,  имеющих
       обёртку в glibc (большинство системных вызовов), копирование аргументов
       в правильные регистры с учётом архитектуры выполняется в  самой  glibc.
       Однако при выполнении системного вызова через syscall(), вызывающий сам
       должен учитывать особенности архитектуры; чаще всего  это  относится  к
       32-битным архитектурам.

       Например,  на  архитектуре  ARM  Embedded ABI (EABI) 64-битное значение
       (long long) должно быть выровнено по чётной паре  регистров.  То  есть,
       при  использовании  syscall() вместо обёрточной функции glibc системный
       вызов readahead() на ARM вызывался бы с учётом EABI следующим образом:

           syscall(SYS_readahead, fd, 0,
                   (unsigned int) (offset >> 32),
                   (unsigned int) (offset & 0xFFFFFFFF),
                   count);

       Так как смещение аргумента 64 бита, и первый аргумент (fd) передаётся в
       регистре r0, вызывающий должен разделить и выровнять 64-битное значение
       так, чтобы оно передавалось в паре  регистров  r2/r3.  Это  выполняется
       вставкой пустого значения в r1 (второго аргумент 0).

       Подобные  сложности  можно  видеть  на  MIPS  с  O32  ABI, на PowerPC с
       32-битным ABI и на Xtensa.

       Это относится  к  системным  вызовам  fadvise64_64(2),  ftruncate64(2),
       posix_fadvise(2),      pread64(2),      pwrite64(2),      readahead(2),
       sync_file_range(2) и truncate64(2).

mittorn ★★★★★
()
Последнее исправление: mittorn (всего исправлений: 1)
Ответ на: комментарий от mittorn

Сделать статическую библиотеку (.a) - то же самое, что дописать в код.

Ну так я знаю ЭТО, я написал про это еще в первом сообщении... Только ЗАЧЕМ делать статическую библиотеку , если она уже сделана, и наз. она libc.a ... Вот в чем вопрос... В чем разница между собственно сделанной библиотекой и не собственно сделанной библиотекой ? Если че-то не догоняю, пример мне пожалуйста какой нибудь дай ....

FreakMurderer
() автор топика
Ответ на: комментарий от FreakMurderer

да забей ты на этот «posix_fadvise», это лишь одна из сотни функций которых может не быть в старых телах... Я просто ради примера показал...

FreakMurderer
() автор топика
Ответ на: комментарий от FreakMurderer

Почти никакой. Разница только в том, что если прилинковать libc, то оттуда будут браться все системные функции, что может вызвать проблемы (фактически, UB), а если делать самому - можно туда только то, чего не хватает добавить.
Вроде бы в CrystaX NDK лучше реализован POSIX (т.е по идее там в старых платформах они могут быть добавлены).

Ну и ради нескольких системных вызовов тащить весь libc по-моему перебор.

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

т.е по идее там в старых платформах они могут быть добавлены

- ну если это так, то это существенный плюс...

Ок, спасибо , постараюсь во всем этом разобраться ...

FreakMurderer
() автор топика
Ответ на: комментарий от mittorn

Ну и ради нескольких системных вызовов тащить весь libc по-моему перебор.

так а я не тащу весь libc. Весь libc.a занимает - 6,77 МБ А моя .so - занимает всего лишь 476 КБ (если была скопилена вместе с libc.a), и вдвое , по моему , меньше - если скомпилена с libc.so. Да не особо растратно я думаю, с местом получается ...

Может туда не все системные функции добавлены , а только те которые использует моя .so ? Но как ты говоришь, все равно проблемы могут быть, да ?

FreakMurderer
() автор топика
Ответ на: комментарий от FreakMurderer

libc.a - архив с объектниками. Используются только те .o, которые нужны в библиотеке

mittorn ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.