Pytanie, które utworzyłeś, odnosi się do funkcji „Połącz plik binarny z bibliotekami”, która różni się nieco od osadzonego pliku binarnego.
„Połącz plik binarny z bibliotekami” oznacza to, czego można oczekiwać w odniesieniu do łączenia: bez względu na to, czy plik binarny jest biblioteką statyczną, biblioteką dynamiczną czy frameworkiem, zostanie połączony z kodem obiektowym w czasie łączenia po kompilacji.
Kiedy myślisz o połączeniu z biblioteką statyczną, to, co się dzieje, jest całkiem jasne: linker kopiuje kod z biblioteki (np. libFoo.a
) Do wyjściowego pliku binarnego. Twój plik wyjściowy rośnie, ale nie musi rozwiązywać żadnych zewnętrznych zależności w czasie wykonywania. Wszystko, czego program potrzebuje do uruchomienia (w odniesieniu do biblioteki statycznej), jest obecne po jego zbudowaniu.
W przypadku biblioteki dynamicznej (.dylib lub frameworku dostarczonego przez system) oczekuje się, że biblioteka, z którą się łączysz, będzie znajdować się gdzieś w ścieżce systemu ładującego bibliotek dynamicznych podczas uruchamiania programu. W ten sposób nie masz narzutu kopiowania wszystkich zewnętrznych bibliotek stron trzecich do swojego pliku binarnego, a wszystkie różne programy na komputerze, które również łączą się z tą biblioteką, będą w stanie ją znaleźć, co oszczędza minimalnie miejsce na dysku, ale także potencjalnie miejsce w pamięci, w zależności od tego, jak i gdzie system buforuje biblioteki.
Framework jest bardzo podobny do biblioteki dynamicznej, ale może zawierać zasoby w swojej strukturze katalogów (obrazy, audio, inne frameworki itp.). W tym przypadku prosty statyczny Biblioteka lub .dylib plik nie będzie go wyciąć, więc może trzeba linku do ramy tak , że można znaleźć to, czego potrzebuje, aby działać prawidłowo.
Kiedy łączysz się z platformą zewnętrzną (powiedz coś, co pobrałeś z github i zbudowałeś samodzielnie), może nie być obecny w systemie, na którym zamierzasz działać. W takim przypadku nie tylko utworzyłbyś link do frameworka, ale również osadziłbyś go w pakiecie aplikacji, korzystając z fazy „Kopiuj struktury”. Gdy program jest uruchomiony, konsolidator środowiska wykonawczego (inaczej resolver) zajrzy do pakietu oprócz ścieżki programu ładującego system, znajdzie osadzoną strukturę i połączy ją, aby aplikacja miała kod potrzebny do uruchomienia.
Wreszcie, to, co właściwie jest „osadzonym plikiem binarnym”, to plik wykonywalny, który zarówno osadzasz w pakiecie aplikacji za pośrednictwem fazy kopiowania plików, jak i wykonujesz samodzielnie, być może za pomocą wywołania popen()
lub podobnego. Osadzony plik binarny może zostać wywołany przez Twój program, ale nie jest z nim powiązany. Jest to w pełni zewnętrzna jednostka (podobnie jak programy w /bin
katalogu).
W praktyce w przypadku bibliotek i frameworków dostarczonych przez system będziesz łączył się z nimi i to wszystko, co musisz zrobić.
Jeśli chcesz połączyć zbudowaną przez siebie bibliotekę, która nie wymaga żadnych zasobów osadzonych (tj. Nie wymaga istnienia struktury), możesz po prostu połączyć się z biblioteką statyczną. Jeśli zauważysz, że masz wiele modułów w swoim programie, które chcą używać tego samego kodu biblioteki, przekonwertowanie go na strukturę lub bibliotekę dynamiczną i połączenie z nimi może zaoszczędzić miejsce i może być wygodne (szczególnie jeśli problemem jest użycie pamięci).
Wreszcie, frameworki mogą zawierać nie tylko zasoby, ale także pliki nagłówkowe i / lub licencyjne. Używanie frameworka do przenoszenia tych plików jest w rzeczywistości wygodnym mechanizmem dystrybucji, więc często możesz chcieć włączyć framework tylko po to, aby te rzeczy mogły tagować wraz z twoim plikiem binarnym (tj. Wymagania licencyjne mogą uczynić to obowiązkowym).
--- EDYTOWAĆ ---
Adam Johns opublikował następujące pytanie jako komentarz:
To świetna odpowiedź. Jest jednak coś, w czym wciąż jestem trochę zdezorientowany. Co to znaczy samemu wykonać plik binarny? Czy masz na myśli po prostu użycie kodu osadzonej platformy? Wiem, że wspomniałeś o popen (), ale mówisz, że moja aplikacja wywołuje popen ()? Naprawdę nie wiem, co to znaczy.
Mówię, że osadzony plik binarny to po prostu kolejny plik zasobów w twoim pakiecie, taki jak plik audio lub obraz, chociaż plik jest zamiast tego wykonywalnym narzędziem wiersza poleceń. popen()
Function ( man popen
od terminala, aby przeczytać więcej o tym) pozwala na wykonywanie dowolnych programów z innego uruchomionego programu. system()
Funkcja jest inna droga. Są inne i podam tutaj historyczny przykład, który może sprawić, że zrozumienie użycia osadzonego pliku binarnego będzie nieco bardziej przejrzyste:
Jak zapewne wiesz, po uruchomieniu aplikacji w systemie Mac OS X jest ona uruchamiana z identyfikatorem bieżącego użytkownika. W większości typowych instalacji jest to domyślny użytkownik na pulpicie admin
, któremu nadawany jest identyfikator użytkownika 501
.
W systemach operacyjnych opartych na Uniksie tylko root
użytkownik (identyfikator użytkownika 0
) ma pełny dostęp do całego systemu plików. Czasami zdarza się, że program instalacyjny uruchamiany przez użytkownika Pulpitu musi zainstalować pliki w uprzywilejowanym katalogu (na przykład sterowniki). W takim przypadku aplikacja musi przekazać swoje uprawnienia root
użytkownikowi, aby mógł pisać w tych zastrzeżonych katalogach.
Aby ułatwić to w systemach operacyjnych za pośrednictwem OS X 10.7, firma Apple udostępniła w swoim interfejsie API usług autoryzacyjnych funkcję AuthorizationExecuteWithPrivileges () (jest to obecnie przestarzałe, ale nadal stanowi użyteczny przykład).
AuthorizationExecuteWithPrivileges()
jako argument wziął ścieżkę do narzędzia wiersza poleceń do wykonania jako root
. Narzędziem wiersza poleceń był wykonywalny skrypt powłoki lub skompilowany plik binarny napisany w celu uruchomienia logiki instalacji. To narzędzie zostało zainstalowane w pakiecie aplikacji, tak jak każdy inny plik zasobów.
Po wywołaniu system operacyjny wyświetli okno dialogowe autoryzacji z prośbą o podanie hasła użytkownika (widzieliście to już wcześniej!), A po wprowadzeniu uruchomi program root
w imieniu Twojej aplikacji. Ten proces jest podobny do zwykłego wykonania programu ze popen()
sobą, chociaż popen()
sam nie daje korzyści z eskalacji uprawnień.