Apple Apple Remote Desktop Administrator’s Guide Version 3 ARD3_AdminGuide.pdf Manuel Apple sur Fnac.com - Pour voir la liste complète des manuels APPLE, cliquez ici

 

 

TELECHARGER LE PDF sur :

http://images.apple.com/ca/fr/remotedesktop/pdf/ARD3_AdminGuide.pdf

Commander un produit Apple sur Fnac.com

 

 

Voir également d'autres Guides et documentation APPLE :

Apple-InstrumentsUserGuide.pdf-manuel

Apple-Logic-Pro-9-TDM-Guide-manuel

Apple-macbook_air_users_guide.pdf-manuel

Apple-macbook_air-13-inch_mid-2012-qs_ta.pdf-manuel

Apple-AppStoreMarketingGuidelines-JP.pdf-Japon-manuel

Apple-macbook_pro_retina_qs_ta.pdf-manuel

Apple-ipad_user_guide_tu.pdf-manuel

Apple-ipad_user_guide_th.pdf-manuel

Apple-iphone_user_guide_gr.pdf-manuel

Apple-Nike_Plus_iPod_Sensor_UG_2A.pdf-manuel

Apple-ipad_manual_del_usuario.pdf-manuel

Apple-ipad_uzivatelska_prirucka.pdf-manuel

Apple-ipad_wifi_informations_importantes.pdf-manuel

Apple-Xsan_2_Admin_Guide_v2.3.pdf-manuel

Apple-macbook_pro-13-inch-late-2012-quick_start.pdf-manuel

Apple-CocoaDrawingGuide.pdf-manuel

Apple-Cryptographic-Services-Guide-manuel

Apple-Resource-Programming-Guide-manuel

AppleSafariVisualEffectsProgGuide.pdf-manuel

/Apple-WorkingWithUSB.pdf-manuel

Apple-macbook_pro-retina-mid-2012-important_product_info_f.pdf-manuel

Apple-iOS_Security_May12.pdf-manue

Apple-Mac-Pro-2008-Performance-and-Productivity-for-Creative-Pros

Apple-iPod_shuffle_4thgen_Manuale_utente.pdf-Italie-Manuel

Apple-KernelProgramming.pdf-manuel

Apple-Core-Data-Model-Versioning-and-Data-Migration-Programming-Guide-manuel

Apple-RED_Workflows_with_Final_Cut_Pro_X.pdf-manuel

Apple-Transitioning-to-ARC-Release-Notes-manuel

Apple-iTunes-Connect-Sales-and-Trends-Guide-manuel

Apple-App-Sandbox-Design-Guide-manuel

Apple-String-Programming-Guide-manuel

Apple-Secure-Coding-Guide-manuel

Apple_AirPort_Networks_Early2009.pdf-manuel

Apple-TimeCapsule_SetupGuide_TA.pdf-manuel

Apple-time_capsule_4th_gen_setup.pdf-manuel

Apple-TimeCapsule_SetupGuide.pdf-manuel

Apple-TimeCapsule_SetupGuide_CH.pdf-Chinois-manuel

Apple-CodeSigningGuide.pdf-manuel

Apple-ViewControllerPGforiOS.pdf-manuel

Apple-KeyValueObserving.pdf-manuel

Apple-mac_mini-late-2012-quick_start.pdf-manuel

Apple-OS-X-Mountain-Lion-Core-Technologies-Overview-June-2012-manuel

Apple-OS-X-Server-Product-Overview-June-2012-manuel

Apple-Apple_Server_Diagnostics_UG_109.pdf-manuel

Apple-PackageMaker_UserGuide.pdf-manuel

Apple-Instrumentos_y_efectos_de_Logic_Studio.pdf-Manuel

Apple-ipod_nano_kayttoopas.pdf-Finlande-Manuel

Apple_ProRes_White_Paper_October_2012.pdf-Manuel

Apple-wp_osx_configuration_profiles.pdf-Manuel

Apple-UsingiTunesProducerFreeBooks.pdf-Manuel

Apple-ipad_manual_do_usuario.pdf-Portugais-Manuel

Apple-Instruments_et_effets_Logic_Studio.pdf-Manuel

Apple-ipod_touch_gebruikershandleiding.pdf-Neerlandais-Manuel

AppleiPod_shuffle_4thgen_Manual_del_usuario.pdf-Espagnol-Manuel

Apple-Premiers-contacts-avec-votre-PowerBook-G4-Manuel

Apple_Composite_AV_Cable.pdf-Manuel

Apple-iPod_shuffle_3rdGen_UG_DK.pdf-Danemark-Manuel

Apple-iPod_classic_160GB_Benutzerhandbuch.pdf-Allemand-Manuel

Apple-VoiceOver_GettingStarted-Manuel

Apple-iPod_touch_2.2_Benutzerhandbuch.pdf-Allemand-Manuel

Apple-Apple_TV_Opstillingsvejledning.pdf-Allemand-Manuel

Apple-iPod_shuffle_4thgen_Manuale_utente.pdf-Italie-Manuel

Apple-iphone_prirucka_uzivatela.pdf-Manuel

Apple-Aan-de-slag-Neerlandais-Manuel

Apple-airmac_express-80211n-2nd-gen_setup_guide.pdf-Thailande-Manuel

Apple-ipod_nano_benutzerhandbuch.pdf-Allemand-Manuel

Apple-aperture3.4_101.pdf-Manuel

Apple-Pages09_Anvandarhandbok.pdf-Manuel

Apple-nike_plus_ipod_sensor_ug_la.pdf-Mexique-Manuel

Apple-ResEdit-Reference-For-ResEdit02.1-Manuel

Apple-ipad_guide_de_l_utilisateur.pdf-Manuel

Apple-Compressor-4-Benutzerhandbuch-Allemand-Manuel

Apple-AirPort_Networks_Early2009_DK.pdf-Danemark-Manuel

Apple-MacBook_Pro_Mid2007_2.4_2.2GHz_F.pdf-Manuel

Apple-MacBook_13inch_Mid2010_UG_F.pdf-Manuel

Apple-Xserve-RAID-Presentation-technologique-Janvier-2004-Manuel

Apple-MacBook_Pro_15inch_Mid2010_F.pdf-Manuel

Apple-AirPort_Express-opstillingsvejledning.pdf-Danemark-Manuel

Apple-DEiPod_photo_Benutzerhandbuch_DE0190269.pdf-Allemand-Manuel

Apple-Final-Cut-Pro-X-Logic-Effects-Reference-Manuel

Apple-iPod_touch_2.1_Brugerhandbog.pdf-Danemark-Manuel

Apple-Remote-Desktop-Administratorhandbuch-Version-3.1-Allemand-Manuel

Apple-Qmaster-4-User-Manual-Manuel

Apple-Server_Administration_v10.5.pdf-Manuel

Apple-ipod_classic_features_guide.pdf-Manuel

Apple-Lecteur-Optique-Manuel

Apple-Carte-AirPort-Manuel

Apple-iPhone_Finger_Tips_Guide.pdf-Anglais-Manuel

Apple-Couvercle-Manuel

Apple-battery.cube.pdf-Manuel

Apple-Boitier-de-l-ordinateur-Manuel

Apple-Pile-Interne-Manuel

Apple-atacable.pdf-Manuel

Apple-videocard.pdf-Manuel

Apple-Guide_de_configuration_de_l_Airport_Express_5.1.pdf-Manuel

Apple-iMac_Mid2010_UG_F.pdf-Manuel

Apple-MacBook_13inch_Mid2009_F.pdf-Manuel

Apple-MacBook_Mid2007_UserGuide.F.pdf-Manuel

Apple-Designing_AirPort_Networks_10.5-Windows_F.pdf-Manuel

Apple-Administration_de_QuickTime_Streaming_et_Broadcasting_10.5.pdf-Manuel

Apple-Opstillingsvejledning_til_TimeCapsule.pdf-Danemark-Manuel

Apple-iPod_nano_5th_gen_Benutzerhandbuch.pdf-Manuel

Apple-iOS_Business.pdf-Manuel

Apple-AirPort_Extreme_Installationshandbuch.pdf-Manuel

Apple-Final_Cut_Express_4_Installation_de_votre_logiciel.pdf-Manuel

Apple-MacBook_Pro_15inch_2.53GHz_Mid2009.pdf-Manuel

Apple-Network_Services.pdf-Manuel

Apple-Aperture_Performing_Adjustments_f.pdf-Manuel

Apple-Supplement_au_guide_Premiers_contacts.pdf-Manuel

Apple-Administration_des_images_systeme_et_de_la_mise_a_jour_de_logiciels_10.5.pdf-Manuel

Apple-Mac_OSX_Server_v10.6_Premiers_contacts.pdf-Francais-Manuel

Apple-Designing_AirPort_Networks_10.5-Windows_F.pdf-Manuel

Apple-Mise_a_niveau_et_migration_v10.5.pdf-Manue

Apple-MacBookPro_Late_2007_2.4_2.2GHz_F.pdf-Manuel

Apple-Mac_mini_Late2009_SL_Server_F.pdf-Manuel

Apple-Mac_OS_X_Server_10.5_Premiers_contacts.pdf-Manuel

Apple-iPod_touch_2.0_Guide_de_l_utilisateur_CA.pdf-Manuel

Apple-MacBook_Pro_17inch_Mid2010_F.pdf-Manuel

Apple-Comment_demarrer_Leopard.pdf-Manuel

Apple-iPod_2ndGen_USB_Power_Adapter-FR.pdf-Manuel

Apple-Feuille_de_operations_10.4.pdf-Manuel

Apple-Time_Capsule_Installationshandbuch.pdf-Allemand-Manuel

Apple-F034-2262AXerve-grappe.pdf-Manuel

Apple-Mac_Pro_Early2009_4707_UG_F

Apple-imacg5_17inch_Power_Supply

Apple-Logic_Studio_Installieren_Ihrer_Software_Retail

Apple-IntroductionXserve1.0.1

Apple-Aperture_Getting_Started_d.pdf-Allemand

Apple-getting_started_with_passbook

Apple-iPod_mini_2nd_Gen_UserGuide.pdf-Anglais

Apple-Deploiement-d-iPhone-et-d-iPad-Reseaux-prives-virtuels

Apple-F034-2262AXerve-grappe

Apple-Mac_OS_X_Server_Glossaire_10.5

Apple-FRLogic_Pro_7_Guide_TDM

Apple-iphone_bluetooth_headset_userguide

Apple-Administration_des_services_reseau_10.5

Apple-imacg5_17inch_harddrive

Apple-iPod_nano_4th_gen_Manuale_utente

Apple-iBook-G4-Getting-Started

Apple-XsanGettingStarted

Apple-Mac_mini_UG-Early2006

Apple-Guide_des_fonctionnalites_de_l_iPod_classic

Apple-Guide_de_configuration_d_Xsan_2

Apple-MacBook_Late2006_UsersGuide

Apple-sur-Fnac.com

Apple-Mac_mini_Mid2010_User_Guide_F.pdf-Francais

Apple-PowerBookG3UserManual.PDF.Anglais

Apple-Installation_de_votre_logiciel_Logic_Studio_Retail

Apple-Pages-Guide-de-l-utilisateur

Apple-MacBook_Pro_13inch_Mid2009.pdf.Anglais

Apple-MacBook_Pro_15inch_Mid2009

Apple-Installation_de_votre_logiciel_Logic_Studio_Upgrade

Apple-FRLogic_Pro_7_Guide_TDM

Apple-airportextreme_802.11n_userguide

Apple-iPod_shuffle_3rdGen_UG

Apple-iPod_classic_160GB_User_Guide

Apple-iPod_nano_5th_gen_UserGuide

Apple-ipod_touch_features_guide

Apple-Wireless_Mighty_Mouse_UG

Apple-Advanced-Memory-Management-Programming-Guide

Apple-iOS-App-Programming-Guide

Apple-Concurrency-Programming-Guide

Apple-MainStage-2-User-Manual-Anglais

Apple-iMacG3_2002MultilingualUserGuide

Apple-iBookG3_DualUSBUserGuideMultilingual.PDF.Anglais

Apple-imacG5_20inch_AirPort

Apple-Guide_de_l_utilisateur_de_Mac_Pro_Early_2008

Apple-Installation_de_votre_logiciel_Logic_Express_8

Apple-iMac_Guide_de_l_utilisateur_Mid2007

Apple-imacg5_20inch_OpticalDrive

Apple-FCP6_Formats_de_diffusion_et_formats_HD

Apple-prise_en_charge_des_surfaces_de_controle_logic_pro_8

Apple-Aperture_Quick_Reference_f

Apple-Shake_4_User_Manual

Apple-aluminumAppleKeyboard_wireless2007_UserGuide

Apple-ipod_shuffle_features_guide

Apple-Color-User-Manual

Apple-XsanGettingStarted

Apple-Migration_10.4_2e_Ed

Apple-MacBook_Air_SuperDrive

Apple-MacBook_Late2007-f

ApplePowerMacG5_(Early_2005)_UserGuide

Apple-iSightUserGuide

Apple-MacBook_Pro_Early_2008_Guide_de_l_utilisateur

Apple-Nouvelles-fonctionnalites-aperture-1.5

Apple-premiers_contacts_2e_ed_10.4.pdf-Mac-OS-X-Server

Apple-premiers_contacts_2e_ed_10.4

Apple-eMac_2005UserGuide

Apple-imacg5_20inch_Inverter

Apple-Keynote2_UserGuide.pdf-Japon

Apple-Welcome_to_Tiger.pdf-Japon

Apple-XsanAdminGuide_j.pdf-Japon

Apple-PowerBookG4_UG_15GE.PDF-Japon

Apple-Xsan_Migration.pdf-Japon

Apple-Xserve_Intel_DIY_TopCover_JA.pdf-Japon

Apple-iPod_nano_6thgen_User_Guide_J.pdf-Japon

Apple-Aperture_Photography_Fundamentals.pdf-Japon

Apple-nikeipod_users_guide.pdf-Japon

Apple-QuickTime71_UsersGuide.pdf-Japon

Apple-iMacG5_iSight_UG.pdf-Japon

Apple-Aperture_Performing_Adjustments_j.pdf-Japon

Apple-iMacG5_17inch_HardDrive.pdf-Japon

Apple-iPod_shuffle_Features_Guide_J.pdf-Japon

Apple-MacBook_Air_User_Guide.pdf-Japon

Apple-MacBook_UsersGuide.pdf-Japon

Apple-iPad_iOS4_Brukerhandbok.pdf-Norge-Norvege

Apple-Apple_AirPort_Networks_Early2009_H.pd-Norge-Norvege

Apple-iPod_classic_120GB_no.pdf-Norge-Norvege

Apple-StoreKitGuide.pdf-Japon

Apple-Xserve_Intel_DIY_ExpansionCardRiser_JA.pdf-Japon

Apple-iMacG5_Battery.pdf-Japon

Apple-Logic_Pro_8_Getting_Started.pdf-Japon

Apple-PowerBook-handbok-Norge-Norveg

Apple-iWork09_formler_og_funksjoner.pdf-Norge-Norvege

Apple-MacBook_Pro_15inch_Mid2010_H.pdf-Norge-Norvege

Apple-MacPro_HardDrive_DIY.pdf-Japon

Apple-iPod_Fifth_Gen_Funksjonsoversikt.pdf-Norge-Norvege

Apple-MacBook_13inch_white_Early2009_H.pdf-Norge-Norvege

Apple-GarageBand_09_Komme_i_gang.pdf-Norge-Norvege

Apple-MacBook_Pro_15inch_Mid2009_H.pdf-Norge-Norvege

Apple-imac_mid2011_ug_h.pdf-Norge-Norvege

Apple-iDVD_08_Komme_i_gang.pdf-Norge-Norvege

Apple-MacBook_Air_11inch_Late2010_UG_H.pdf-Norge-Norvege

Apple-iMac_Mid2010_UG_H.pdf-Norge-Norvege

Apple-MacBook_13inch_Mid2009_H.pdf-Norge-Norvege

/Apple-iPhone_3G_Viktig_produktinformasjon_H-Norge-Norvege

Apple-MacBook_13inch_Mid2010_UG_H.pdf-Norge-Norvege

Apple-macbook_air_13inch_mid2011_ug_no.pdf-Norge-Norvege

Apple-Mac_mini_Early2009_UG_H.pdf-Norge-Norvege

Apple-ipad2_brukerhandbok.pdf-Norge-Norvege

Apple-iPhoto_08_Komme_i_gang.pdf-Norge-Norvege

Apple-MacBook_Air_Brukerhandbok_Late2008.pdf-Norge-Norvege

Apple-Pages09_Brukerhandbok.pdf-Norge-Norvege

Apple-MacBook_13inch_Late2009_UG_H.pdf-Norge-Norvege

Apple-iPhone_3GS_Viktig_produktinformasjon.pdf-Norge-Norvege

Apple-MacBook_13inch_Aluminum_Late2008_H.pdf-Norge-Norvege

Apple-Wireless_Keyboard_Aluminum_2007_H-Norge-Norvege

Apple-NiPod_photo_Brukerhandbok_N0190269.pdf-Norge-Norvege

Apple-MacBook_Pro_13inch_Mid2010_H.pdf-Norge-Norvege

Apple-MacBook_Pro_17inch_Mid2010_H.pdf-Norge-Norvege

Apple-Velkommen_til_Snow_Leopard.pdf-Norge-Norvege.htm

Apple-TimeCapsule_Klargjoringsoversikt.pdf-Norge-Norvege

Apple-iPhone_3GS_Hurtigstart.pdf-Norge-Norvege

Apple-Snow_Leopard_Installeringsinstruksjoner.pdf-Norge-Norvege

Apple-iMacG5_iSight_UG.pdf-Norge-Norvege

Apple-iPod_Handbok_S0342141.pdf-Norge-Norvege

Apple-ipad_brukerhandbok.pdf-Norge-Norvege

Apple-GE_Money_Bank_Handlekonto.pdf-Norge-Norvege

Apple-MacBook_Air_11inch_Late2010_UG_H.pdf-Norge-Norvege

Apple-iPod_nano_6thgen_Brukerhandbok.pdf-Norge-Norvege

Apple-iPod_touch_iOS4_Brukerhandbok.pdf-Norge-Norvege

Apple-MacBook_Air_13inch_Late2010_UG_H.pdf-Norge-Norvege

Apple-MacBook_Pro_15inch_Early2011_H.pdf-Norge-Norvege

Apple-Numbers09_Brukerhandbok.pdf-Norge-Norvege

Apple-Welcome_to_Leopard.pdf-Japon

Apple-PowerMacG5_UserGuide.pdf-Norge-Norvege

Apple-iPod_touch_2.1_Brukerhandbok.pdf-Norge-Norvege

Apple-Boot_Camp_Installering-klargjoring.pdf-Norge-Norvege

Apple-MacOSX10.3_Welcome.pdf-Norge-Norvege

Apple-iPod_shuffle_3rdGen_UG_H.pdf-Norge-Norvege

Apple-iPhone_4_Viktig_produktinformasjon.pdf-Norge-Norvege

Apple_TV_Klargjoringsoversikt.pdf-Norge-Norvege

Apple-iMovie_08_Komme_i_gang.pdf-Norge-Norvege

Apple-iPod_classic_160GB_Brukerhandbok.pdf-Norge-Norvege

Apple-Boot_Camp_Installering_10.6.pdf-Norge-Norvege

Apple-Network-Services-Location-Manager-Veiledning-for-nettverksadministratorer-Norge-Norvege

Apple-iOS_Business_Mar12_FR.pdf

Apple-PCIDualAttachedFDDICard.pdf

Apple-Aperture_Installing_Your_Software_f.pdf

Apple-User_Management_Admin_v10.4.pdf

Apple-Compressor-4-ユーザーズマニュアル Japon

Apple-Network_Services_v10.4.pdf

Apple-iPod_2ndGen_USB_Power_Adapter-DE

Apple-Mail_Service_v10.4.pdf

Apple-AirPort_Express_Opstillingsvejledning_5.1.pdf

Apple-MagSafe_Airline_Adapter.pdf

Apple-L-Apple-Multiple-Scan-20-Display

Apple-Administration_du_service_de_messagerie_10.5.pdf

Apple-System_Image_Admin.pdf

Apple-iMac_Intel-based_Late2006.pdf-Japon

Apple-iPhone_3GS_Finger_Tips_J.pdf-Japon

Apple-Power-Mac-G4-Mirrored-Drive-Doors-Japon

Apple-AirMac-カード取り付け手順-Japon

Apple-iPhone開発ガイド-Japon

Apple-atadrive_pmg4mdd.j.pdf-Japon

Apple-iPod_touch_2.2_User_Guide_J.pdf-Japon

Apple-Mac_OS_X_Server_v10.2.pdf

Apple-AppleCare_Protection_Plan_for_Apple_TV.pdf

Apple_Component_AV_Cable.pdf

Apple-DVD_Studio_Pro_4_Installation_de_votre_logiciel

Apple-Windows_Services

Apple-Motion_3_New_Features_F

Apple-g4mdd-fw800-lowerfan

Apple-MacOSX10.3_Welcome

Apple-Print_Service

Apple-Xserve_Setup_Guide_F

Apple-PowerBookG4_17inch1.67GHzUG

Apple-iMac_Intel-based_Late2006

Apple-Installation_de_votre_logiciel

Apple-guide_des_fonctions_de_l_iPod_nano

Apple-Administration_de_serveur_v10.5

Apple-Mac-OS-X-Server-Premiers-contacts-Pour-la-version-10.3-ou-ulterieure

Apple-boot_camp_install-setup

Apple-iBookG3_14inchUserGuideMultilingual

Apple-mac_pro_server_mid2010_ug_f

Apple-Motion_Supplemental_Documentation

Apple-imac_mid2011_ug_f

Apple-iphone_guide_de_l_utilisateur

Apple-macbook_air_11inch_mid2011_ug_fr

Apple-NouvellesfonctionnalitesdeLogicExpress7.2

Apple-QT_Streaming_Server

Apple-Web_Technologies_Admin

Apple-Mac_Pro_Early2009_4707_UG

Apple-guide_de_l_utilisateur_de_Numbers08

Apple-Decouverte_d_Aperture_2

Apple-Guide_de_configuration_et_d'administration

Apple-mac_integration_basics_fr_106.

Apple-iPod_shuffle_4thgen_Guide_de_l_utilisateur

Apple-ARA_Japan

Apple-081811_APP_iPhone_Japanese_v5.4.pdf-Japan

Apple-Recycle_Contract120919.pdf-Japan

Apple-World_Travel_Adapter_Kit_UG

Apple-iPod_nano_6thgen_User_Guide

Apple-RemoteSupportJP

Apple-Mac_mini_Early2009_UG_F.pdf-Manuel-de-l-utilisateur

Apple-Compressor_3_Batch_Monitor_User_Manual_F.pdf-Manuel-de-l-utilisateur

Apple-Premiers__contacts_avec_iDVD_08

Apple-Mac_mini_Intel_User_Guide.pdf

Apple-Prise_en_charge_des_surfaces_de_controle_Logic_Express_8

Apple-mac_integration_basics_fr_107.pdf

Apple-Final-Cut-Pro-7-Niveau-1-Guide-de-preparation-a-l-examen

Apple-Logic9-examen-prep-fr.pdf-Logic-Pro-9-Niveau-1-Guide-de-preparation-a-l-examen

Apple-aperture_photography_fundamentals.pdf-Manuel-de-l-utilisateu

Apple-emac-memory.pdf-Manuel-de-l-utilisateur

Apple-Apple-Installation-et-configuration-de-votre-Power-Mac-G4

Apple-Guide_de_l_administrateur_d_Xsan_2.pdf

Apple-premiers_contacts_avec_imovie6.pdf

Apple-Tiger_Guide_Installation_et_de_configuration.pdf

Apple-Final-Cut-Pro-7-Level-One-Exam-Preparation-Guide-and-Practice-Exam

Apple-Open_Directory.pdf

Apple-Nike_+_iPod_User_guide

Apple-ard_admin_guide_2.2_fr.pdf

Apple-systemoverviewj.pdf-Japon

Apple-Xserve_TO_J070411.pdf-Japon

Apple-Mac_Pro_User_Guide.pdf

Apple-iMacG5_iSight_UG.pdf

Apple-premiers_contacts_avec_iwork_08.pdf

Apple-services_de_collaboration_2e_ed_10.4.pdf

Apple-iPhone_Bluetooth_Headset_Benutzerhandbuch.pdf

Apple-Guide_de_l_utilisateur_de_Keynote08.pdf

APPLE/Apple-Logic-Pro-9-Effectsrfr.pdf

Apple-Logic-Pro-9-Effectsrfr.pdf

Apple-iPod_shuffle_3rdGen_UG_F.pdf

Apple-iPod_classic_160Go_Guide_de_l_utilisateur.pdf

Apple-iBookG4GettingStarted.pdf

Apple-Administration_de_technologies_web_10.5.pdf

Apple-Compressor-4-User-Manual-fr

Apple-MainStage-User-Manual-fr.pdf

Apple-Logic_Pro_8.0_lbn_j.pdf

Apple-PowerBookG4_15inch1.67-1.5GHzUserGuide.pdf

Apple-MacBook_Pro_15inch_Mid2010_CH.pdf

Apple-LED_Cinema_Display_27-inch_UG.pdf

Apple-MacBook_Pro_15inch_Mid2009_RS.pdf

Apple-macbook_pro_13inch_early2011_f.pdf

Apple-iMac_Mid2010_UG_BR.pdf

Apple-iMac_Late2009_UG_J.pdf

Apple-iphone_user_guide-For-iOS-6-Software

Apple-iDVD5_Getting_Started.pdf

Apple-guide_des_fonctionnalites_de_l_ipod_touch.pdf

Apple_iPod_touch_User_Guide

Apple_macbook_pro_13inch_early2011_f

Apple_Guide_de_l_utilisateur_d_Utilitaire_RAID

Apple_Time_Capsule_Early2009_Setup_F

Apple_iphone_4s_finger_tips_guide_rs

Apple_iphone_upute_za_uporabu

Apple_ipad_user_guide_ta

Apple_iPod_touch_User_Guide

apple_earpods_user_guide

apple_iphone_gebruikershandleiding

apple_iphone_5_info

apple_iphone_brukerhandbok

apple_apple_tv_3rd_gen_setup_tw

apple_macbook_pro-retina-mid-2012-important_product_info_ch

apple_Macintosh-User-s-Guide-for-Macintosh-PowerBook-145

Apple_ipod_touch_user_guide_ta

Apple_TV_2nd_gen_Setup_Guide_h

Apple_ipod_touch_manual_del_usuario

Apple_iphone_4s_finger_tips_guide_tu

Apple_macbook_pro_retina_qs_th

Apple-Manuel_de_l'utilisateur_de_Final_Cut_Server

Apple-iMac_G5_de_lutilisateur

Apple-Cinema_Tools_4.0_User_Manual_F

Apple-Personal-LaserWriter300-User-s-Guide

Apple-QuickTake-100-User-s-Guide-for-Macintosh

Apple-User-s-Guide-Macintosh-LC-630-DOS-Compatible

Apple-iPhone_iOS3.1_User_Guide

Apple-iphone_4s_important_product_information_guide

Apple-iPod_shuffle_Features_Guide_F

Liste-documentation-apple

Apple-Premiers_contacts_avec_iMovie_08

Apple-macbook_pro-retina-mid-2012-important_product_info_br

Apple-macbook_pro-13-inch-mid-2012-important_product_info

Apple-macbook_air-11-inch_mid-2012-qs_br

Apple-Manuel_de_l_utilisateur_de_MainStage

Apple-Compressor_3_User_Manual_F

Apple-Color_1.0_User_Manual_F

Apple-guide_de_configuration_airport_express_4.2

Apple-TimeCapsule_SetupGuide

Apple-Instruments_et_effets_Logic_Express_8

Apple-Manuel_de_l_utilisateur_de_WaveBurner

Apple-Macmini_Guide_de_l'utilisateur

Apple-PowerMacG5_UserGuide

Disque dur, ATA parallèle Instructions de remplacement

Apple-final_cut_pro_x_logic_effects_ref_f

Apple-Leopard_Installationshandbok

Manuale Utente PowerBookG4

Apple-thunderbolt_display_getting_started_1e

Apple-Compressor-4-Benutzerhandbuch

Apple-macbook_air_11inch_mid2011_ug

Apple-macbook_air-mid-2012-important_product_info_j

Apple-iPod-nano-Guide-des-fonctionnalites

Apple-iPod-nano-Guide-des-fonctionnalites

Apple-iPod-nano-Guide-de-l-utilisateur-4eme-generation

Apple-iPod-nano-Guide-de-l-utilisateur-4eme-generation

Apple-Manuel_de_l_utilisateur_d_Utilitaire_de_reponse_d_impulsion

Apple-Aperture_2_Raccourcis_clavier

AppleTV_Setup-Guide

Apple-livetype_2_user_manual_f

Apple-imacG5_17inch_harddrive

Apple-macbook_air_guide_de_l_utilisateur

Apple-MacBook_Early_2008_Guide_de_l_utilisateur

Apple-Keynote-2-Guide-de-l-utilisateur

Apple-PowerBook-User-s-Guide-for-PowerBook-computers

Apple-Macintosh-Performa-User-s-Guide-5200CD-and-5300CD

Apple-Macintosh-Performa-User-s-Guide

Apple-Workgroup-Server-Guide

Apple-iPod-nano-Guide-des-fonctionnalites

Apple-iPad-User-Guide-For-iOS-5-1-Software

Apple-Boot-Camp-Guide-d-installation-et-de-configuration

Apple-iPod-nano-Guide-de-l-utilisateur-4eme-generation

Power Mac G5 Guide de l’utilisateur APPLE

Guide de l'utilisateur PAGE '08 APPLE

Guide de l'utilisateur KEYNOTE '09 APPLE

Guide de l'Utilisateur KEYNOTE '3 APPLE

Guide de l'Utilisateur UTILITAIRE RAID

Guide de l'Utilisateur Logic Studio

Power Mac G5 Guide de l’utilisateur APPLE

Guide de l'utilisateur PAGE '08 APPLE

Guide de l'utilisateur KEYNOTE '09 APPLE

Guide de l'Utilisateur KEYNOTE '3 APPLE

Guide de l'Utilisateur UTILITAIRE RAID

Guide de l'Utilisateur Logic Studio

Guide de l’utilisateur ipad Pour le logiciel iOS 5.1

PowerBook G4 Premiers Contacts APPLE

Guide de l'Utilisateur iphone pour le logiciel ios 5.1 APPLE

Guide de l’utilisateur ipad Pour le logiciel iOS 4,3

Guide de l’utilisateur iPod nano 5ème génération

Guide de l'utilisateur iPod Touch 2.2 APPLE

Guide de l’utilisateur QuickTime 7  Mac OS X 10.3.9 et ultérieur Windows XP et Windows 2000

Guide de l'utilisateur MacBook 13 pouces Mi 2010

Guide de l’utilisateur iPhone (Pour les logiciels iOS 4.2 et 4.3)

Guide-de-l-utilisateur-iPod-touch-pour-le-logiciel-ios-4-3-APPLE

Guide-de-l-utilisateur-iPad-2-pour-le-logiciel-ios-4-3-APPLE

Guide de déploiement en entreprise iPhone OS

Guide-de-l-administrateur-Apple-Remote-Desktop-3-1

Guide-de-l-utilisateur-Apple-Xserve-Diagnostics-Version-3X103

Guide-de-configuration-AirPort-Extreme-802.11n-5e-Generation

Guide-de-configuration-AirPort-Extreme-802-11n-5e-Generation

Guide-de-l-utilisateur-Capteur-Nike-iPod

Guide-de-l-utilisateur-iMac-21-5-pouces-et-27-pouces-mi-2011-APPLE

Guide-de-l-utilisateur-Apple-Qadministrator-4

Guide-d-installation-Apple-TV-3-eme-generation

User-Guide-iPad-For-ios-5-1-Software

Apple Remote Desktop Administrator’s Guide Version 3K Apple Computer, Inc. © 2006 Apple Computer, Inc. All rights reserved. The owner or authorized user of a valid copy of Apple Remote Desktop software may reproduce this publication for the purpose of learning to use such software. No part of this publication may be reproduced or transmitted for commercial purposes, such as selling copies of this publication or for providing paid for support services. The Apple logo is a trademark of Apple Computer, Inc., registered in the U.S. and other countries. Use of the “keyboard” Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair competition in violation of federal and state laws. Apple, the Apple logo, AirPort, AppleScript, AppleTalk, AppleWorks, FireWire, iBook, iMac, iSight, Keychain, Mac, Macintosh, Mac OS, PowerBook, QuickTime, and Xserve are trademarks of Apple Computer, Inc., registered in the U.S. and other countries. Apple Remote Desktop, Bonjour, eMac, Finder, iCal, and Safari are trademarks of Apple Computer, Inc. Adobe and Acrobat are trademarks of Adobe Systems Incorporated. Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. UNIX is a registered trademark in the United States and other countries, licensed exclusively through X/Open Company, Ltd. 019-0629/02-28-06 3 3 Contents Preface 9 About This Book 10 Using This Guide 10 Remote Desktop Help 10 Notation Conventions 11 Where to Find More Information About Apple Remote Desktop Chapter 1 13 Using Apple Remote Desktop 13 Administering Computers 15 Deploying Software 18 Taking Inventory 21 Housekeeping 22 Supporting Users 23 Providing Help Desk Support 25 Interacting with Students 26 Finding More Information Chapter 2 28 Getting to Know Remote Desktop 28 Remote Desktop Human Interface Guide 29 Remote Desktop Main Window 31 Task Dialogs 32 Control and Observe Window 33 Multiple-Client Observe Window 34 Report Window 35 Changing Report Layout 36 Configuring Remote Desktop 36 Customizing the Remote Desktop Toolbar 36 Setting Preferences for the Remote Desktop Administrator Application 37 Interface Tips and Shortcuts Chapter 3 39 Installing Apple Remote Desktop 39 System Requirements for Apple Remote Desktop 40 Network Requirements 40 Installing the Remote Desktop Administrator Software 41 Setting Up an Apple Remote Desktop Client Computer for the First Time4 Contents 41 Upgrading the Remote Desktop Administrator Software 42 Upgrading the Client Software 42 Method #1—Remote Upgrade Installation 43 Method #2—Manual Installation 43 Upgrading Apple Remote Desktop Clients Using SSH 44 Creating a Custom Client Installer 46 Considerations for Managed Clients 46 Removing or Disabling Apple Remote Desktop 46 Uninstalling the Administrator Software 47 Disabling the Client Software 48 Uninstalling the Client Software from Client Computers Chapter 4 49 Organizing Client Computers Into Computer Lists 49 Finding and Adding Clients to Apple Remote Desktop Computer Lists 50 Finding Clients by Searching the Local Network 50 Finding Clients by Searching a Network Range 51 Finding Clients by Network Address 52 Finding Clients by File Import 52 Making a New Scanner 53 Making and Managing Lists 53 About Apple Remote Desktop Computer Lists 54 Creating an Apple Remote Desktop Computer List 54 Deleting Apple Remote Desktop Lists 54 Creating a Smart Computer List 55 Editing a Smart Computer List 55 Creating a List of Computers of from Existing Computer Lists 56 Importing and Exporting Computer Lists 56 Transferring Computer Lists from Apple Remote Desktop 3 to a New Administrator Computer 57 Transferring Remote Desktop 2 Computer Lists to a New Remote Desktop 3 Administrator Computer 57 Transferring Old v1.2 Computer Lists to a New Administrator Computer Chapter 5 59 Understanding and Controlling Access Privileges 59 Apple Remote Desktop Administrator Access 61 Setting Apple Remote Desktop Administrator Access Authorization and Privileges Using Local Accounts 62 Apple Remote Desktop Administrator Access Using Directory Services 62 Creating Administrator Access Groups 65 Enabling Directory Services Group Authorization 65 Apple Remote Desktop Guest Access 66 Apple Remote Desktop Nonadministrator Access 67 Virtual Network Computing AccessContents 5 68 Command-Line SSH Access 68 Managing Client Administration Settings and Privileges 69 Getting an Administration Settings Report 69 Changing Client Administrator Privileges Chapter 6 71 Setting Up the Network and Maintaining Security 71 Setting Up the Network 72 Using Apple Remote Desktop with Computers in an AirPort Wireless Network 73 Getting the Best Performance 73 Maintaining Security 75 Remote Desktop Authentication and Data Transport Encryption 75 Encrypting Observe and Control Network Data 76 Encrypting Network Data During Copy Items and Install Packages Tasks Chapter 7 77 Interacting with Users 78 Controlling 78 Controlling Apple Remote Desktop Clients 79 Control Window Options 80 Switching the Control Window Between Full Size And Fit-To-Window 80 Switching Between Control and Observe Modes 80 Sharing Control with a User 81 Hiding a User’s Screen While Controlling 81 Capturing the Control Window to a File 81 Switching Control Session Between Full Screen and In a Window 82 Sharing Clipboards for Copy and Paste 82 Controlling VNC Servers 83 Setting up a Non–Mac OS X VNC Server 84 VNC Control Options 85 Configuring an Apple Remote Desktop Client to be Controlled by a VNC Viewer 85 Observing 87 Changing Observe Settings While Observing 88 Changing Screen Titles While Observing 88 Viewing a User’s Account Picture While Observing 88 Viewing a Computer’s System Status While at the Observe Window 90 Shortcuts in the Multiple Screen Observe Window 90 Observing a Single Computer 91 Observing Multiple Computers 91 Observing a Computer in Dashboard 92 Sending Messages 92 Sending One-Way Messages 92 Interactive Chat 93 Viewing Attention Requests 93 Sharing Screens6 Contents 93 Sharing a Screen with Client Computers 94 Monitoring a Screen Sharing Tasks 94 Interacting with Your Apple Remote Desktop Administrator 94 Requesting Administrator Attention 95 Canceling an Attention Request 95 Changing Your Observed Client Icon Chapter 8 96 Administering Client Computers 96 Keeping Track of Task Progress and History 97 Enabling a Task Notification Script 98 Getting Active Task Status 98 Using the Task Feedback Display 98 Stopping a Currently Running Task 99 Getting Completed Task History 99 Saving a Task for Later Use 100 Creating and Using Task Templates 101 Editing a Saved Task 101 Installing Software Using Apple Remote Desktop 101 Installing by Package and Metapackage 103 Installing Software on Offline Computers 104 Installing by Using the Copy Items Command 104 Using Installers from Other Companies 105 Upgrading Software 106 Copying Files 107 Copy Options 108 Copying from Administrator to Clients 109 Copying Using Drag and Drop 110 Restoring Items from a Master Copy 111 Creating Reports 111 Collecting Report Data 112 Using a Task Server for Report Data Collection 113 Report Database Recommendations and Bandwidth Usage 114 Auditing Client Usage Information 116 Finding Files, Folders, and Applications 118 Comparing Software 119 Auditing Hardware 124 Testing Network Responsiveness 125 Exporting Report Information 126 Using Report Windows to Work with Computers 127 Maintaining Systems 127 Deleting Items 128 Emptying the Trash 128 Setting the Startup DiskContents 7 129 Renaming Computers 129 Synchronizing Computer Time 130 Setting Computer Audio Volume 131 Repairing File Permissions 131 Adding Items to the Dock 132 Changing Energy Saver Preferences 133 Changing Sharing Preferences for Remote Login 133 Setting Printer Preferences 135 Managing Computers 135 Opening Files and Folders 136 Opening Applications 137 Quitting Applications Without Logging Out the User 137 Putting a Computer to Sleep 138 Waking Up a Computer 138 Locking a Computer Screen 139 Displaying a Custom Picture on a Locked Screen 139 Unlocking a Computer Screen 140 Disabling a Computer Screen 140 Logging In a User at the Login Window 141 Logging Out the Current User 141 Restarting a Computer 142 Shutting Down a Computer 143 UNIX Shell Commands 143 Send UNIX Command Templates 145 Executing a Single UNIX Command 145 Executing Scripts Using Send UNIX Command 147 Built-in Command-Line Tools 152 Automating Functions 152 Setting the Client’s Data Reporting Policy 153 Creating a Template Data Reporting Policy 154 Designating the Task Server and Setting the Report Data Collection Location 155 Scheduled Tasks 156 Using AppleScript with Remote Desktop 159 Using Automator with Remote Desktop Appendix A 161 Icon and Port Reference 161 Client Status Icons 161 Apple Remote Desktop Status Icons 162 List Menu Icons 162 Task Status Icons 163 System Status Icons (Basic) 163 System Status Icons (Detailed) 164 TCP and UDP Port Reference8 Contents Appendix B 165 Report Field Definitions Reference 165 System Overview Report 167 Storage Report 169 USB Devices Report 169 FireWire Devices Report 169 Memory Report 169 PCI Cards Report 170 Network Interfaces Report 172 Network Test Report 172 Administration Settings Report 173 Application Usage Report 173 User History Report Appendix C 174 AppleScript Remote Desktop Suite 174 Classes and Commands for the Remote Desktop Application. Appendix D 180 PostgreSQL Schema Sample Index 182 9 Preface About This Book What Is Apple Remote Desktop? Apple Remote Desktop is easy-to-use, powerful, open standards-based, desktop management software for all your networked Macs. IT professionals can remotely control and configure systems, install software, offer interactive online help to end users, and assemble detailed software and hardware reports for an entire Mac network. You can use Apple Remote Desktop to:  Manage client computers and maintain, update, and distribute software  Collect more than 200 system-information attributes for any Mac on your network  Store the results in an SQL database and view the information using any of several hardware or software reports  Control and manage multiple computer systems simultaneously, making shutdown, restart, and sending UNIX commands fast and easy  Provide help and remote assistance to users when they encounter problems  Interact with users by sending text messages, observing and controlling users’ screens, and sharing their screens with other client users You can use Apple Remote Desktop to manage your client systems. IT administrators use Remote Desktop in education and business to simplify and empower the management of their organizations computer assets. For system administrators, Apple Remote Desktop can be used to administer large numbers of servers, like a virtual Keyboard-Video-Mouse (KVM) sharing unit. In computer administration environments, it’s the ideal solution for managing remote systems, reducing administration costs, and increasing productivity. Apple Remote Desktop can also be used by educators to facilitate instruction in computer labs or one-on-one learning initiatives. Used in a classroom, Apple Remote Desktop enhances the learning experience and allows teachers to monitor and control students’ computers.10 Preface About This Book Using This Guide The Apple Remote Desktop Administrator’s Guide contains chapters to help you use Remote Desktop. It contains overviews and explanations about Apple Remote Desktop’s features and commands. It also explains how to install and configure Apple Remote Desktop on clients, how to administer client computers, and how to use Remote Desktop to interact with computer users. This guide is provided on the Apple Remote Desktop installation disc and on the Apple Remote Desktop support website as a fully searchable, bookmarked PDF file. You can use Apple’s Preview application or Adobe (Acrobat) Reader to browse the contents of this guide as well as search for specific terms, features, or tasks. Remote Desktop Help Remote Desktop Help is available using Help Viewer. To open Remote Desktop Help, choose Help > Remote Desktop Help. The help files contain the same information found in this guide, and are useful when trying to accomplish a task when this guide is unavailable. Additionally, the Remote Desktop Help contains new information, corrections, and latebreaking information about Apple Remote Desktop. The most up-to-date information is available through Remote Desktop Help before it’s available on the web as an updated PDF file. Notation Conventions This guide and Remote Desktop Help contain step-by-step procedures to help you use Remote Desktop’s commands effectively. In many tasks shown in this manual and in Remote Desktop Help, you need to choose menu commands, which look like this: Choose Edit > Clear. The first term after Choose is the name of a menu in the Remote Desktop menu bar. The next term (or terms) are the items you choose from that menu.Preface About This Book 11 Terminal Command Conventions Commands or command parameters that you might type, along with other text that normally appears in a Terminal window, are shown in this font. For example: You can use the doit command to get things done. When a command is shown on a line by itself as you might type it in a Terminal window, it follows a dollar sign that represents the shell prompt. For example: $ doit To use this command, type “doit” without the dollar sign at the command prompt in a Terminal window, then press the Return key. Where to Find More Information About Apple Remote Desktop For additional information related to Apple Remote Desktop, try these resources. You’ll find more information in the Apple Remote Desktop Read Me file and on the Apple Remote Desktop website: www.apple.com/remotedesktop/ You can find the most recent edition of the Apple Remote Desktop Administrator’s Guide at:  the Apple Server Division Documentation page www.apple.com/server/documentation/  the Remote Desktop section of Apple.com, and www.apple.com/remotedesktop/  the Help Menu in the Remote Desktop application Notation Indicates monospaced font A command or other Terminal text $ A shell prompt [text_in_brackets] An optional parameter (one|other) Alternative parameters (type one or the other) underlined A parameter you must replace with a value [...] A parameter that may be repeated A displayed value that depends on your configuration or settings12 Preface About This Book The Apple Remote Desktop Support website provides a database of technical articles about product issues, use, and implementation: www.apple.com/support/remotedesktop/ To provide feedback about Apple Remote Desktop, visit the feedback page: www.apple.com/feedback/remotedesktop.html For details about how to join the Apple Remote Desktop Mailing list, visit: lists.apple.com/mailman/listinfo/remote-desktop/ To share information and learn from others in online discussions, visit the Apple Remote Desktop Discussions Forum: discussions.info.apple.com/appleremotedesktop/ For more information about PostgreSQL go to: www.postgresql.org For more information about using Apple products for IT professionals go to: apple.com/itpro/1 13 1 Using Apple Remote Desktop Apple Remote Desktop helps you keep Macintosh computers and the software running on them up to date and trouble free. And it lets you interact directly with Macintosh users to provide instructional and troubleshooting support. This chapter describes the main aspects of Apple Remote Desktop’s administration and user interaction capabilities and tells you where to find complete instructions for using them. Administering Computers Apple Remote Desktop lets you perform a wide range of client hardware and software administrative activities remotely, from an administrator computer (a computer on which administrator software resides):  Keep users’ software up to date by using Apple Remote Desktop to deploy software and related files to client computers.  Create reports that inventory the characteristics of client computer software and hardware.  Use Apple Remote Desktop’s remote administration capabilities to perform housekeeping tasks for client computers.14 Chapter 1 Using Apple Remote Desktop You can administer client computers individually, but most Apple Remote Desktop features can be used to manage multiple computers at the same time. For example, you may want to install or update the same applications on all the computers in a particular department. Or you may want to share your computer screen to demonstrate a task to a group of users, such as students in a training room. To manage multiple computers with a single action, you define Apple Remote Desktop computer lists. A computer list is a group of computers that you want to administer similarly. Computer lists let you group and organize computers for administration. Setting up computer lists is easy; you simply scan the network or import the identity of computers from files. A particular computer can belong to more than one list, giving you a lot of flexibility for multicomputer management. A computer can be categorized by its type (laptop, desktop), its physical location (building 3, 4th floor), its use (marketing, engineering, computing), and so forth. Once you’ve set up computer lists, you can perform most of the computer administration activities described next for groups of client computers. Marketing department Engineering departmentChapter 1 Using Apple Remote Desktop 15 Deploying Software Apple Remote Desktop lets you distribute software and related files to client computers from your Apple Remote Desktop administrator computer or from a computer running Mac OS X Server. Distributing Installer Packages You can distribute and automatically install packages in .pkg and .mpkg formats. Apple Remote Desktop lets you install software and software updates on one or more client computers without user interaction or interruption, or even if no user is logged in. After installation, Apple Remote Desktop erases the installer files. If the computers need to be restarted, as they do following an operating system update, you can restart them from Apple Remote Desktop. Xserve cluster node Marketing department Engineering department Deploy configuration files Deploy drag-and-drop application folders Deploy install packages (.pkg or .mpkg) Network install images NetBoot images Deploy UNIX shell scripts Set startup partition Administrator computer Mac OS X Server16 Chapter 1 Using Apple Remote Desktop For example, you can use Apple Software Update to download an iCal update or an operating system update to a test computer. If the update works as expected and introduces no compatibility issues, copy the installer package to the administrator computer to distribute to computers that need upgrading. Note that this approach conserves Internet bandwidth, because only one copy of the package needs to be downloaded. You can also use Apple Remote Desktop to deploy new versions of computational software to Xserve computers in a cluster node. You can use the PackageMaker tool (included on the Apple Remote Desktop installation CD and with Apple’s developer tools) to create your own installer packages, such as when you want to:  Distribute school project materials or business forms and templates  Automate the installation of multiple installer packages  Deploy custom applications Before performing remote installations, you can send an Apple Remote Desktop text message to notify users, perhaps letting them know that you’ll be using Apple Remote Desktop to lock their screens at a particular time before you start the installation. Using Network Install Images You can also distribute and install software, including the Mac OS X operating system, by using Network Install images. On Mac OS X Server, use the Network Image Utility to create a Network Install image. You can create the image by cloning a system that’s already installed and set up, or by using an installation disc or an image downloaded using Apple Software Update. If you choose to auto-install, you won’t have to interact with each computer. On the Apple Remote Desktop administrator computer, set the startup disk of remote client systems to point to the Network Install image, and then remotely reboot the clients to initiate installation. Before initiating installations that require computers to be restarted afterwards, send an Apple Remote Desktop text message to client users to notify them of a pending installation. For example, tell users you’ll log them off at 5:00 p.m. to install an operating system update. Using NetBoot Images Another kind of system image you can create using Mac OS X Server is a NetBoot image. Like a Network Install image, a client computer uses NetBoot images to start up. Unlike a Network Install image, the boot software is not installed on the client system. Instead, it resides on a remote server. It is recommended you use a NetBoot image that has Apple Remote Desktop installed and configured. Otherwise, administering the computer using Apple Remote Desktop after starting up from NetBoot is impossible.Chapter 1 Using Apple Remote Desktop 17 Client computers that boot from a NetBoot image get a fresh system environment every time they start up. For this reason, using NetBoot images is useful when a particular computer is shared by several users who require different work environments or refreshed work environments, or when you want to start a new experiment or use a different computing environment in a cluster node. You can use Apple Remote Desktop to set the startup disks of client systems to point to the NetBoot image, and then restart the systems remotely using Apple Remote Desktop. Users can also choose a NetBoot image for startup by using the Startup Disk pane of System Preferences. With just a few clicks you can reconfigure all the computers in a lab or cluster without having to manually restart and configure each computer individually. Distributing Preference Files Managed computers often require a standard set of preferences for each instance of an application. Use Apple Remote Desktop to distribute preference files when you need to replace or update a application preferences. For example, you can copy a standardized preference file to the currently logged in user’s Library/Preferences folder. Using UNIX Shell Scripts You can use Apple Remote Desktop to distribute and run UNIX shell scripts on client computers. For example, a script can mount an AFP server volume, from which it downloads a disk image to client computers. The script might also download an installer package and then perform a command-line installation. On an Xserve in a cluster node, you could also run a script that mounts an Xserve RAID disk designed for high throughput and then downloads large data sets for processing. You can also use Apple Remote Desktop to distribute AppleScript files that automate PDF workflows, or job instructions for computational clusters. Distributing Drag-and-Drop Applications You can distribute and install self-contained (drag-and-drop) applications by copying them to one or more client computers. Use this approach, for example, to distribute application updates. Verifying Installations To check whether an installation has been completed successfully, use Apple Remote Desktop’s remote control capabilities. For example, you can start an application remotely, or search for particular files. You can also use the File Search report to verify that all files for an application are installed correctly.18 Chapter 1 Using Apple Remote Desktop Taking Inventory Apple Remote Desktop lets you capture data describing the attributes of client computers, then generate reports based on the data. You specify how often you want to capture data, the data you want to capture, and the computers you want to profile. You can collect data just before generating a report if you need up-to-the-minute information. Or you can schedule data to be collected by Apple Remote Desktop at regular intervals and stored in its built-in SQL (Structured Query Language) database for use on an as-needed basis. You can also specify where you want the database to reside—on the local administrator computer, or on a server where the Apple Remote Desktop administrator software is installed and always running, so data can be captured on an ongoing basis. Using the collected data, Apple Remote Desktop generates reports tailored to your specifications. Xserve cluster node Marketing department Engineering department Administrator computer Mac OS X Server ARD SQL database ARD SQL database SQL toolsChapter 1 Using Apple Remote Desktop 19 File Search Report Use the File Search report to search client systems for specific files and folders and to audit installed applications. This report can help you find out how many copies of a particular application are in use so you don’t violate license agreements. Spotlight File Search Use the Spotlight Search report to search Tiger client systems for specific files and folders. The information in the report is updated as files matching your search change on the client systems. Software Version Report Use the Software Version report to make sure that all users have the latest application versions appropriate for their systems. Software Difference Report Use the Software Difference report to detect application versions that are out of date, nonstandard, or unacceptable for some other reason. Or, you can learn whether a user has installed an application that shouldn’t be installed. System Overview Report The System Overview report makes visible a wide variety of client computer characteristics. Using this report, you can review information about a client’s AirPort setup, computer and display characteristics, devices, network settings, system preferences, printer lists, and key software attributes. There are numerous uses for this report, such as identifying problems or verifying system configurations before installing new software, or determining how many devices of a particular type (such as scanners) are in a particular lab. Hardware Reports Several reports provide details about particular hardware used by client computers— storage, FireWire devices, USB devices, network interfaces, memory, and PCI cards. Use these reports to determine, for example, which computers need more memory, which computer has the fastest processor speed, and how much free space is left on a particular disk. Administration Settings Report Use the Administration Settings report to determine which Apple Remote Desktop administrator privileges are enabled or disabled for you in the Sharing pane of System Preferences on individual client computers. User History Report Use the User History report to show you who has logged in to a client, how they logged in, and for how long.20 Chapter 1 Using Apple Remote Desktop Application Usage Report Use the Application Usage report to find out which applications have been running on your client computers and who ran those applications. Network Test Report A Network Test report helps you measure and troubleshoot the communication between your administrator computer and your client computers. The Network Interfaces report might also help troubleshooting network hardware issues. Use this report to help identify reasons for network communication problems that could affect Apple Remote Desktop. For example, if you’re unable to copy items to particular client computers from the administrator computer, you may find you have a bad connection to the computers. Using this information can help you isolate the problem to a particular cable or hub. Generating Your Own Reports Because the Apple Remote Desktop database is in standard SQL format, you can also use your favorite SQL scripts to query, sort, and analyze the collected data. In addition, you can export data from the database into a file so you can import it for viewing in a different program, such as a spreadsheet application.Chapter 1 Using Apple Remote Desktop 21 Housekeeping Apple Remote Desktop provides several ways to remotely control client computers for housekeeping activities, which you can conduct using one or more Apple Remote Desktop windows. Managing Power State Use Apple Remote Desktop to control the power state of client computers. For example, you may need to have all computers turned off during maintenance of a power generation unit or during a holiday shutdown. You can send an Apple Remote Desktop text message reminding users to shut down their computers at a particular time. Any computers still running when you need to start maintenance can be detected and shut down remotely with Apple Remote Desktop. Xserve cluster node Marketing department Engineering department Administrator computer Execute UNIX shell script Restart/ shutdown/sleep Remote screen control Empty Trash Set startup partition Send text notification Mac OS X Server NetBoot images22 Chapter 1 Using Apple Remote Desktop Locking Computer Screens You can lock the screens of client computers for specified durations when you don’t want the computers to be used. For example, you may need to perform network maintenance and want to make sure computers don’t use the network for a few hours. You can display custom pictures or text messages on locked computer screens to let users know when the computers are available again. Reclaiming Disk Space Periodically empty the Trash on client computers to conserve disk space. Automating Periodic Maintenance Use AppleScript and UNIX shell scripts to automate periodic maintenance, such as checking permissions or deleting log files. Controlling Screens Use Apple Remote Desktop’s remote screen control to perform activities on the desktop of Xserve computers, or use graphical applications on them. Apple Remote Desktop replaces the need for KVM (keyboard-video-mouse) switches for accessing Xserve computers without a monitor attached. You can also remotely control a user’s computer to help determine reasons for slow performance or other problems. Changing Startup Disks Change the startup disk of a client computer to perform diagnostic or troubleshooting activities. For example, start up a computer using a server-based NetBoot image that’s been set up for troubleshooting. When you’re finished, reset the startup disk to the original boot volume. Managing Shared Computers On computers that are shared among users, check for files that need to be deleted, close applications, log users off, or perform other activities needed to prepare computers for the next users. Supporting Users Apple Remote Desktop lets you interact with users from your administrator computer in these ways:  Provide help: respond to users who need help by using Apple Remote Desktop to receive user requests and to remotely diagnose and fix problems.  Interact: conduct instructional interactions with students in a school or corporate training environment—from controlling or observing student screens to sharing your screen with all your students in order to perform a demonstration.Chapter 1 Using Apple Remote Desktop 23 Providing Help Desk Support When a user is having trouble, Apple Remote Desktop provides several ways to interact with the user and his or her computer to diagnose and fix the problem. Requesting Help A user can discreetly notify you of a problem by sending a request for help using an Apple Remote Desktop text message. Users initiate requests using the commands in the menu that appears when they click the Apple Remote Desktop icon in the menu bar. A notification on the administrator computer alerts you to the message, and you can use several techniques to obtain more information and troubleshoot the problem. Chatting with the User Conduct two-way Apple Remote Desktop text communication with the user to obtain more information. Screen Monitoring Use Apple Remote Desktop to observe the user’s screen if you need more details to understand the problem. Marketing department Engineering department Copy items Administrator computer Control, observe, and share screens Use text chat24 Chapter 1 Using Apple Remote Desktop Screen Controlling Use Apple Remote Desktop to control the user’s screen in order to diagnose and fix the problem. You may have unlimited control, or a user can grant you temporary guest access so you can control the computer only during troubleshooting. There are two levels of control available. You can take complete control of the user’s computer, or you can share control of the keyboard and mouse with the user. Screen Sharing If the problem is caused by incorrect actions by the user, share your screen with the user as you demonstrate the correct way to perform the action. Using Reports Use hardware and software reports as diagnostic tools to determine whether the client computer setup is part of the problem. For example, if a user can’t save his or her work, the storage report can help you determine whether it’s a disk space issue. Deploying New Software or Files If software or configuration settings are part of the problem, use Apple Remote Desktop to copy new configuration files, installer packages, or other items to client computers.Chapter 1 Using Apple Remote Desktop 25 Interacting with Students Apple Remote Desktop helps instructors teach more efficiently by letting them interact with student computers individually or as a group. Using Text Messages Send Apple Remote Desktop text messages to communicate with students. For example, notify them that a classroom activity will start soon or that they have ten minutes to finish an examination. Monitoring Student Computers View student computer screens on your computer, so you can monitor student activities or assess how well they’re able to perform a particular task. You can also monitor the applications running on any student’s computer. Sharing Screens Display your screen or a student’s screen on other student computers for training and demonstration purposes. Controlling Screens Show students how to perform tasks by controlling their screens from your computer, opening applications and using files as required. Classroom Administrator computer Observe and share one or multiple screens One-to-one help desk support Broadcast text messages Lock screens Distribute items electronically Open applications or files Control screen Log out students26 Chapter 1 Using Apple Remote Desktop Locking Screens Lock student screens to prevent students from using their computer when you want them to focus on other activities. Terminating Computer Use Remotely log students out or shut down their computers at the end of a class or school day. Distributing and Collecting Files Distribute handouts electronically, at a time that won’t disrupt class activities or when they’re needed for the next class activity, and collect homework files. Automating Website Access Open a webpage on all student computers. Drag a URL from Safari to your desktop, then copy it to student computers and open it in Safari. You can also copy files and open them in the appropriate applications on student computers. Providing One-to-One Assistance Provide help when a student needs it, conducting private and discreet computer-tocomputer interactions. Finding More Information You’ll find detailed instructions for performing the tasks highlighted in this chapter— and more—throughout this manual. To learn more about See information for Starting on page Remote Dekstop interface Window and icon functions page 28 Computer lists Creating computer lists page 49 Apple Remote Desktop administration Administrator privileges Administrator computers page 59 Controlling screens Controlling page 78 Observing screens Observing page 85 Deploying software Installing software Upgrading software page 101 Distributing files Copying files page 106 Taking inventory Data collection options Auditing software Auditing hardware Network responsiveness Customizing reports Exporting report data page 111 Client use reporting User login accounting Application usage page 114Chapter 1 Using Apple Remote Desktop 27 Additional information can be obtained at several Apple websites:  For information about NetBoot and Network Install, download the system imaging administration guide at: www.apple.com/server/documentation  You can find PackageMaker’s documentation at Apple’s Developer Connection: http://developer.apple.com/documentation/DeveloperTools/Conceptual/ SoftwareDistribution/index.html? Housekeeping tasks Deleting items Emptying the Trash Setting startup volumes Renaming computers Sleeping and waking Locking screens Logging users out Restart and shutdown page 127 Automating tasks Configuring data gathering Scheduling tasks Using UNIX shell scripts page 152 To learn more about See information for Starting on page2 28 2 Getting to Know Remote Desktop Remote Desktop is the administrator application for Apple Remote Desktop. Its attractive interface is powerful, yet simple to use. Remote Desktop’s interface is customizable, allowing you to get the information you want quickly, the way you want it. This chapter contains screenshots and short descriptions of Remote Desktop’s interface, as well as detailed instructions for customizing the appearance and preferences of the application. You will learn about:  “Remote Desktop Human Interface Guide” on page 28  “Configuring Remote Desktop” on page 36  “Interface Tips and Shortcuts” on page 37 Remote Desktop Human Interface Guide The following sections give basic information about the human interface of Remote Desktop, Apple Remote Desktop’s administrator application.  “Remote Desktop Main Window” on page 29  “Task Dialogs” on page 31  “Control and Observe Window” on page 32  “Multiple-Client Observe Window” on page 33  “Report Window” on page 34  “Changing Report Layout” on page 35Chapter 2 Getting to Know Remote Desktop 29 Remote Desktop Main Window The main window of Remote Desktop has a customizable toolbar, groups of lists, tasks, and scanners on the left, and the main window area to the right. “List Menu Icons” on page 162 contains icons seen in the list menu of the main window. A All Computers list: The All Computers list is a list of all client computers that you plan to administer. It includes all the clients you have authenticated to, as well as the client computers that you plan to authenticate to. Computers need to be in the All Computers list before you can command or administer them. If you have a 10-client license, the All Computers list can contain only 10 computers. B Apple Remote Desktop computer lists: A list of computers you create to group computers in ways that are convenient for you. Any list is a subset of the client computers in the All Computers list. If you add a computer directly to a computer list, it is added automatically to the All Computers list as well. C Smart computer lists: A smart computer list is a list of computers which is a subset of the client computers in the All Computers list that meet a predetermined criteria. Smart Computer lists update themselves based on your criteria compared to the contents of the All Computers list. D Group folders: Groups are tools to help you organize all your possible lists, tasks, and scanners. Groups look like folders, and can be collapsed to hide the group contents. E Saved tasks: Saved tasks are listed in the left portion of the main window. They have the icon of the type of task and have a user-changeable name. A B C D E F G I H K L J30 Chapter 2 Getting to Know Remote Desktop F Scanner: Scanners find clients to add to the All Computers list. You can make new scanners and customize them for your needs. See “Making a New Scanner” on page 52. G Task server list: This lists tasks delegated to the Task Server, rather than run those run directly from the application. When all the target computers have come online and participated in the task, the task is labeled as complete. H Active tasks list: This list shows all tasks that are currently running or scheduled and uncompleted. I Task history list: The task history list shows a list of most recently run tasks, as defined in the Remote Desktop preferences. You can inspect each task by double-clicking it. Once a task is completed (whether successfully or not) it is moved to the Task History list. J Task status icon: These icons represent the current state of a task. See “Task Status Icons” on page 162. K Client status icon: Icon representing the current state of a client computer. See “Client Status Icons” on page 161. L Customizable toolbar: The toolbar can be fully customized with icons of your most-used Apple Remote Desktop features.Chapter 2 Getting to Know Remote Desktop 31 Task Dialogs When you click a task, a dialog appears to let you set task parameters or confirm the task. A Task type header: This header area shows you the kind of task represented. B Saved task name: When you save a task, you name it for your own use. C Task configuration area: This area is different for every task. It’s where you set operating parameters for the task to be performed. D Participating computers: This area shows you the computers that will be affected by the task. You can add or remove computers in this area without changing computer list membership. E Schedule task button: When you click this button in a task dialog, you can set a time to perform the task as well as repeat the task. See “Scheduled Tasks” on page 155 for more information. F Save task button: When you click this button in a task dialog, you can name and save the task as configured. Saved tasks appear in the left side of Remote Desktop’s main window. G Task templates: This control allows you to save current task configuration settings, or apply previously saved settings to the current task. These templates are stored on a per-task basis. For example, the Send UNIX Commands template pop-up has an extensive list of built-in templates, while other tasks may have none. A B G C D E F32 Chapter 2 Getting to Know Remote Desktop Control and Observe Window This window is the same for both controlling and observing a single client. The only difference is the state of the Observe or Control toggle button. When it’s selected, you have control over the remote client. A Observe or control toggle: When this button is selected, you have control over the remote client. B Share mouse control: When this button is selected, you share mouse control with the user. C Fit screen in window: When this button is selected, the remote client is scaled to the Control window size. D Lock computer screen for control: When this button is selected, the remote client screen shows a lock, and your view allows you to view the client desktop normally. E Capture screen to file: When this button is clicked, the remote client screen is saved to a local file at the selected image quality. F Fit screen to full display: When this button is selected, your display doesn’t show your computer desktop, only that of the remote computer, at full possible resolution. G Get clipboard from client: When this button is clicked, the contents of the remote client Clipboard are transferred to the local Clipboard. A B C D E F G H J IChapter 2 Getting to Know Remote Desktop 33 Multiple-Client Observe Window When you observe many clients at the same time, they all appear in the same window. If you have more computers than will fit in the window, they are divided across several pages. H Send clipboard to the client: When clicked, the remote client Clipboard receives the contents of the local Clipboard. I Image Quality: Adjusts the screen color depth from black and white to millions of colors. J Desktop of Controlled Computer: Resize this window from the lower right corner. A Page Delay: Adjusts the number of seconds before automatically advancing to the next page of screens. B Computers Per Page: Adjusts the number of client screens visible on each page. C Image Quality: Adjusts the screen color depth from black and white to millions of colors. D Display Computer Information: Shows the computer information area, which contains desktop titles, account pictures, and status icons. E Computer title selector: Changes the titles displayed underneath the client screens (you can choose the computer name, IP address, or hostname). F Account picture: Shows the login icon of the currently logged in user. H A B C I G E I D F34 Chapter 2 Getting to Know Remote Desktop Report Window Reports serve as valuable shortcuts when you’re copying files and organizing computer lists. G Computer status: Shows basic computer status beneath each client screen. H Cycle through pages: Manually advances to the next page of screens. I View Options: Reveals the view option controls. J Observed computers: Contains the scaled desktops of the observed client computers. A Report category: Most reports have subcategories to help you find the information you want. In the report window, you switch between the subcategories using these tabs. B Save report to file: Saves the report to a plain text file. C Print: Formats and prints the report window. D Open selected: Opens the item selected in the report. The item opens on the client computer. C B A C B D E FChapter 2 Getting to Know Remote Desktop 35 Changing Report Layout You can customize report layouts for your own purposes. By default, reports include a column for each information type you selected before running the report, in the order presented in the report dialog. The columns in the report are initially sorted by computer name. You can resize or rearrange the columns of a report, as well as sort the rows by column. Additionally, in the File Search report, you can choose what information is displayed about a found item. By default, the item name, kind, parent path, actual size, and modification date are displayed. To change what information is displayed: 1 In the File Search report window, select or deselect each report column as desired. 2 After making your selections, click Generate Report as usual. When the report window appears, you can rearrange the columns or sort by a different column. E Delete selected: Deletes the item selected in the report from the remote computer. F Copy to this computer: Copies selected items to the administrator computer. Report column If checked, will show Name The item name Parent path The path to the folder that the item is in Full path The full file path Extension The file extension indicating the file type (.app, .zip, .jpg) Date modified The last date and time the file was changed and saved Date created The date and time the file was created Actual size Actual file size, in kilobytes or megabytes Size on disk Amount of disk space used by the file, in kilobytes Kind File, folder, or application Invisible A checkmark indicating whether it is visible in the Finder Version number If an application, the version reported Version string If an application, the version reported Owner The item owner’s short name Group The item’s group name Permissions The item’s UNIX permissions (for example, -rw-r--r--) Locked A checkmark indicating whether it is a locked file36 Chapter 2 Getting to Know Remote Desktop Configuring Remote Desktop You can configure the Remote Desktop administrator application to meet your work needs. Remote Desktop has an interface that is both flexible and functional. Customizing the Remote Desktop Toolbar The Remote Desktop application has a fully customizable toolbar, which provides a quick way to perform tasks. To perform a task, just click the appropriate icon in the toolbar. To show or hide the toolbar, click the toolbar button in the upper-right corner of the application window. You can add, remove, or rearrange the task icons in the toolbar to suit your needs. To customize the application toolbar: 1 Choose Window > Customize Toolbar. 2 Drag your favorite toolbar items or the default set of items to the toolbar. To remove an item, drag it from the toolbar. To rearrange items, drag them into the order you prefer. 3 Choose whether to display toolbar items as text, icons, or both. Selecting “Use Small Size” shrinks the items in the toolbar. Setting Preferences for the Remote Desktop Administrator Application In Remote Desktop preferences, you can select options that affect how the administrator application interacts with client computers. To open the Preferences window:  Choose Remote Desktop > Preferences. In the General pane, you can set:  What double-clicking a client computer does (Get Info, Control, Observe, Text Chat)  Whether to show the client idle time  What warnings may appear when quitting the application  A new serial number  A new Remote Desktop application password In the Control & Observe pane, you can set:  Whether a remote screen is shown in a window or a full screen  Whether control of the mouse and keyboard is shared with the client computer when the client is controlled  Whether a remote screen is shown at its actual size in a window or if it shrinks to fit the window In the Task Server pane, you can set:  Whether Remote desktop is using another computer as a Task Server, or whether this copy of Remote Desktop is being used as a Task ServerChapter 2 Getting to Know Remote Desktop 37  Whether other Apple Remote Desktop administrators can access your local Task Server  Whether clients collect user and application tracking data  A saved template for scheduling client reporting policies In the Labels pane, you can set:  Label colors and text for labeling computers In the Tasks pane, you can set:  Whether to automatically change focus to the active task  Whether to execute a notification script on task completion  Limits on task history list contents and time until removed In the Security pane, you can set:  Whether to accept messages from client users  Whether to allow control of the computer while Remote Desktop is active  The default encryption preference for control and observe sessions  The default encryption preference for Copy Items and Install Packages tasks  Which features of Remote Desktop are available to nonadministrator users See “Apple Remote Desktop Nonadministrator Access” on page 66. Interface Tips and Shortcuts There are a number of features of the Remote Desktop interface which make it particularly flexible and powerful. The following lists a few built-in shortcuts to features which can make using Remote Desktop more productive. Computers can be selected from any window Any computer in any window—report windows, task windows, computer lists, observe windows—can be a target for some task. For example, if you are observing 10 computer screens and need to send a text message to one, select the screen with a single click and then choose Interact > Send Text Message. Likewise, if you get a software report on 50 computers and notice that one of the computers is missing some vital piece of software, you can drop that software onto the selected computer within the report window. Treating all windows as possible computer selection lists for tasks may save you lots of time switching between the Remote Desktop window and other windows as you accomplish your work.38 Chapter 2 Getting to Know Remote Desktop Drag and drop works on configuration dialogs Configuration dialogs accept dragged items. Computer lists in the dialogs accept dragged computers. The Copy Items dialog accepts dragged files to copy, without having to browse the file system for them. Save yourself time and effort by dragging available items to dialogs rather than browsing for them. Making lists from reports or other lists You may need to make a list based on the outcome of some report, but you don’t know which computers will need to be included. After getting a report and sorting on the desired column, you can select the computers and make a new list from the selection. If you double-click the list icon, you open another window containing the computers in the list. This is useful for comparing lists, or for using the new window as a source from which to drag computers to other lists. Saved Tasks and Task Templates save you time You may spend a lot of time coming up with the perfect software search to find exactly what you need. You shouldn’t recreate that search every time you need it. Save your tasks, and duplicate them. With a little editing, you can have a number of similar saved tasks for specific uses. Alternatively, you can use task templates to save settings across task dialogs, applying the same settings through various tasks.3 39 3 Installing Apple Remote Desktop To use Apple Remote Desktop, install the administration software on the administrator computer first, and then install and enable the client software on the computers you want to manage. You’ll need your install disc, the serial number, and either the printed Welcome instructions, or these instructions. This chapter describes how to install Apple Remote Desktop for system administration and user interaction and gives complete setup instructions. You can learn about:  “System Requirements for Apple Remote Desktop” on page 39  “Installing the Remote Desktop Administrator Software” on page 40  “Setting Up an Apple Remote Desktop Client Computer for the First Time” on page 41  “Upgrading the Remote Desktop Administrator Software” on page 41  “Upgrading the Client Software” on page 42  “Creating a Custom Client Installer” on page 44  “Considerations for Managed Clients” on page 46  “Removing or Disabling Apple Remote Desktop” on page 46 System Requirements for Apple Remote Desktop Administrator and client computers:  Mac OS X or Mac OS X Server version 10.3.9 or later (Mac OS X version 10.4 or later is required for some features).  Mac OS Extended (HFS+) formatted hard disk.  For observing and controlling other platforms: a system running VNC-compatible server software. NetBoot and Network Install (optional)  Mac OS X Server version 10.3 or 10.4 with NetBoot and Network Install services enabled40 Chapter 3 Installing Apple Remote Desktop Network Requirements  Ethernet (recommended), AirPort, FireWire, or other network connection See “Setting Up the Network” on page 71 for more information. Installing the Remote Desktop Administrator Software To set up Apple Remote Desktop on administrator computers, you install the software on the computer you plan to use to administer remote computers. Then, you open the application setup assistant, and add to the main list of computers. To install Apple Remote Desktop on an administrator computer: 1 Insert the Apple Remote Desktop installation disc. 2 Double-click the Remote Desktop installer package and follow the onscreen instructions. The Remote Desktop application will be installed in the Applications folder. 3 Launch Remote Desktop (in the Applications folder). The Remote Desktop Setup Assistant appears. 4 Enter the serial number. The serial number can be found on the Apple Remote Desktop Welcome document that came with your software. Optionally, enter a registration name and organization. 5 Click Continue. 6 Enter a Remote Desktop application password and verify it. The Remote Desktop application password is used to encrypt names and passwords of client computers for Apple Remote Desktop. You can store this password in your keychain for convenience, or you can require that the password be entered each time you open Remote Desktop. 7 If you have another unlimited-licensed copy of Apple Remote Desktop acting as a Task Server (a dedicated computer running Remote Desktop for report data collection and delegated install tasks), enter the server address and click Continue. 8 Set the default data collection scope and time for newly administered computers. These settings will be stored as the default upload schedule, which can be applied to computers when you add them for administration. For more detailed information, see “Setting the Client’s Data Reporting Policy” on page 152. 9 Click Done. The main application window appears.Chapter 3 Installing Apple Remote Desktop 41 10 Configure some client computers for administration, find them in a scanner, and add them to a computer list. See:  “Setting Up an Apple Remote Desktop Client Computer for the First Time” on page 41  “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49 Setting Up an Apple Remote Desktop Client Computer for the First Time The following section contains information on setting up Apple Remote Desktop 3 on client computers. Since Apple Remote Desktop v1.2 was included with Mac OS X v10.3 computers and Apple Remote Desktop v2.2 was installed with Mac OS X v10.4 computers, all Apple Remote Desktop 3 client installations are upgrade installations, even if you are setting up clients for the first time. See “Upgrading the Client Software” on page 42 for more information. If the Apple Remote Desktop client software was removed from the computer, you can install a fresh copy of the most recent client software by installing Apple Remote Desktop manually. See “Method #2—Manual Installation” on page 43 for more information. If you’re setting up Mac OS X Server for the first time using Server Setup Assistant, you can enable Apple Remote Desktop as one of the initial services. This allows you to administer a server immediately after server software installation by providing Remote Desktop with the user name and password of the default system administrator. Upgrading the Remote Desktop Administrator Software Upgrading Remote Desktop is just like installing it for the first time. The only difference is that the final button in the installer reads “Upgrade” rather than “Install.” The installer upgrades existing software to its latest version, imports previously created lists, and restarts the underlying processes after completion. See “Installing the Remote Desktop Administrator Software” on page 40, for detailed instructions. If you are upgrading from version 1.2 and changing administrator computers, you’ll need to transfer your existing computer lists. See “Transferring Old v1.2 Computer Lists to a New Administrator Computer” on page 57. Be sure to transfer your lists from Apple Remote Desktop v1.2 to the new computer before upgrading to Apple Remote Desktop 3. If you upgrade from version 1.2 to version 3 on the same administrator computer, this list migration is done for you.42 Chapter 3 Installing Apple Remote Desktop Upgrading the Client Software This section contains information on installing Apple Remote Desktop 3 on client computers. Since Apple Remote Desktop client software was automatically included on the clients running Mac OS X v10.3 and v10.4, all Apple Remote Desktop 3 installations are upgrade installations, even if you are setting up clients for the first time. You can only upgrade Apple Remote Desktop v1.x and v2.x computers if they meet the minimum system requirements (see “System Requirements for Apple Remote Desktop” on page 39). Please note that there is no supported “downgrade” to any previous version, and if you upgrade the client computers to version 3, you will not be able to administer them with earlier versions of Remote Desktop. There are two methods to upgrade the client computer’s software. Method #1—Remote Upgrade Installation This method works best with existing clients already configured using a previous version of Apple Remote Desktop. If used with existing administered clients, use Remote Desktop to identify those clients running a previous version. You may then upgrade them to the latest version. The main benefit of this upgrade method is the ease of installation and the retention of previous client settings, if any. This method only works for Apple Remote Desktop 1.2 clients and later. Earlier versions of Apple Remote Desktop like 1.0 must be upgraded to version 1.2 using Mac OS X’s Software Update, or they must be updated manually. See “Method #2—Manual Installation” on page 43 for more information. To upgrade existing client software remotely using Apple Remote Desktop: 1 Enable the existing version of Apple Remote Desktop on the client computers. 2 Configure the clients for administration. See “Setting Apple Remote Desktop Administrator Access Authorization and Privileges Using Local Accounts” on page 61. 3 If the client computers are not in an existing Remote Desktop computer list, find the client computers using an Apple Remote Desktop scanner. See “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49 for more information. 4 Select the client computers to be upgraded. 5 Choose Manage > Upgrade Client Software. 6 Click Upgrade.Chapter 3 Installing Apple Remote Desktop 43 Method #2—Manual Installation This method works best if you have never enabled Apple Remote Desktop on your clients and have an existing software distribution infrastructure. This method also allows for the greatest power and configuration flexibility. Also, if you don’t want Apple Remote Desktop to upgrade your clients using the Upgrade Client Software feature, you can perform a manual upgrade. The custom installer not only installs the needed software but also prepares and configures the client computer for administration and can be configured to add or edit user names and passwords for Apple Remote Desktop authentication. To manually upgrade the client software: 1 Use Remote Desktop to create a client software installer package. For detailed instructions, see “Creating a Custom Client Installer” on page 44. 2 Copy and install the package on the client computers. You need the name and password of a user with administrator privileges on the computer to install the package. There are several ways to do this. For example, you can:  Distribute the package by removable media, such as a CD.  Copy the installer to the clients over the network using file sharing.  Copy the installer to the clients using command-line tools like scp (if ssh is enabled), and use Apple’s command-line installation tool, “installer,” to install the package remotely. This process is described in detail in “Upgrading Apple Remote Desktop Clients Using SSH” on page 43.  Add the custom installer package to a Network Install image, using System Image Utility to automatically include the software and your custom settings when clients install the operating system using Mac OS X Server 10.4’s NetBoot and Network Install features. Upgrading Apple Remote Desktop Clients Using SSH You may not be able to or want to use Remote Desktop to upgrade existing clients to Apple Remote Desktop 3. If the clients have SSH enabled (called Remote Login in System Preferences), and are available on the network, you can still upgrade the client computers. You still need to use Remote Desktop to create a custom installer package. You also need the user name and password of a user with system administrator privileges on the client computer. Warning: Custom install packages that create user names contain sensitive password data. Take care to store such custom installers securely.44 Chapter 3 Installing Apple Remote Desktop To upgrade existing client software using SSH: 1 Create the custom client installer package. For detailed instructions, see “Creating a Custom Client Installer” on page 44. 2 Open the Terminal application (located in /Applications/Utilities/). 3 Copy the installer package to the client computer by typing: $ scp -r @: For other options, see the scp man page. 4 Log in to the client computer by typing: $ ssh @ For other options, see the ssh man page. 5 On the client computer, install the package by typing: $ sudo installer -pkg -target / For other options, see installer man page. Creating a Custom Client Installer To install the Apple Remote Desktop client software on computers, you use the administrator application, Remote Desktop, to create a custom client installer. The custom client installer not only installs the Apple Remote Desktop system software, but can create user names and passwords on the client computer with their Apple Remote Desktop privileges already assigned. You’ll use an assistant to create a custom client installer package. Any values set in the custom installer will apply to all the computers that receive the installation. While creating a custom installer, you will have a chance to create new Apple Remote Desktop administrator user names with passwords, and automatically set Apple Remote Desktop access privileges and preferences. To create the client installer: 1 Open Remote Desktop. 2 Choose File > Create Client Installer. The Custom Installer Setup Assistant appears. 3 Choose to create a custom installer and click Continue. If you choose not to create a custom installer, you can create a basic installer that sets no preferences on the client computer. Warning: Custom installer packages that create user names contain sensitive password data. Take care to store and transmit such custom installers securely.Chapter 3 Installing Apple Remote Desktop 45 4 Click Continue to begin creating a custom installer. 5 Choose whether to start Remote Desktop sharing at system startup. This changes the setting found in the Sharing pane of System Preferences. 6 Choose whether to hide or show the Apple Remote Desktop menu bar icon. 7 Click Continue. 8 Choose whether to create a new user for Apple Remote Desktop login. Click Continue. A new user account can be created to grant Apple Remote Desktop administrator privileges. Creating a new user account does not overwrite existing user accounts or change existing user passwords. If you choose not to create a new user account, skip to step 10 after clicking Continue. 9 Add a new user by clicking Add and filling in the appropriate information. Click OK after adding each user, and click Continue when you’re ready to go on. 10 Choose whether to assign Apple Remote Desktop administrator access privileges to Directory Services groups. If you choose to do so, select “Enable directory-based administration.” See “Apple Remote Desktop Administrator Access Using Directory Services” on page 62 for more information on using this method to grant Apple Remote Desktop administrator access. 11 Choose whether to assign Apple Remote Desktop administrator access privileges to specific users. Click Continue. If you choose not to assign administrator access privileges, skip to step 14. 12 Click Add to designate a user to receive Apple Remote Desktop access privileges. 13 Provide the user’s short name and set the privileges as desired. See “Apple Remote Desktop Administrator Access” on page 59 for more information. Click OK after each user, and click Continue when you’re ready to go on. 14 Choose whether to allow temporary guest control by requesting permission on the client computers. See “Considerations for Managed Clients” on page 46 for more information. 15 Choose whether to allow non–Apple VNC viewers to control the client computers, and click Continue. See “Virtual Network Computing Access” on page 67 for more information. 16 If desired, select and enter information in any or all of the four System Data fields. This information appears in Apple Remote Desktop System Overview reports. For example, you can enter an inventory number for the computer, a serial number, or a user’s name and telephone number.46 Chapter 3 Installing Apple Remote Desktop 17 Click Continue. 18 Select a location for the installer. 19 Click Continue to create the installer. An installer metapackage (.mpkg file) is created in the designated location. 20 Click Done. Considerations for Managed Clients If you plan on restricting what applications can open on a managed client, you’ll need to make sure that Apple Remote Desktop’s processes are allowed to run. A managed client is a client computer whose environment is governed by Mac OS X Server’s Workgroup Manager. The following options need to be enabled in Workgroup Manager’s client and group application preference settings:  “Allow approved applications to launch non-approved applications”  “Allow UNIX tools to run” Removing or Disabling Apple Remote Desktop Apple Remote Desktop’s client components are bundled as part of Mac OS X and Mac OS X Server. You may choose to remove or disable parts of it to fit your own personal computing needs. The following section describes how to uninstall or disable key Apple Remote Desktop components. Uninstalling the Administrator Software To remove the administrator software completely, you must remove the application, the encrypted list of computer user names and passwords, and the client information database. To remove the administrator software: 1 Drag the Remote Desktop application to the Trash. 2 Empty the Trash. 3 Delete the Apple Remote Desktop database from /var/db/RemoteManagement/ using the following commands in the Terminal application: $ sudo rm -rf /var/db/RemoteManagement 4 Delete the Remote Desktop preferences files using the following commands in the Terminal application. $ sudo rm /Library/Preferences/com.apple.RemoteDesktop.plist $ sudo rm /Library/Preferences/com.apple.RemoteManagement.plist $ rm ~/Library/Preferences/com.apple.RemoteDesktop.plistChapter 3 Installing Apple Remote Desktop 47 5 Delete the Remote Desktop documentation using the following commands in the Terminal application. sudo rm -r /Library/Documentation/Applications/RemoteDesktop 6 Delete the Apple Remote Desktop support files from /Library/Application Support/ using the following commands in the Terminal application: $ rm -rf ~/Library/Application\ Support/Remote\ Desktop/ $ sudo rm -rf /Library/Application\ Support/Apple\ Remote\ Desktop/ 7 Delete the Apple Remote Desktop installation receipts from /Library/Receipts/ using the following commands in the Terminal application: $ rm -r /Library/Receipts/RemoteDesktopAdmin* $ rm -r /Library/Receipts/RemoteDesktopRMDB* 8 Delete the Apple Remote Desktop Dashboard Widget (after closing every instance of the Widget) using the following commands in the Terminal application: $ sudo rm -r /Library/Widgets/Remote\ Desktop/ Disabling the Client Software You may want to temporarily disable Apple Remote Desktop on a client without removing the software. To disable the client software on a client computer: 1 On the client computer, open System Preferences and click Sharing. If necessary, enter the user name and password of a user with administrator privileges on that computer. 2 Deselect Apple Remote Desktop in the Sharing pane. 3 Quit System Preferences. Apple Remote Desktop is now disabled and the underlying software is deactivated. Alternately, you can disable only the administrator privileges by doing the following: a Click Access Privileges. b Deselect each user account that you enabled for Apple Remote Desktop administration. c Click OK. d Quit System Preferences. Warning: Because Apple Remote Desktop is part of the default Mac OS X 10.3 and 10.4 installation, do not remove the Apple Remote Desktop client components.48 Chapter 3 Installing Apple Remote Desktop Uninstalling the Client Software from Client Computers To remove Apple Remote Desktop client software from Mac OS X clients, you need to remove a number of software components from each client system. To uninstall client software: 1 Open Terminal (located in /Applications/Utilities). 2 Delete the client pieces from /System/Library/ using the following commands in the Terminal application: $ sudo rm -rf /System/Library/CoreServices/Menu\ Extras/RemoteDesktop.menu $ sudo rm -rf /System/Library/CoreServices/RemoteManagement/ $ sudo rm -rf /System/Library/PreferencePanes/ARDPref.prefPane $ sudo rm -rf /System/Library/StartupItems/RemoteDesktopAgent/ 3 Delete the client preferences from /Library/Preferences/ using the following command in the Terminal application: $ sudo rm /Library/Preferences/com.apple.ARDAgent.plist $ sudo rm /Library/Preferences/com.apple.RemoteManagement.plist 4 Delete the client installation receipts from /Library/Receipts/ using the following command in the Terminal application: $ sudo rm -r /Library/Receipts/RemoteDesktopClient* $ sudo rm -rf /var/db/RemoteManagement/ Warning: It is not recommended that you uninstall the client software. Disabling the client software is sufficient to stop Apple Remote Desktop system activity. See “Disabling the Client Software” on page 47 for instructions.4 49 4 Organizing Client Computers Into Computer Lists Apple Remote Desktop uses lists of client computers to logically organize the client computers under your control. Connecting to client computers on the network and adding them to your list is necessary to administer them. This chapter describes finding clients and organizing them into lists for Apple Remote Desktop administration and user interaction. You can learn about:  “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49  “Making and Managing Lists” on page 53  “Importing and Exporting Computer Lists” on page 56 Finding and Adding Clients to Apple Remote Desktop Computer Lists Before you can audit, control, or maintain any client, you need to add it to an Apple Remote Desktop computer list. To find computers that aren’t on the local subnet, your local network’s routers and firewalls must be properly configured to pass network “pings,” and TCP/UDP packets on ports 3283 and 5900. Remote Desktop has four different methods for discovering possible clients: searching the local networks, searching a range of IP addresses, using a specific IP address or domain name, and importing a list of IP addresses. Once you have found a potential client, you see the following default information: Search column Description (none) Displays a small icon indicating whether the computer is already in the Master List. (none) Displays a small icon showing what kind of access the client is capable of. See “Client Status Icons” on page 161. Name The name given to the computer in the Sharing pane of System Preferences. IP Address The computer’s IP address, if any.50 Chapter 4 Organizing Client Computers Into Computer Lists If you want to change the default display list for the scanner, you can select Edit > View Options and choose any of the other available options (which include Computer Info Fields, Ethernet ID, Label, or others). To add a computer to a computer list, you first authenticate to the computer. Authenticated computers are found in the All Computers list in the Remote Desktop window. You can add a computer to the All Computers list without authenticating, but you will be unable to administer the client until you provide a valid user name and password. Finding Clients by Searching the Local Network When you select a local network scanner, Remote Desktop sends a subnet broadcast to computers in the same subnets as the administrator computer. All possible clients on the local subnets appear in a list on the right side of the Remote Desktop window. To search for clients on the local network: 1 Select a scanner at the left of the Remote Desktop window. 2 Select Local Network. All responding clients are listed in the Remote Desktop window. 3 Select the desired computers. 4 Drag the selected computers to the All Computers list. 5 Authenticate by providing a user name and password for an Apple Remote Desktop administrator. The computer is now in your All Computers list. Finding Clients by Searching a Network Range To locate computers by network range, you provide a beginning and ending IP address to scan, and Apple Remote Desktop queries each IP address in that range in sequence, asking if the computer is a client computer. This method works best when searching for clients outside the local subnet, but on the local area network. Alternatively, you can use a text file that contains IP address ranges (in this format “192.168.0.1-192.168.3.20”), and use text file import to find clients. See “Finding Clients by File Import” on page 52. DNS Name The computer’s DNS name, found by reverse lookup, if any. ARD Version Apple Remote Desktop client software version. Network Interface Which interface the client responded through. Search column DescriptionChapter 4 Organizing Client Computers Into Computer Lists 51 To search a range of network addresses: 1 Select a scanner at the left of the Remote Desktop window. 2 Select Network Range. 3 Enter the beginning and ending IP address. 4 Click the Refresh button. All responding clients are listed in the Remote Desktop window. 5 Select the desired computers. 6 Drag the selected computers to the All Computers list. 7 Authenticate by providing a user name and password for an Apple Remote Desktop administrator. The computer is now in your All Computers list. Finding Clients by Network Address If you know the exact IP address or fully qualified domain name of a computer, you can use that IP address or domain name to add the computer to your All Computers list. To add a specific address immediately to the All Computers list: 1 Choose File > Add By Address. 2 Enter the IP address or fully qualified domain name. 3 Enter the user name and password. 4 Choose whether to verify the name and password before adding it to the All Computers list. 5 Click Add. Alternatively you use the scanner to try an address or domain name and check availability before attempting to add it to the All Computers list. To search for a specific address: 1 Select a scanner at the left of the Remote Desktop window. 2 Select Network Address. 3 Enter the IP address or fully qualified domain name in the Address field. 4 Click the Refresh button. If the client responds successfully, it is listed in the Remote Desktop window. 5 Select the desired computers. 6 Drag the selected computers to the All Computers list. 7 Authenticate by providing a user name and password for an Apple Remote Desktop administrator. The computer is now in your All Computers list.52 Chapter 4 Organizing Client Computers Into Computer Lists Finding Clients by File Import You can import a list of computers into Apple Remote Desktop by importing a file listing the computers’ IP addresses. The list can be in any file format (text, spreadsheet, word processor) and must contain either IP addresses or fully qualified domain names (such as foo.example.com). File import also allows you to add ranges of IP addresses by expressing the range in the following format: xxx.xxx.xxx.xxx-yyy.yyy.yyy.yyy. For example, a text file with the line “192.168.0.2-192.168.2.200” would add all IP addresses in that address range. To import a list of computers from a file: 1 Select a scanner at the left of the Remote Desktop window. 2 Select File Import. 3 Browse for the file by clicking the Open File button, or drag a file into the window. Alternatively, you can enter the file’s pathname in the File field. All responding clients are listed in the Remote Desktop window. 4 Select the desired computers. 5 Drag the selected computers to the All Computers list. 6 Authenticate by providing a user name and password for an Apple Remote Desktop administrator. The computer is now in your All Computers list. Making a New Scanner You may want several scanners in order to search for specific address ranges or to do other types of searches. You can make and save your own scanner so you can quickly do the search at any time. You can rename scanners to make them easy to identify. To make a custom search list: 1 Choose File > New Scanner. 2 Rename the newly created scanner. 3 Select the scanner icon. 4 Choose a search type from the pop-up menu to the right.Chapter 4 Organizing Client Computers Into Computer Lists 53 5 Customize the search by entering the specific parameters for the search (such as an IP address range, or file location). You can find out how to customize the search in the following sections:  “Finding Clients by Searching the Local Network” on page 50  “Finding Clients by Searching a Network Range” on page 50  “Finding Clients by Network Address” on page 51  “Finding Clients by File Import” on page 52 6 Click the Refresh button. All responding clients are listed in the Remote Desktop window. Select your scanner icon and click the Refresh button whenever you want to run the search. Making and Managing Lists You use lists to organize and perform management tasks on client computers. You can make groups of lists, and rearrange the lists by dragging them up and down the left side of the main window. Apple Remote Desktop has several different kinds of lists. The following section describes the kinds of lists, and explains how to create lists and use them for client management. About Apple Remote Desktop Computer Lists Apple Remote Desktop displays computers in lists in the main section of the Remote Desktop window. The default computer list is called the All Computers list. This is a full list of all possible clients that you have located and authenticated to. You can create other lists to group the computers on your network in any way you wish. Computer lists have the following capabilities:  You can create as many lists as you want.  The All Computers list can have up to the number of computers your license allows.  Computers can appear in more than one list.  Lists can be made in any grouping you can imagine: geographic, functional, hardware configuration, even color.  Click a list name and keep the mouse over the list name, you can edit the list name.  If you double-click the list icon, you open another window containing the computers in the list.54 Chapter 4 Organizing Client Computers Into Computer Lists Creating an Apple Remote Desktop Computer List You can make more specific, targeted lists of computers from your All Computers list. The easiest way to make a new list is to use computers already in the All Computers list. You can also create blank lists and add computers to them later. To create an Apple Remote Desktop computer list: 1 Select the All Computers list icon in the main Remote Desktop window. 2 Select the computers you want to add to the new list. 3 Choose File > New List From Selection. 4 Name the computer list. Alternatively, you can choose File > New List to create a blank list and drag computers from the All Computers list, or from the scanner search results, to the blank list. Deleting Apple Remote Desktop Lists You can delete Apple Remote Desktop computer lists and scanner lists that you created. You cannot delete the All Computers list, Task Server list, or Task History list. To delete a list: m Select the list and press the Delete key. Creating a Smart Computer List You can create a computer list which automatically populates based on custom criteria. Once you create a smart list, any computer added to the All Computers list (or other specified list) which matches the criteria will automatically be added to the smart list. You can match any or all of the following criteria:  Name  IP Address  DNS Name  Label  Apple Remote Desktop version  Startup Volume  Installed RAM  CPU Information  Machine Model  Mac OS version  Computer is in List In order to use a smart list which populates from any list except the All Computers list, you need to add the “Computer is in List” criterion and specify the source list.Chapter 4 Organizing Client Computers Into Computer Lists 55 To create a smart computer list: 1 Choose File > New Smart List. 2 Name the smart computer list. 3 Choose “any” or “all” criteria to match. 4 Select the attribute to select by, using the pop-up windows and text entry field. 5 Add any other criteria with the Add (+) button. 6 Click OK. The new smart list appears in Remote Desktop’s main window. Editing a Smart Computer List You may want to edit the smart lists you have created. The editing window is the same as the one used to create the smart list. The options available are the same as those listed in “Creating a Smart Computer List” on page 54. To edit a smart computer list: 1 Select the smart list in Remote Desktop’s main window. 2 Choose File > Edit Smart List. 3 Change the smart computer list as desired. Creating a List of Computers of from Existing Computer Lists You may want a list which combines the results of several different lists and smart lists. You can create aggregate lists by using the “Computer is in List” option. The list created will have the computers from the source lists, but not indicate which source list they came from. To create an list of computer lists: 1 Create the lists which will serve as the sources of the smart list. See “Creating an Apple Remote Desktop Computer List” on page 54 or “Creating a Smart Computer List” on page 54 for more information. 2 Create the Smart List which will draw its computers from the previously created lists. “Creating a Smart Computer List” on page 54 for more information. 3 In the Smart List creation dialog, choose to match all of the stated conditions. 4 For the first condition, select “Computer is in List.” 5 Select a source list from the pop-up menu. 6 Add another condition by clicking the Add (+) button. 7 Repeat steps 4-6, adding Computer Lists for all of the source lists.56 Chapter 4 Organizing Client Computers Into Computer Lists 8 Add other conditions and criteria as desired. 9 Create the final Smart List by clicking OK. The new Smart List appears in Remote Desktop’s main window. Importing and Exporting Computer Lists When setting up Apple Remote Desktop 3, you may not necessarily use the same computer you used for the previous version of Apple Remote Desktop. Rather than create new lists of client computers, you can transfer existing lists between computers, with benefits and limitations depending on the transfer circumstance. The following sections will help you import or export your computer lists.  “Transferring Computer Lists from Apple Remote Desktop 3 to a New Administrator Computer” on page 56  “Transferring Remote Desktop 2 Computer Lists to a New Remote Desktop 3 Administrator Computer” on page 57  “Transferring Old v1.2 Computer Lists to a New Administrator Computer” on page 57 Transferring Computer Lists from Apple Remote Desktop 3 to a New Administrator Computer You may want to move your existing computer lists to the new administrator computer running Apple Remote Desktop 3. Lists transferred in this way retain their client computers as well as the original name of the list. You can only use these instructions to move computer lists between administrator computers which run Apple Remote Desktop 3. When you import or export a computer list, the user name and password used for Apple Remote Desktop authentication are not exported. Once you’ve imported the computer list, you will still need to authenticate to the computers. To transfer the computer lists: 1 In the main Remote Desktop window, select the list you want to move. 2 Choose File > Export List. 3 Select a name and a file location for the exported list. The default file name is the list name. Changing the file name, however, does not change the list name. 4 Click Save. A .plist file is created in the desired location. The XML-formatted .plist file is a plain text file that can be inspected with Apple’s Property List Editor or a text editor. 5 Copy the exported file to the desired administrator computer. 6 On the new administrator computer, launch Remote Desktop. 7 Choose File > Import List.Chapter 4 Organizing Client Computers Into Computer Lists 57 8 Select the exported list, and click Open. The list now appears in Remote Desktop’s main window. Transferring Remote Desktop 2 Computer Lists to a New Remote Desktop 3 Administrator Computer If you are installing Apple Remote Desktop 3 on a computer different from the version 2.x administrator computer, you may want to move your existing computer lists to the new administrator computer running Apple Remote Desktop 3. When you import or export a computer list, the user name and password used for Apple Remote Desktop authentication are not exported. Once you’ve imported the computer list, you will still need to authenticate to the computers. To transfer the computer lists: 1 In the main Remote Desktop window, select the list you want to move. 2 Make sure Remote Desktop lists the computer’s name and IP address. 3 Choose File > Export Window. 4 Select a name and a file location for the exported list, and click Save. The default file name is the window’s title. 5 Copy the exported file to the desired administrator computer. 6 On the new administrator computer, launch Remote Desktop. 7 Using the Scanner, add the clients by File Import. See “Finding Clients by File Import” on page 52, for detailed instructions. The list now appears in Remote Desktop’s main window. 8 Select the computers in the list. 9 Choose File > New List From Selection. The new list now appears in Remote Desktop’s main window. Transferring Old v1.2 Computer Lists to a New Administrator Computer If you are installing Apple Remote Desktop 3 on a computer other than an older administrator computer using Apple Remote Desktop 1.2, you need to move your existing computer lists to the new administrator computer before installing version 3. These instructions only apply when moving Apple Remote Desktop 1.2 computer lists to a new computer. Throughout these instructions, the computer with the original lists is the “source computer.” The computer that will have Apple Remote Desktop 3 installed is the “target computer.”58 Chapter 4 Organizing Client Computers Into Computer Lists To transfer the computer lists: 1 Open Keychain Access (located in /Applications/Utilities) on the source computer. 2 Choose File > New Keychain. 3 Name the new keychain, and click Create. 4 Enter a password for the new keychain. This is a temporary password that you will use to retrieve the information in the keychain. Do not use your login password or other sensitive password. 5 If necessary, click Show Keychains to show the administrator keychain. 6 Select the source computer’s main keychain. If the keychain is locked, unlock it and authenticate. 7 Select only the Apple Remote Desktop entries in the keychain. 8 Drag the Apple Remote Desktop entries to the newly created keychain. 9 Provide the source computer keychain password for each entry. 10 Quit Keychain Access on the source computer. 11 Copy the newly created keychain from the source computer (~/Library/Keychains/ ) to the same location on the target computer. You can copy the keychain over the network, or use a removable storage drive. 12 On the target computer, open Keychain Access in the Finder. 13 Choose File > Add Keychain. 14 Select the keychain that was copied from the source computer, and click Open. 15 If necessary, click Show Keychains to show the keychains. 16 Unlock the newly imported keychain, using the password designated for that keychain. 17 Select the Apple Remote Desktop entries. 18 Drag the Apple Remote Desktop entries to the main keychain on the target computer. Provide the temporary keychain password for each entry. 19 Quit Keychain Access on the source computer. When you open Apple Remote Desktop on the new computer, you will notice that the computer lists from the old computer are available.5 59 5 Understanding and Controlling Access Privileges There are several different ways to access and authenticate to Apple Remote Desktop clients. Some depend on Apple Remote Desktop settings, and others depend on other client settings, or third-party administration tools. This chapter explains the various access types, their configuration, and their uses. You can learn about:  “Apple Remote Desktop Administrator Access” on page 59  “Apple Remote Desktop Administrator Access Using Directory Services” on page 62  “Apple Remote Desktop Guest Access” on page 65  “Apple Remote Desktop Nonadministrator Access” on page 66  “Virtual Network Computing Access” on page 67  “Command-Line SSH Access” on page 68  “Managing Client Administration Settings and Privileges” on page 68 Apple Remote Desktop Administrator Access Access privileges allow an Apple Remote Desktop administrator to add computers to a list and then interact with them. If no access privileges are allowed on a client computer, that computer cannot be used with Apple Remote Desktop. Access privileges are defined in the Apple Remote Desktop section of the Sharing pane of the client computers’ System Preferences. The recommended access privileges for a client computer depend on how it’s used.  If the computer is used in a public area, such as a computer lab, you may want to allow administrators full access privileges.  If the computer is used by one person, you may not want to give administrators full access privileges. Also, you may want a user who administers his or her own computer to take responsibility for creating passwords and setting the access privileges for the computer60 Chapter 5 Understanding and Controlling Access Privileges The following table shows the settings in the Apple Remote Desktop settings in the Sharing Preference pane and the features of Remote Desktop that they correspond to. For example, if you want a certain administrator to be rename computer file sharing names, you will need to grant that user that privilege by selecting “Change Settings”. checkbox in the Apple Remote Desktop settings in the Sharing Preference pane on the client computer. Select To allow administrators to Select any other privileges. (If you select only this box, the administrator can see the client computer in the Computer Status window and include it in Network Test reports.) Generate reports Create hardware and software reports using the Report menu; use Set Reporting Policy and Spotlight Search. Open and quit applications Use these Manage menu commands: Open Application, Open Items, Send UNIX Command and Log Out Current User. Change settings Use these Manage menu commands: Rename Computer, Send UNIX Command and Set Startup Disk. Delete and replace items Use these Manage menu commands: Copy Items, Install Packages, Send UNIX Command and Empty Trash. Also delete items from report windows. This item must be enabled in order to use the Upgrade Client Software feature. Send text messages Use these Interact menu commands: Send Message and Chat. Restart and shut down Use these Manage menu commands: Sleep, Wake Up, Restart, Send UNIX Command, and Shut Down. This item must be enabled in order to use the Upgrade Client Software feature. Copy items Use these Manage menu and Server menu commands: Copy Items, Send UNIX Command and Install Packages. This item must be enabled in order to use the Upgrade Client Software and Change Client Settings features. Control Use these Interact menu commands: Control, Share Screen, Lock and Unlock Screen. This item must be enabled in order to use the Upgrade Client Software and Change Client Settings features.Chapter 5 Understanding and Controlling Access Privileges 61 Setting Apple Remote Desktop Administrator Access Authorization and Privileges Using Local Accounts To prepare a client for administration, you activate the existing version of Apple Remote Desktop on the client computer and set Apple Remote Desktop administrator access privileges by using the Sharing pane of the computer’s System Preferences. You set access privileges separately for each user account on the computer. Follow the steps in this section to set access privileges on each client computer. Note: You can skip this step if you create a custom installer that automatically enables your desired client settings. To make changes on a client computer, you must have the name and password of a user with administrator privileges on the computer. To set administrator privileges on a computer: 1 On the client computer, open System Preferences and click Sharing. If the preference pane is locked, click the lock and then enter the user name and password of a user with administrator privileges on that computer. 2 Select Apple Remote Desktop in the Sharing service pane. 3 Click Access Privileges. 4 Select each user that you want enabled for Apple Remote Desktop administration authentication. 5 Select a listed user whose access privileges you want to set, and then make the changes you want to the access privileges. Your changes take effect immediately. Hint: Holding down the Option key while clicking the user’s checkbox will automatically select all the following checkboxes for access. See “Apple Remote Desktop Administrator Access” on page 59 for more information. 6 Repeat for additional users whose access privileges you want to set. 7 If desired, enter information in any or all of the four Computer Information fields. This information appears in Apple Remote Desktop System Overview reports and optionally in the computer list views. For example, you can enter an inventory number for the computer, a serial number, or a user’s name and telephone number. 8 Click OK. 9 To activate the Apple Remote Desktop client, make sure to select the Apple Remote Desktop checkbox, or select Apple Remote Desktop and click Start.62 Chapter 5 Understanding and Controlling Access Privileges Apple Remote Desktop Administrator Access Using Directory Services You can also grant Apple Remote Desktop administrator access without enabling any local users at all by enabling group-based authorization if the client computers are bound to a directory service. When you use specially named groups from your Directory Services master domain, you don’t have to add users and passwords to the client computers for Apple Remote Desktop access and privileges. When Directory Services authorization is enabled on a client, the user name and password you supply when you authenticate to the computer are checked in the directory. If the name belongs to one of the Apple Remote Desktop access groups, you are granted the access privileges assigned to the group. Creating Administrator Access Groups In order to use Directory Services authorization to determine access privileges, you need to create groups and assign them privileges. There are two ways of doing this: Method #1 You can create groups and assign them privileges through the mcx_setting attribute on any of the following records: any computer record, any computer list record, or the guest computer record. To create an administrator access group: 1 Create groups as usual. If you are using Mac OS X Server, you use Workgroup Manager to make them. 2 After you have created groups, you edit either the computer record of the computer to be administered, its computer list record, or the guest computer record. 3 Use a text editor, or the Apple Developer tool named Property List Editor to build the mcx_setting attribute XML. The XML contains some administrator privilege key designations (ard_admin, ard_reports, etc.), and the groups that you want to possess those privileges. The following privilege keys have these corresponding Remote Desktop management privileges:Chapter 5 Understanding and Controlling Access Privileges 63 In the XML, you name a privilege key and make the value the name of the group or groups you want to possess the privilege. Use the sample XML below to make your management/key designation XML. 4 When you have created the snippet of XML, you enter this whole snippet into a computer record or computer list record. If you are using Workgroup Manager, you enable the preference to “Show All Records Tab and Inspector” and use the Inspector to copy the entire snippet of XML the value which corresponds to the “MCXSettings” attribute name. Management Privilege ard_admin ard_reports ard_manage ard_interact Generate reports X X X Open and quit applications X X Change settings X X Copy items X X Delete and replace items X X Send messages X X X Restart and shut down X X Control X X Observe X X Show being observed X X64 Chapter 5 Understanding and Controlling Access Privileges For more information on using Workgroup Manager, and Open Directory, see their documentation at: www.apple.com/server/documentation The following is the sample XML format you need to use to assign management privileges via MCX keys. It assigns the above “ard_interact” privileges to the groups named “some_group” and “staff.” It also assigns the “ard_manage” privileges to the group named “staff,” the “ard_admin” privileges to the group “my_admin_group,” and leaves no group with the “ard_reports” privilege set. Here’s the XML: mcx_application_data com.apple.remotedesktop Forced mcx_preference_settings ard_interact some_group staff ard_manage staff ard_admin my_admin_group ard_reports This example attribute defines four privileges, although any of them may be left out.Chapter 5 Understanding and Controlling Access Privileges 65 Method #2 You can create groups with special names that correspond to the privilege keys above: ard_admin, ard_reports, ard_manage, and ard_interact. The corresponding privileges are automatically assigned to these specially named groups. If you have already created these groups for use with Apple Remote Desktop 2, they will continue to work as expected with Apple Remote Desktop 3. Enabling Directory Services Group Authorization In order to enable group-based authorization for Apple Remote Desktop access, you create the appropriate groups in your Directory Services master directory domain. To complete this task, you need to be the Directory Services administrator and have access to your organization’s users and groups server. To enable Apple Remote Desktop authorization by group: 1 Use one of the methods in the section “Creating Administrator Access Groups” to create groups with Apple Remote Desktop access privileges assigned to them. 2 Add users to the groups. 3 Make sure the client computers to be administered are bound to your directory system. 4 Set the clients to use directory authorization by using the Change Client Settings feature or make a custom installer. 5 Choose to enable directory-based administration on the clients using Directory Access found in /Applications/Utilities/. Apple Remote Desktop Guest Access You can configure an Apple Remote Desktop client to give temporary, one-time access to an Apple Remote Desktop administrator who does not have a user name or password for the client computer. Each time the Apple Remote Desktop administrator would like to control the client computer, he or she must request permission from the remote client’s user. Warning: Granting access to control a screen is the most powerful feature in Apple Remote Desktop, and can be equivalent to unrestricted access.66 Chapter 5 Understanding and Controlling Access Privileges To allow guest access: 1 On the client computer, open System Preferences and click Sharing. If prompted, enter the user name and password of a user with administrator privileges on that computer. 2 Select Apple Remote Desktop in the Sharing pane. 3 Click Access Privileges. 4 Select “Guests may request permission to control screen.” 5 Click OK. Apple Remote Desktop Nonadministrator Access Remote Desktop can operate in what is referred to as “user mode.” User mode is activated when a nonadministrator user opens Remote Desktop to administer Apple Remote Desktop client computers. The administrator of the computer with Remote Desktop installed can choose which features and tasks are available to nonadministrator users. Limiting Features in the Administrator Application User mode is a great way to delegate administrative tasks, or give users only the features of Remote Desktop that they really use. For example, you might not allow nonadministrators to copy or delete files, but you may want them to be able to observe client screens and send messages to client users. You can choose to allow nonadministrators to:  Observe, control, and share screens  Lock and unlock screens  Send text messages and chat  Sleep and wake client computers  Log out users  Restart and shut down computers  Open or quit files and applications  Rename computers  Generate reports and software searches  Copy items, delete items, and empty the Trash  Create Apple Remote Desktop custom client installers  Upgrade clients and change client settings  Install packages  Set the client computer’s startup volume  Set the client’s data reporting policy  Send UNIX commandsChapter 5 Understanding and Controlling Access Privileges 67 Each of these features can be enabled or disabled independently of each other, or you can enable all of Remote Desktop’s features for nonadministrator users. To enable User Mode: 1 Make sure you are logged in as an administrator user. 2 Open Remote Desktop. 3 Choose Remote Desktop > Preferences. 4 Click the Security button. 5 Enable or disable features, as desired. 6 Close the Preference’s window. Virtual Network Computing Access You can use Apple Remote Desktop to access a Virtual Network Computing (VNC) server and view and interact with the server’s screen. VNC access is determined by the VNC server software. To access a VNC server, it is only necessary to know the IP address or fully qualified domain name and the password designated in the VNC server software. This password does not necessarily correspond to any other password on the system, and is determined by the VNC configuration. VNC access is similar to Apple Remote Desktop’s Control command. It allows you to use your keyboard and mouse to control a VNC server across a network. It doesn’t give any other Apple Remote Desktop administrator privileges except those of the currently logged-in user. Non-Apple VNC viewers can control Apple Remote Desktop clients if the client allows it. Allowing a non-Apple VNC viewer access to an Apple Remote Desktop client is less secure than using Apple Remote Desktop to control the client. The VNC protocol implemented in third-party VNC viewers may not encrypt keystrokes sent over the network, so sensitive information can be intercepted. Warning: Granting VNC access to control a screen is the most powerful feature in Apple Remote Desktop, and can be equivalent to unrestricted access.68 Chapter 5 Understanding and Controlling Access Privileges To allow VNC access: 1 On the client computer, open System Preferences and click Sharing. If prompted, enter the user name and password of a user with administrator privileges on that computer. 2 Select Apple Remote Desktop in the Sharing pane. 3 Click Access Privileges. 4 Select “VNC viewers may control screen with password.” 5 Enter a VNC password. Command-Line SSH Access Command-line SSH access is not granted or managed using Remote Desktop. This type of access is managed in the Sharing pane of System Preferences (called “Remote Login”) and is separate from Apple Remote Desktop access types. When you log in to a client remotely using SSH, you have the user privileges assigned to the user name and password. These may or may not include computer administrator privileges. You can use SSH to access a client using a user account created for Apple Remote Desktop, but you are limited to performing whatever tasks were allowed to that user when the account was created. Conversely, only the users specified in the Apple Remote Desktop access privileges can access a computer using Apple Remote Desktop. Apple Remote Desktop privileges are completely separate and distinct from local computer administrator UNIX privileges. Managing Client Administration Settings and Privileges Regular audits of administration settings can help maintain a secure Remote Desktop administration environment. Using the various administrator options given with Apple Remote Desktop administrator privileges, you can create specialized logins for certain tasks, limiting potentially disruptive power of certain sub-administrators. The following section gives detailed instructions for checking the administrator privilege settings of client computers, and changing those settings. Warning: Do not use the same password as any local user or Apple Remote Desktop login.Chapter 5 Understanding and Controlling Access Privileges 69 Getting an Administration Settings Report You can query active Apple Remote Desktop clients for a report on what commands they are accepting from your administrator authentication. The report is a list of the Apple Remote Desktop administrator access types each with an “On” or “Off” to indicate whether that access type is available to you. To get an administration settings report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Administration Settings. 4 Click Get Report. Changing Client Administrator Privileges Once the client computers are able to be administered, you can change the administrator access privileges for multiple computers simultaneously, using the Change Client Settings command. If you are using Directory Services to designate administrator privileges, you don’t need to change the settings on the clients. To make changes on a client, you must have the name and password of a user with administrator privileges on the computer. Additionally, you must already have the Control privilege. Note: You do not have to make a selection on every page of the assistant. You can click Continue to move to the next set of settings. To change administrator privileges on each computer: 1 Select a computer list. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Change Client Settings. The client assistant appears. Click Continue. 4 Choose whether to start Remote Desktop sharing at system startup. This changes the setting found in the Sharing pane of System Preferences. 5 Choose whether to hide or show the Apple Remote Desktop menu bar icon. 6 Click Continue. 7 Choose whether to create a new user for Apple Remote Desktop login. Click Continue. New users can be used to grant Apple Remote Desktop administrator privileges. Creating a new user does not overwrite existing users or change existing user passwords. If you choose not to create a new user, skip to step 9 after clicking Continue.70 Chapter 5 Understanding and Controlling Access Privileges 8 Add a new user by clicking Add and filling in the appropriate information. Click OK after adding each user, and click Continue when you’re ready to go on. 9 Choose whether to assign Apple Remote Desktop administrator access privileges to Directory Services groups. If you choose to do so, select “Enable directory-based administration.” See “Apple Remote Desktop Administrator Access Using Directory Services” on page 62 for more information on using this method to grant Apple Remote Desktop administrator access. 10 Choose whether to assign Apple Remote Desktop administrator access privileges to specific users. Click Continue. If you choose not to assign administrator access privileges, skip to step 13. 11 Click Add to designate a user to receive Apple Remote Desktop access privileges. 12 Provide the user’s short name and assign the privileges as desired. See “Apple Remote Desktop Administrator Access” on page 59 for more information. Click OK after each user, and click Continue when you’re ready to go on. 13 Choose whether to allow temporary guest control by requesting permission on the client computers. 14 Choose whether to allow non-Apple VNC viewers to control the client computers, and click Continue. See “Virtual Network Computing Access” on page 67 for more information. 15 If desired, select and enter information in any or all of the four System Data fields. This information appears in Apple Remote Desktop System Overview reports. For example, you can enter an inventory number for the computer, a serial number, or a user’s name and telephone number. 16 Click Continue to review the clients’ settings. 17 Choose whether to execute the change using the application or a dedicated task server. 18 Click Change to change the clients’ settings The client configuration assistant contacts all of the selected computers and changes their administration settings.6 71 6 Setting Up the Network and Maintaining Security This chapter describes the main aspects of setting up your network for use with Apple Remote Desktop system administration, as well as best-practice tips for your network. Additionally, it contains information about Apple Remote Desktop security features, and detailed instructions for enabling them. You can learn about:  “Setting Up the Network” on page 71  “Using Apple Remote Desktop with Computers in an AirPort Wireless Network” on page 72  “Getting the Best Performance” on page 73  “Maintaining Security” on page 73 Setting Up the Network Your network configuration determines Apple Remote Desktop’s performance and usability. AirPort and AirPort Extreme networks offer slower performance than almost any Ethernet network. Therefore, file copying, client monitoring, and reporting are slower over AirPort and AirPort Extreme connections. Network routers and firewalls also shape, direct, or block network traffic; these things can have an effect on Apple Remote Desktop’s reliability and efficiency. Here are a few guidelines to keep in mind when setting up Apple Remote Desktop on your network:  The more AirPort clients connected to a base station, the lower the bandwidth for each computer. AirPort Base Stations are not considered “switched networks.”  Local Hostname (name using Apple’s Bonjour technology, that looks like: name.local) browsing does not extend beyond the local subnet. Local Hostnames do not resolve across routers like domain names do.  Networks with switches have fewer collisions and packet errors than networks with hubs. This means greater reliability and speed. Consider using switches instead of hubs.72 Chapter 6 Setting Up the Network and Maintaining Security  Organize computers you’re administering using Apple Remote Desktop into small groups, and close the Remote Desktop administrator application when not in use. This helps reduce the number of status queries, thus reducing network traffic.  If a client has a slow network type, consider running it in a list separate from the faster clients. A single slow client can slow down network operations.  If network traffic passes through firewalls, make sure you have a large Maximum Transmission Unit (MTU) setting (1200 or greater). Too small an MTU setting can result in black screens when sharing or sending screens.  If you are using a wide-area network (WAN), or metropolitan area network (MAN), make sure that the defrag bit is turned off in your router so packets don’t get chunked up. This can result in black screens when sharing or sending screens.  Network Address Translation (NAT) networks (such as those that use the Mac OS X Internet Sharing feature) can pose configuration and access difficulties. If you want to use Remote Desktop from behind a NAT router to access computers beyond the NAT router, you need to set TCP and UDP port forwarding for ports 3283 and 5900 to your administrator computer. Similarly, if you wish to access a single client computer that is behind a NAT router, you need to set the router to forward TCP and UDP ports 3283 and 5900 to the client computer you wish to access. Using Apple Remote Desktop with Computers in an AirPort Wireless Network Using Apple Remote Desktop to observe or control client computers connected using AirPort wireless technology can sometimes result in impaired performance or cause communication errors to appear in the Computer Status window. To get the best performance from Apple Remote Desktop with computers in an AirPort wireless network:  Make sure that all AirPort Base Stations and all Apple Remote Desktop client computers have the latest versions of Apple Remote Desktop software, AirPort software, and Mac OS X software installed.  Limit the number of clients that connect to an AirPort Base Station. AirPort clients on a base station receive all network communication packets sent to any one client on that base station. Although clients ignore packets that aren’t addressed to them, CPU resources are used to identify and discard the packet.  Scale the Control and Observe window. Apple Remote Desktop has server-side scaling that will allow for less traffic across the network as you scale the window to smaller sizes.  Try not to use tasks that multicast traffic such as Share Screen and File Copy. File Copy tries to initiate a series of individual copies if there is a significant number of multicast networking errors.Chapter 6 Setting Up the Network and Maintaining Security 73  Wireless networks also are not suited for multicast traffic. However Apple Remote Desktop’s multi-observe feature is different because it doesn’t use multicast traffic.  Display shared screens in black and white rather than in color.  Configure your AirPort Base Station with a station density of High and increase the multicast rate to 11 Mbps using AirPort Admin Utility. Using the base station density and multicast rate settings limits the range of each AirPort Base Station’s network, requiring client computers to be fewer than 50 meters from a base station. Getting the Best Performance To get the best performance when using the Share Screen, Observe, and Control commands:  Use the fastest network possible. This means favoring Ethernet over AirPort, 1000Base-T over 100Base-T, and 100Base-T over 10Base-T.  If you’re using AirPort, adjust the multicast speed higher.  Don’t mix network speeds if possible.  Reduce the use of animation on remote computers. For example, you can simplify Dock preference settings by turning off animation, automatic hiding and showing, and magnification effects.  View the client’s screen in a smaller window when using the “fit to window” option.  View the client’s screen with fewer colors.  Use a solid color for the desktop of the screen you’re sharing.  Share screens only on local networks. If you share a screen with a computer connected across a router, screen updates happen more slowly.  Set the Control and Observe image quality to the lowest acceptable for the given circumstance. Maintaining Security Remote Desktop can be a powerful tool for teaching, demonstrating, and performing maintenance tasks. For convenience, the administrator name and password used to access Remote Desktop can be stored in a keychain or can be required to be typed each time you open the application. However, the administrator name and password for each client computer are stored in the administrator’s preferences and are strongly encrypted.74 Chapter 6 Setting Up the Network and Maintaining Security Administrator Application Security  Make use of user mode to limit what nonadministrator users can do with Remote Desktop. See “Apple Remote Desktop Nonadministrator Access” on page 66.  If you leave the Remote Desktop password in your keychain, be sure to lock your keychain when you are not at your administrator computer.  Consider limiting user accounts to prevent the use of Remote Desktop. Either in a Managed Client for Mac OS X (MCX) environment, or using the Accounts pane in System Preferences, you can make sure only the users you designate can use Remote Desktop.  Check to see if the administrator computer is currently being observed or controlled before launching Remote Desktop (and stop it if it is). Remote Desktop prevents users from controlling a client with a copy of Remote Desktop already running on it at connection time, but does not disconnect existing observe or control sessions to the administrator computer when being launched. Although this functionality is helpful if you want to interact with a remote LAN which is behind a NAT gateway, it is possible to exploit this feature to get secretly get information about the administrator, administrator’s computer, and its associated client computers. User Privileges and Permissions Security  To disable or limit an administrator’s access to an Apple Remote Desktop client, open System Preferences on the client computer and make changes to settings in the Remote Desktop pane in the Sharing pane of System Preferences. The changes take effect after the current Apple Remote Desktop session with the client computer ends.  Remember that Apple Remote Desktop keeps working on client computers as long as the session remains open, even if the password used to administer the computer is changed.  Don’t use a user name for an Apple Remote Desktop access name and password. Make “dummy” accounts specifically for Apple Remote Desktop password access and limit their GUI and remote login privileges. Password Access Security  Never give the Remote Desktop password to anyone.  Never give the administrator name or password to anyone.  Use cryptographically sound passwords (no words found in a dictionary; eight characters or more, including letters, numbers and punctuation with no repeating patterns).  Regularly test your password files against dictionary attack to find weak passwords.Chapter 6 Setting Up the Network and Maintaining Security 75  Quit the Remote Desktop application when you have finished using it. If you have not stored the Remote Desktop password in your keychain, the application prompts you to enter the administrator name and password when you open it again. Physical Access Security  If you have stored the Remote Desktop password in your keychain, make sure the keychain is secured and the application isn’t running while you are away from the Remote Desktop window.  If you want to leave the Remote Desktop application open but need to be away from the computer, use a password-protected screen saver and select a hot corner so you can instantly activate the screen saver. Remote Desktop Authentication and Data Transport Encryption Authentication to Apple Remote Desktop clients uses an authentication method based on a Diffie-Hellman Key agreement protocol that creates a shared 128-bit key. This shared key is used to encrypt both the name and password using the Advanced Encryption Standard (AES). The Diffie-Hellman key agreement protocol used in Remote Desktop 3 is very similar to the one used in personal file sharing, with both of them using a 512-bit prime for the shared key calculation. With Remote Desktop 3, keystrokes and mouse events are encrypted when you control Mac OS X client computers. Additionally, all tasks except Control and Observe screen data, and files copied via Copy Items and Install Packages are encrypted for transit (though you may choose to encrypt these as well by changing your application preferences). This information is encrypted using the Advanced Encryption Standard (AES) with the 128-bit shared key that was derived during authentication. Encrypting Observe and Control Network Data Although Remote Desktop sends authentication information, keystrokes, and management commands encrypted by default, you may want additional security. You can choose to encrypt all Observe and Control traffic, at a certain performance cost. Encryption is done using an SSH tunnel between the participating computers. In order to use encryption for Observe and Control tasks, the target computers must have SSH enabled (“Remote Login” in the computer’s Sharing Preference pane). Additionally, firewalls between the participating computers must be configured to pass traffic on TCP port 22 (SSH well known port). If the you are trying to control a VNC server which is not Remote Desktop, it will not support Remote Desktop keystroke encryption. If you try to control that VNC server, you will get a warning that the keystrokes aren’t encrypted which you will have to acknowledge before you can control the VNC server. If you chose to encrypt all network data, then you will not be able to control the VNC server because Remote Desktop is not able to open the necessary SSH tunnel to the VNC server. 76 Chapter 6 Setting Up the Network and Maintaining Security To enable Observe and Control transport encryption: 1 Choose Remote Desktop > Preferences. 2 Click the Security button. 3 In the “Controlling computers” section, select “Encrypt all network data.” Encrypting Network Data During Copy Items and Install Packages Tasks Remote Desktop can send files for Copy Items and Install Packages via encrypted transport. This option is not enabled by default, and you must either enable it explicitly for each copy task, or in a global setting in Remote Desktop’s preferences. Even installer package files can be intercepted if not encrypted. To encrypt individual file copying and package installation tasks: m In the Copy Items task or Install Packages task configuration window, select “Encrypt network data.” To set a default encryption preference for file copies: 1 In the Remote Desktop Preferences window, select the Security pane. 2 Check “Encrypt transfers when using Copy Items,” or “Encrypt transfers when using Install Packages” as desired. Alternatively, you could encrypt a file archive before copying it. The encrypted archive could be intercepted, but it would be unreadable.7 77 7 Interacting with Users Apple Remote Desktop is a powerful tool for interacting with computer users across a network. You can interact by controlling or observing remote screens, text messaging with remote users, or sharing your screen with others. This chapter describes Remote Desktop’s user interaction capabilities and gives complete instructions for using them. You can learn about:  “Controlling” on page 78  “Observing” on page 85  “Sending Messages” on page 92  “Sharing Screens” on page 93  “Interacting with Your Apple Remote Desktop Administrator” on page 9478 Chapter 7 Interacting with Users Controlling Apple Remote Desktop allows you to control remote computers as if you were sitting in front of them. You can only control the keyboard and mouse of any one computer at a time. There are two kinds of remote computers that Apple Remote Desktop can control: Apple Remote Desktop clients and Virtual Network Computing (VNC) servers. Controlling Apple Remote Desktop Clients Apple Remote Desktop client computers can be controlled by any administrator computer that has the Control permission set. See “Apple Remote Desktop Administrator Access” on page 59 for more information about Apple Remote Desktop permissions. While you control an Apple Remote Desktop client computer, some keyboard shortcut commands are not sent to the remote computer, but they affect the administrator computer. These include:  Change Active Application (Command-Tab and Command-Shift-Tab)  Show or Hide Dock (Command-Option-D)  Log Out User (Command-Shift-Q)  Take Screen Shot (Command-Shift-3, -4)  Force Quit (Command-Option-Escape)Chapter 7 Interacting with Users 79 Also, special keys including the sound volume, screen brightness, and Media Eject keys do not affect the client computer. These instructions assume the that observed computer has Apple Remote Desktop installed and configured properly (see “Setting Up an Apple Remote Desktop Client Computer for the First Time” on page 41) and that the computer has been added to an Apple Remote Desktop computer list (see “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49). To control an Apple Remote Desktop client: 1 Select a computer list in the Remote Desktop window. 2 Select one computer from the list. 3 Choose Interact > Control. 4 To customize the control window and session, see “Control Window Options” on page 79. 5 Use your mouse and keyboard to perform actions on the controlled computer. If your Remote Desktop preferences are set to share keyboard and mouse control, the remote computer’s keyboard and mouse are active and affect the computer just as the administrator computer’s keyboard and mouse do. If your preferences aren’t set to share control, the remote computer’s keyboard and mouse do not function while the administrator computer is in control. Control Window Options When controlling a client, the control window contains several buttons in the window title bar which you can use to customize your remote control experience. There are toggle buttons that switch your control session between two different states, and there are action buttons that perform a single task. In addition to the buttons, there is a slider for image quality. The toggle buttons are:  Control mode or Observe mode  Share mouse control with user  Fit screen in window  Lock computer screen while you control  Fit screen to full display The action buttons are:  Capture screen to a file  Get the remote clipboard contents  Send clipboard contents to the remote clipboard80 Chapter 7 Interacting with Users Switching the Control Window Between Full Size And Fit-To-Window When controlling a client, you can see the client window at full size, or scaled to fit the control window. Viewing the client window at full size will show the client screen at its real pixel resolution. If the controlled computer’s screen is larger than your control window, the screen show scroll bars at the edge of the window. To switch in-a-window control between full size and fit-to-window modes: 1 Control a client computer. 2 Click the Fit Screen In Window button in the control window toolbar. Switching Between Control and Observe Modes Each control session can be switched to a single-client observe session, in which the controlled computer no longer takes mouse and keyboard input from the administrator computer. This allows you to easily give control over to a user at the client computer keyboard, or place the screen under observation without accidentally affecting the client computer. See “Observing a Single Computer” on page 90 for more information on Apple Remote Desktop observe mode. To switch between control and observe modes: 1 Control a client computer. 2 Click the Control/Observe toggle button in the control window toolbar. Sharing Control with a User You can either take complete mouse and keyboard control or share control with an Apple Remote Desktop client user. This allows you to have more control over the client interaction as well as prevents possible client side interference. This button has no effect while controlling VNC servers. See “Controlling VNC Servers” on page 82 for more information. To switch between complete control and shared mouse modes: 1 Control a client computer. 2 Click the “Share mouse and keyboard control” button in the control window toolbar.Chapter 7 Interacting with Users 81 Hiding a User’s Screen While Controlling Sometimes you may want to control a client computer with a user at the client computer, but you don’t want the user to see what you’re doing. In such a case, you can disable the client computer’s screen while preserving your own view of the client computer. This is a special control mode referred to as “curtain mode.” You can change what’s “behind the curtain” and reveal it when the mode is toggled back to the standard control mode. To switch between standard control and curtain modes: 1 Control a client computer. 2 Click the “Lock computer screen while you control” button in the control window toolbar. Capturing the Control Window to a File You can take a picture of the remote screen, and save it to a file. The file is saved to the administrator computer, and is the same resolution and color depth as the controlled screen in the window. To screen capture a controlled client’s screen: 1 Control a client computer. 2 Click the “Capture screen to a file” button in the control window toolbar. 3 Name the new file. 4 Click Save. Switching Control Session Between Full Screen and In a Window You can control a computer either in a window, or using the entire administrator computer screen. The “Fit screen to full display” toggle button changes between these two modes. In full screen mode, the client computer screen is scaled up to completely fill the administrator screen. In addition to the client screen, there are a number of Apple Remote Desktop controls still visible overlaying the client screen. In in-a-window mode, you can switch between fitting the client screen in the window or showing it actual size, possibly scrolling around the window to see the entire client screen. See “Switching the Control Window Between Full Size And Fit-To-Window” on page 80 for more information. To switch between full screen and in-a-window modes: 1 Control a client computer. 2 Click the “Fit screen to full display” button in the control window toolbar.82 Chapter 7 Interacting with Users Sharing Clipboards for Copy and Paste You can transfer data between the Clipboards of the administrator and client computer. For example, you may want to copy some text from a file on the administrator computer and paste it into a document open on the client computer. Similarly, you could copy a link from the client computer’s web browser and paste it into the web browser on the administrator computer. The keyboard shortcuts for Copy, Cut, and Paste are always passed through to the client computer. To share clipboard content with the client: 1 Control a client computer. 2 Click the “Get the remote clipboard contents” button in the control window toolbar to get the client’s Clipboard content. 3 Click the “Send clipboard contents to the remote clipboard” button in the control window toolbar to send content to the client’s Clipboard. Controlling VNC Servers Virtual Network Computing (VNC) is remote control software. It allows a user at one computer (using a “viewer”) to view the desktop and control the keyboard and mouse of another computer (using a VNC “server”) connected over the network. For the purposes of these instructions, VNC-enabled computers are referred to as “VNC clients.” VNC servers and viewers are available for a variety of computing platforms. Remote Desktop is a VNC viewer and can therefore control any computer on the network (whether that computer is running Mac OS X, Linux, or Windows) that is:  Running the VNC server software  In an Apple Remote Desktop computer list If the you are trying to control a VNC server which is not Remote Desktop, it will not support Remote Desktop keystroke encryption. If you try to control that VNC server, you will get a warning that the keystrokes aren’t encrypted which you will have to acknowledge before you can control the VNC server. If you chose to encrypt all network data, then you will not be able to control the VNC server because Remote Desktop is not able to open the necessary SSH tunnel to the VNC server. For more information, see “Encrypting Observe and Control Network Data” on page 75. These instructions assume the observed computer has been added to an Apple Remote Desktop computer list (see “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49). When adding a VNC server to an Apple Remote Desktop computer list, you only need to provide the VNC password, with no user name. To control a VNC client computer: 1 Select a computer list in the Remote Desktop window.Chapter 7 Interacting with Users 83 2 Select one computer from the list. 3 Choose Interact > Control. If the controlled computer’s screen is larger than your control window, the screen scrolls as the pointer approaches the edge of the window. 4 To customize the control window and session, see “Control Window Options” on page 79. 5 Use your mouse and keyboard to perform actions on the controlled computer. Regardless of your Apple Remote Desktop preferences, controlled VNC servers share keyboard and mouse control. The remote computer’s keyboard and mouse are active and affect the computer just as the administrator computer’s keyboard and mouse do. Setting up a Non–Mac OS X VNC Server This section contains very basic, high-level steps for setting up a non–Mac OS X client to be viewed with Remote Desktop. This section cannot give detailed instructions, since the client operating system, VNC software, and firewall will be different. The basic steps are: 1 Install VNC Server software on the client computer (for example, a PC, or a Linux computer). 2 Assign a VNC password on the client computer. 3 Make sure the client’s firewall has the VNC port open (TCP 5900). 4 Make sure “Encrypt all network data” is not selected in the Security section of the Remote Desktop Preferences. 5 Add the computer to the Remote Desktop’s All Computers list using the client’s IP address. 6 Put the client computer’s VNC password in the Remote Desktop authentication box. There is no user name for a VNC server, just a password. Apple Remote Desktop Control and the PC’s Ctrl-Alt-Del If you use Remote Desktop to administer a PC that’s running VNC, you may be wondering how to send the Ctrl-Alt-Del command (Control-Alternate-Delete) from a Mac to the PC. Though Mac and PC key mappings differ, you can use an alternate key combination to send the command.  For full-size (desktop) keyboards, use Control-Option-Forward Delete.  For abbreviated keyboards (on portable computers), use Function-Control-OptionCommand-Delete.84 Chapter 7 Interacting with Users VNC Control Options After you have added a VNC server to a computer list (or when you are first adding it), you can set a custom port for VNC communication, and you can designate a display to control. To set a custom port on an existing computer list member: 1 Select a computer list in the Remote Desktop window. 2 Select a VNC Server computer in the Remote Desktop window. 3 Choose File > Get Info. 4 Click Edit in the Info window. 5 At the end of the IP Address or fully qualified domain name, add a colon followed by the desired port. For example, if you want to connect to a VNC server (vncserver.example.com) that is listening on TCP port 15900, you would enter: vncserver.example.com:15900 6 Click Done. To set a custom VNC port when adding a computer by address: 1 Choose File > Add By Address. 2 Enter the IP address or fully qualified domain name. 3 At the end of the IP Address or fully qualified domain name, add a colon followed by the desired port. For example, if you want to connect to a VNC server (vncserver.example.com) that is listening on TCP port 15900, you would enter: vncserver.example.com:15900 4 Enter the user name and password. 5 Click Add. To designate a display to control: 1 Add a custom port number, as described above. 2 Use the display number for the last number in the custom port designation (display designations start at 0 for the default primary display). For example, f you want to control the default display on a VNC server (vncserver.example.com) that is listening on TCP port 5900, you would enter: vncserver.example.com:5900 If you want to control the second display, you would enter: vncserver.example.com:5901Chapter 7 Interacting with Users 85 If you want to control the third display, you would enter: vncserver.example.com:5902 Configuring an Apple Remote Desktop Client to be Controlled by a VNC Viewer When configured to do so, an Apple Remote Desktop client can be controlled with a non–Apple VNC viewer. Allowing a non–Apple VNC viewer access to an Apple Remote Desktop client is less secure than using Remote Desktop to control the client. The non–Apple VNC software expects the password to be stored in a cryptographically unsecured form and location. To configure a client to accept VNC connections: 1 On the client computer, open System Preferences. 2 Click Sharing, select Apple Remote Desktop, then click Access Privileges. 3 Select “VNC viewers may control screen with the password.” 4 Enter a VNC password. 5 Click OK. Observing You may not want to control a computer, but merely monitor what is on its screen. Observing a remote computer is similar to controlling one, except your mouse movements and keyboard input are not sent to the remote computer. Apple Remote Desktop client computers can be observed on any administrator computer that has the “Observe” permission set. See “Apple Remote Desktop Administrator Access” on page 59 for more information about Apple Remote Desktop permissions. Warning: Do not use the same password as any user or Apple Remote Desktop administrator. The password may not be secure.86 Chapter 7 Interacting with Users Remote Desktop allows you to observe multiple clients on the same screen, cycling through the list of observed computers. This allows you to monitor many screens without having to select each one individually. Dealing With Many Client Screens When observing a single client, you can see the client window at full size, or scaled it to fit the observe window. To switch between the full size and fitting to the window, click the Fit to Window button, just as you would in a control window. If you’re observing more clients than you’ve chosen to fit on one screen, you can cycle through multiple pages by clicking the Previous or Next button. Cycle Pages: Use these buttons to manually switch to the previous or next page of screens. Getting More Information on Observed Clients There is a computer information area beneath each of the observed desktops. It’s automatically disabled when the administrator is viewing more computers than the computer information area is able to show effectively (a threshhold of about 220 pixels across). This could happen if:  the initial selection of computers is too great for the window sizeChapter 7 Interacting with Users 87  the observe window is resized, shrinking the information beneath the threshold  the setting for the number of viewed machines is changed The computer information area is reenabled when the sizes are returned to more than the image size threshhold. Changing Observe Settings While Observing While you are observing multiple computers, you can adjust the Apple Remote Desktop observe settings using the controls at the top of the observe window. These settings will be visible after clicking View Options in the toolbar. To change your observe settings:  Page Delay: Adjust the number of seconds before automatically advancing to the next page of screens.  Computers per page: Adjust the number of client screens visible on each page.  Image Quality: Adjust the screen color depth from black and white to millions of colors.  Titles: Change the titles of the displayed screens in the computer information area.  Account Picture: Add the currently logged-in user’s account picture under each observed desktop. See “Viewing a User’s Account Picture While Observing” on page 88 for more information.  Computer Status: Add a status overview icon underneath the observed desktop. See “Viewing a Computer’s System Status While at the Observe Window” on page 88 for more information.88 Chapter 7 Interacting with Users Changing Screen Titles While Observing While you are observing multiple computers, you can change the title underneath the desktops shown in the observe window. The main title can be the:  Name (the computer sharing name)  IP Address  Host Name To change your observe window titles: 1 Click View Options in the observe window’s toolbar. 2 Select Display Computer Information. 3 From the Title pop-up menu, select the desired title. 4 Click Done. Viewing a User’s Account Picture While Observing Remote Desktop can display the user’s account picture and a user-created status underneath the observed desktop. The user’s account picture is their system login icon, so it might be either a picture taken from an iSight camera, or a custom image selected in the Accounts pane of System Preferences. To view a user’s account picture: 1 Click View Options in the observe window’s toolbar. 2 Select Display Computer Information. 3 Select Account Picture. 4 Click Done. Viewing a Computer’s System Status While at the Observe Window Remote Desktop can display certain system status information underneath the observed desktop. This information gives you a basic assessment of the following service statistics:  CPU Usage  Disk Usage  Free MemoryChapter 7 Interacting with Users 89 There are two levels of detail for system statistics. The top level is a single icon (a red, yellow, or green icon). You show the second level of detail by placing the mouse pointer over the high-level status icon. The icon changes to an “i” and you can click the “i” to get more information. Clicking the icon exposes per-service status icons: Icon Indicates or One or more service statistic is red. This takes precedence over any yellow or green indicator. or One or more service statistic is yellow This takes precedence over any green indicator. Service is operating within established parameters. No service informaiton available. Service Icon Status CPU Usage Usage is at 60% or less Usage is between 60% to 85% Usage is at 85% or higher No status information is available DIsk Usage Usage is at 90% or less Usage is between 90% and 95% Usage is at 95% or higher No status information is available Free Memory Less than 80% used Between 80% and 95% used90 Chapter 7 Interacting with Users To show system status in the observe window: 1 Click View Options in the observe window’s toolbar. 2 Select Display Computer Information. 3 Select Computer Status. 4 Click Done. Shortcuts in the Multiple Screen Observe Window You can access several Apple Remote Desktop commands using icons in the observe window. You can customize the observe window with the commands that are most useful to you. For example, you may want to access the Copy Items command, the Text Chat command, and the Lock Screen command, using the buttons in the observe window toolbar. You perform Remote Desktop tasks on any computer by selecting its screen and choosing a task from the Remote Desktop menus or the observe window toolbar. Regardless of your toolbar customizations, you’ll be able to advance through pages manually, change the titling of the observed screens, change the number of client screens per page, change the number of seconds before paging, or change the color depth of the observed screens. Observing a Single Computer When you observe a single computer, the observed screen appears in a window on your administrator computer. If a screen saver is active when you observe the screen, the screen saver remains in effect. The observe window contains a “Share mouse control” button to switch to controlling the screen. To observe a single computer: 1 Select a computer list in the Remote Desktop window. 2 Select a computer in the Remote Desktop window. 3 Choose Interact > Observe. If the observed computer’s screen is larger than the observe window, the screen will scroll as the pointer approaches the edge of the window. 4 To customize the single-client observe window and session, see “Control Window Options” on page 79. The observe window’s options are the same as those of the control window. Over 95% used No status information available Service Icon StatusChapter 7 Interacting with Users 91 Observing Multiple Computers When you observe multiple client computers, each client screen is scaled down, so that several computers can be viewed at the same time. You can set the number of client screens that appear at any one time. See “Setting Preferences for the Remote Desktop Administrator Application” on page 36 for more information. If a client has a screen saver running when you start observing, the screen saver remains in effect. The screens will cycle through the entire list of selected computers, a few at a time, switching every 30 seconds, altered by the speed setting. To observe multiple computers: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Interact > Observe. The remote computer screens appear in a window. Observing a Computer in Dashboard If you are using Mac OS X version 10.4 or later, you can use the Dashboard widget to observe one client computer. The computer must be in your All Computers list and be authenticated with permission to Observe. Apple Remote Desktop does not have to be launched to use the widget. To observe using Dashboard: 1 Add the computer to your All Computers list. See “Finding and Adding Clients to Apple Remote Desktop Computer Lists” on page 49 for detailed information. 2 Activate Dashboard, and click the widget’s icon to run it. 3 Click the widget’s “Info” button to flip the widget over. 4 Supply a hostname or IP address, login name, and password or simply select the computer you want to observe (if it’s listed). 5 Click Done.92 Chapter 7 Interacting with Users Sending Messages Apple Remote Desktop allows you to communicate with users of Apple Remote Desktop client computers using text messaging. You can use text messages to give instructions or announcements, to collaborate remotely, or troubleshoot with users. There are two types of text messaging: one-way messages and two-way interactive chat. Text messages and chat are available only to Apple Remote Desktop client computers; they are not available to VNC client computers. Sending One-Way Messages You can use a one-way text message to send announcements or information to users client computers. The announcements appear in front of open application windows and can be dismissed by the user. To send a one-way text message: 1 Select a computer list in the Remote Desktop window. 2 Select one computer from the list. 3 Choose Interact > Send Message. 4 Enter your message. 5 Click Send. The text message appears on the screen of all the selected computers. Interactive Chat You can start an interactive text chat with the user of an Apple Remote Desktop client computer. This allows instant feedback from users, so you can collaborate or troubleshoot. To begin an interactive chat: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Interact > Chat. 4 Enter your message, one line at a time. The message appears real-time on the user’s screen as you type.Chapter 7 Interacting with Users 93 5 Press the Return key to complete and send each line. Viewing Attention Requests After a client user sends an attention request, the Apple Remote Desktop administrator can read the attention request text. To view attention requests: 1 Choose Window > Messages From Users. 2 Select the message you want to view. 3 Click Display to view the request’s message. Sharing Screens Apple Remote Desktop allows you to show your screen (or the screen of a client computer in your list) to any or all Apple Remote Desktop client computers in the same computer list. You can, for example, show a presentation to a classroom of computers from a single computer. Sharing a Screen with Client Computers You can share a client computer’s screen, or the administrator’s screen, with any number of clients. The client screen displays what is on the shared screen, but cannot control it in any way. To share a computer’s screen: 1 Select a computer list in the Remote Desktop window. 2 Select on or more computers in the selected computer list. These computers include the target computers and the source computer. 3 Choose Interact > Share Screen. 4 Select the screen to be shared. If you want to share the Apple Remote Desktop administrator screen, select “Share your screen.” If you want to share a client screen, select “Share a different screen,” and drag a computer from an Apple Remote Desktop computer list to the dialog. 5 Click Share Screen. The selected computer shows the shared computer screen. If the target computer’s screen resolution is lower than the shared computer’s, only the top left part of the shared screen (up to the lowest screen resolution) is seen on the target screen.94 Chapter 7 Interacting with Users Monitoring a Screen Sharing Tasks You may want to keep track of the screen sharing tasks you have begun. You can get information on all active screen sharing tasks, and can sort the tasks by time started, source screen, or target computers. To view current active screen sharing tasks: m Choose Window > Active Share Screen Tasks. Interacting with Your Apple Remote Desktop Administrator Users of Apple Remote Desktop client computers can initiate contact with a Remote Desktop administrator. Clients can ask for attention from the administrator, or cancel that attention request. Additionally, users of Apple Remote Desktop client computers can set an identifying icon for a Remote Desktop administrator to view. The Remote Desktop administrator can choose whether to view the icon or not. Requesting Administrator Attention At times, Apple Remote Desktop client computer users need to get the attention of the Apple Remote Desktop administrator. If an Apple Remote Desktop administrator is currently monitoring the client computer, the client user can send an attention request. To request administrator attention: 1 Click the Apple Remote Desktop status icon and choose Message to Administrator. The attention request window appears. 2 If the network has more than one Apple Remote Desktop administrator available, choose an administrator from the “Send message to” pop-up menu. 3 Enter the message. 4 Click Send. The attention request icon appears on the administrator’s screen.Chapter 7 Interacting with Users 95 Canceling an Attention Request If a user no longer needs the Apple Remote Desktop administrator’s attention, he or she can cancel the attention request after it has been sent. To cancel an attention request: 1 Click the Apple Remote Desktop status icon and choose Message to Administrator. 2 Click the Apple Remote Desktop status icon in the menu bar and choose Cancel Message. Changing Your Observed Client Icon By default, the icon that the Remote Desktop administrator sees while observing is the login icon for the currently logged-in user. If you had an iSight camera active when setting up your computer, you may have taken a picture of yourself for your user icon. You can change this icon, and it will change on the administrator’s observation screen. To change your login icon: 1 Prepare the picture you want to use. You could use a graphic file, or take a picture using an iSight camera. 2 Open System Preferences. The System Preferences application launches. 3 Select the Accounts pane. 4 Select your account, and choose the Picture button. 5 Replace your current account picture with the new picture. 6 Close System Preferences.8 96 8 Administering Client Computers Apple Remote Desktop gives you powerful administrative control. You can manually or automatically get detailed information about every computer, install software, and maintain systems from a single administrator computer. This chapter describes Remote Desktop’s capabilities and gives complete instructions for using them. You can learn about:  “Keeping Track of Task Progress and History” on page 96  “Installing Software Using Apple Remote Desktop” on page 101  “Upgrading Software” on page 105  “Copying Files” on page 106  “Creating Reports” on page 111  “Maintaining Systems” on page 127  “Managing Computers” on page 135  “UNIX Shell Commands” on page 143  “Automating Functions” on page 152 Keeping Track of Task Progress and History The task history area is on the left side of the Remote Desktop window (see “Remote Desktop Main Window” on page 29) with all computer lists and scanners. Every time you execute a task (generating a report, copying a file, restarting a computer), the task name, affected computers, task result, and time you execute it is stored in the Task History window (accessible via Window > Task History). The Task History list, in the main Remote Desktop window, shows the task name and result. You can collapse the Task History list to reduce its size. You can select a task in the Task History list to see some information about it, and double-click it to view a more detailed description of the task, as well as the computers involved with it. Tasks in progress appear in the Active Tasks list, where you can stop and restart them.Chapter 8 Administering Client Computers 97 Remote Desktop keeps track of three kinds of task progress: active, Task Server, and completed. Active tasks are those which are currently being processed by the client computers, and the client computers have not all reported back to the administrator console. Some tasks are so short that they only briefly appear in the list of current tasks; other tasks may take a long time and remain there long enough to return to the task and view the progress as it happens. The Active Tasks list is located in the left side of the Remote Desktop window, and has a disclosure triangle to expand or hide the list. Task Server tasks are those which have been assigned to the task server (either the one running on the administrator’s computer, or a remote one) which have not yet completed for all the task participants. Completed tasks are those which have received a task status for all participating client computers. The task description and computer list then moves to the task history list. The task history list is located in the left side of the Remote Desktop window, and has a disclosure triangle for expanding or hiding the list. In addition to the task status and notification features of Remote Desktop, you can set a task notification shell script to run when any task has completed. This script is for all tasks, but it can be as complex as your needs require. Enabling a Task Notification Script When a task completes, Remote Desktop can run a script that you create. This script is for all completed tasks, and it must be a shell script. There is a default notification script provided, which you can customize for your needs. The script must be a shell script, but you can use various other scripting environments like AppleScripts with the osascript command. To enable a task notification script: 1 Make sure you are logged in as an administrator user. 2 Open Remote Desktop. 3 Choose Remote Desktop > Preferences. 4 Click the Tasks button. 5 Select “Enable task notification script.” 6 Choose the location of the script. The default notification script is located at /Library/Application Support/Apple/Remote Desktop/Notify. 7 Close the Preferences window.98 Chapter 8 Administering Client Computers Getting Active Task Status When you get a task’s current status, you see the progress of the task, the computers involved, and their feedback to the administrator computer. To get status on a currently running task: 1 Select the Active Tasks list. 2 Select the desired task in the Remote Desktop window. The task status and computers involved are shown in the Remote Desktop window. You can make sure the main window always shows the currently running task in the main work area by setting a preference. Otherwise, the main window will continue to show the last selected computer list. To automatically show task status in the main window: 1 Make sure you are logged in as an administrator user. 2 Open Remote Desktop. 3 Choose Remote Desktop > Preferences. 4 Click the Tasks button. 5 Select “Always change focus to active task.” 6 Close the Preference’s window. Using the Task Feedback Display You can use the task feedback display to:  Retry a task on selected computers  Cancel a task in progress Tasks in progress appear in the Active Tasks list, where you can stop them, or run them again. To use the task feedback window: 1 Select the task in the task history list or active task list. 2 Change the task as desired: a Click the retry button to perform the task again. b Click the stop button to cancel the active task. Stopping a Currently Running Task If a task is in progress and Remote Desktop is still waiting for feedback from the client computers, you can stop the task. You use the Active Tasks list to stop the command in progress.Chapter 8 Administering Client Computers 99 To stop a currently running task: 1 Select the Active Tasks list. 2 Select the desired task in the Remote Desktop window. The task status and computers involved are shown in the Remote Desktop window. 3 Click the Stop button in the top-right of the main window. Getting Completed Task History After a task has received feedback from all the involved client computers, or they have experienced a communication time-out, the task is moved to the Task History list. The Task History list is located in the left side of the Remote Desktop window, and has a disclosure triangle to expand or hide the list. This list stays populated as long you’ve set in the Remote Desktop preferences. The Task History list can also be viewed in a separate window with the tasks sorted by date. To get status on a completed task: 1 Open the Task History list using the disclosure triangle. 2 Select the desired task in the Remote Desktop window. The final task status and computers involved are shown in the Remote Desktop window. or m Select Window > Task History. The final task status and computers involved are shown in a separate window. Saving a Task for Later Use You may want to save a task for later, repeated use. If you find yourself repeating certain tasks, you can save those tasks and the information about which computers go with them. Observe and Control tasks cannot be saved. Saved tasks appear in a list on the left side of the Remote Desktop main window. To save a task for later use: 1 Open the task you want to save. For example, if you want to save a Copy Items task, select Manage > Copy Items. 2 Configure the task as desired. 3 Before executing the task, click Save. 4 Name the saved task. The task appears in a list on the left side of the Remote Desktop main window.100 Chapter 8 Administering Client Computers Creating and Using Task Templates In each task configuration dialog, you can save a task’s settings to a template to reuse for future tasks of that same type. For example, if you always use certain copy options for a Copy Items task, you can save those settings as a template, and have them apply to any newly created Copy Items task. Once a task template is saved, you can select any one of the saved templates from the Templates pop-up menu. Selecting a template automatically configures the dialog box according to the saved template. If you want to perform a task similar to an existing template, you start with that template using the Template pop-up menu, then you customize the resulting task configuration dialog after applying the template. For example, if you always want to use the same Copy Items options, but you want vary the group of computers you apply it to, you create a task template by configuring the copy options dialog without selecting target computers and then saving it via the Templates pop-up menu. Then whenever you make a new Copy Items task with target computers selected, you can apply the saved settings by selecting those settings from out of the Templates pop-up menu and add your own settings afterward. You are free to make as many templates as you want either from existing templates or from scratch. Once saved, a template can be made the task’s default, with all new instances of the task opening with the default template settings. You can also edit the task template list from the Template pop-up list, removing a template, or making it the task default. There are existing, built-in templates for the Send UNIX Command task which can not be removed, see “Send UNIX Command Templates” on page 143 for more information. Note: Templates are only stored for their own task type. For example, Copy Items saved templates are not available for use with Rename Computer tasks, etc. To create a task template: 1 Open a task configuration window. You can use existing saved tasks, or a newly created task. 2 Configure the task as desired. 3 Click the Template pop-up menu, and select Save as Template. 4 Name the template, and click OK. To apply a task template: 1 Open a task configuration window. You can use existing saved tasks, or a newly created task. 2 Click the Template pop-up menu, and select the template you want. The settings in the template are now applied to the dialog window. 3 If desired, customize the task further.Chapter 8 Administering Client Computers 101 Editing a Saved Task You may want to change a previously saved task, changing whether what the task does or changing the target computers. To edit a saved task: 1 Double-click the saved task you want to edit. Alternatively, you could use Control-click or right-click and choose Edit Task from contextual menu. 2 In the task description window, change the task parameters. You can alter task preferences, and change the computer list. Remove computers by selecting them and pressing the Delete key; add computers by dragging them from a list to the task. After a task is completed, the task name, result, and time you last ran it are stored for review. The task feedback window gives a detailed account of the task, and reports success or failure for each participating client computer. To view the task feedback window: m Select the task in the Task History list. Installing Software Using Apple Remote Desktop There are several methods you can use to install software with Apple Remote Desktop. The following section describes how to install software using installer packages and metapackages, using the copy command in Remote Desktop, using installers made by other software companies, or using NetBoot or Network Install. Installing by Package and Metapackage You can install new software automatically and without user intervention by copying installer packages (.pkg or .mpkg files) to one or more remote clients. Apple Remote Desktop copies the package to the computers you choose, runs the installer with no visible window or user interaction required, and then erases the installer files on completion. Warning: Distributing copyrighted software without the appropriate license agreement is a violation of copyright law.102 Chapter 8 Administering Client Computers You can choose to initiate the installation of a package from the designated Task Server rather from a Remote Desktop task. This allows you to install packages on to computers that may not be connected to the network (with a status of “Offline”) when you run the task. The Task Server monitors the network for the next time the offline client comes online again. Then the Task Server performs the installation. For more information about designating a Task Server, see “Using a Task Server for Report Data Collection” on page 112 and “Designating the Task Server and Setting the Report Data Collection Location” on page 154. For detailed instructions about installing via the Task Server, see “Installing Software on Offline Computers” on page 103. You can install multiple packages in succession. When you execute installation of multiple packages, Remote Desktop copies over all the selected packages and then installs them. It also detects whether a restart is required and will give you a visual cue. You can tell the task to restart the computers upon completion, or restart the computers manually later. It is not possible to stop the installation of a package. Once the installation starts, it will complete (assuming no errors occur on the client). However, you can click the Stop button to stop remaining packages from being copied over and therefore halt the install. Alternatively, an administrator can use the PackageMaker application (available on the Apple Remote Desktop CD or with the Apple Developer Tools) to create a metapackage that contains several installers to be run in sequence. In addition to creating metapackages, you can also use PackageMaker to create packages for custom software that your organization may have developed. More information about making and using packages and metapackages is available on the Apple Developer Connection website: developer.apple.com To copy and install software using a .pkg file: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Install Packages. 4 Select a .pkg or .mpkg file to install. Alternatively, you can drag an installer package on to the package list window. 5 Select whether to restart the target computers after installation. 6 Select the option to run the task from “This application.” This option is preferable when installing on computers that are all currently online. If you want to install the software via a Task Server, see “Installing Software on Offline Computers” on page 103.Chapter 8 Administering Client Computers 103 7 Select other installation parameters, as desired. For more information on the available options, see “Copy Options” on page 107. Note: Client computers are not restarted automatically after an installation is complete unless explicitly selected in the task command. 8 Click Install. During installation, a progress bar appears in the task header in the main window. No progress bars appear on the client computer. The copied package is deleted from the client computer if an error occurs during installation. However, a failed installation may leave behind other files created by the installer. Installing Software on Offline Computers Using Apple Remote Desktop, you can install software on a computer that is not currently connected to the network (with a status of “Offline”). The installation does not occur when initially ordered, but when the offline computer next becomes available. The installation itself is handled by a designated Task Server. The Task Server will continue to monitor the network for the next time the offline client comes online again. For more detailed information about setting up and using a Task Server, see “Designating the Task Server and Setting the Report Data Collection Location” on page 154. To install software on offline clients: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. Any or all may be offline. 3 Choose Manage > Install Packages. 4 Select a .pkg or .mpkg file to install. Alternatively, you can drag an installer package into the Packages list. 5 Choose whether to run the task from the Task Server designated by Remote Desktop’s preferences. To set up or alter the Task Server, see “Using a Task Server for Report Data Collection” on page 112 and “Designating the Task Server and Setting the Report Data Collection Location” on page 154. 6 Select other installation parameters, as desired. For more information on the available options, see “Copy Options” on page 107 and “Installing by Package and Metapackage” on page 101. 7 Click Install.104 Chapter 8 Administering Client Computers Installing by Using the Copy Items Command Many applications can be installed simply by copying the application or its folder to the client computer. Consult the application’s documentation to verify that you can simply copy the application to the hard disk to install it. To install software by copying: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Copy Items. 4 Add software to the “Items to copy” list. For more information, see “Copying Files” on page 106. Repeat this step until all the software you want to copy is in the list. 5 Select a destination. There are several preset locations available in the “Place items in” pop-up menu, including the Applications folder. If you do not see the location you want, you can specify a full pathname. 6 Select your copy options. See “Copy Options” on page 107 for more information on the available options. 7 Click Copy. The software is copied to the indicated location. If the copy operation is unsuccessful, an error message appears in the task feedback window. Using Installers from Other Companies The Install Packages command only works with installers that use the .pkg or .mpkg file format, and some applications can’t be installed by simply copying the application to the hard disk. To install software using installers with different file formats, you use a combination of tasks. To install software with third-party installers: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Copy Items. 4 Add the software installer to the “Items to copy” list. For more information, see “Copying Files” on page 106. 5 Select a copy destination. 6 Select After Copying Open Items. 7 Click Copy.Chapter 8 Administering Client Computers 105 The software is copied to the indicated destination. If the copy is operation unsuccessful, an error message appears in the task feedback window. 8 Select a computer that received the copy of the installer. 9 Choose Interact > Control. 10 Control the screen of the selected computer and complete the installation process interactively. Upgrading Software Upgrading software is similar to installing software. However, the method of upgrading software depends on the original method of installation. As a general rule, upgrades should not be done while users have their applications open. Make sure the software to be upgraded is not running. Upgrading consists of three main tasks:  Finding out if a piece needs to be updated  Removing the old version  Installing the new version To upgrade software on client computers: 1 Run a Software Version report to determine what version of the software client computers have. See “Generating a Software Version Report” on page 118 to learn how to run the report. 2 Remove the old version of the software. If the software was originally installed using a package or metapackage, it should be removed automatically when you install the new version. If the software was originally installed using the Copy Items command, you can delete the old version, or simply replace the old version with the new version when you install the new version. If the software was originally installed using another company’s installer application, you may need to use an uninstaller before installing the new version. Consult the software’s manual for instructions on removing its software. If an uninstaller application is necessary, you can copy it to each of the client computers and run it remotely. Warning: Distributing copyrighted software without the appropriate license agreement is a violation of copyright law.106 Chapter 8 Administering Client Computers 3 Use the appropriate installation method to install the new version of the software. For more information, see:  “Installing by Package and Metapackage” on page 101  “Installing by Using the Copy Items Command” on page 104  “Using Installers from Other Companies” on page 104 Copying Files Apple Remote Desktop makes it easy to copy items (other than the system software) on one or more client computers. Copying files works fastest with a small number of files. For example, ten files that are 10 KB each generally take longer than one file that is 100 KB. Consider copying a single file archive (like a .zip or .sit file) to remote computers for faster copying. Remember that Mac OS X applications are bundles of many smaller files. Although the application you want to copy looks like a single file in the Finder, it may contain hundreds, or even thousands of smaller files. If a client computer is asleep when you attempt to copy items, Remote Desktop tries to wake the client. If it can’t wake the client and the copy does not proceed, you should use Remote Desktop to wake the target computer, and then attempt the copy again.Chapter 8 Administering Client Computers 107 If you choose to copy out to many client computers simultaneously, Remote Desktop uses network multicasts to send the files. If there is a significant number of multicast networking errors, Remote Desktop tries to copy individually to each client computer. Copy Options Each time you copy an item to a remote computer, you have the chance to customize the operation to allow fine-grained control of the location and file owner of the copied file, the network bandwidth used, and what to do in case of failure or duplicate files. Copy Destination Locations There are several preset destinations available in the “Place Items In” destination popup menu, including the Applications folder. If you do not see the destination you want, you can specify a full pathname. Owner and Group for Copied File By default, the copied files inherit the owner and group of the enclosing destination folder. For additional flexibility, you have several options for handing file ownership. You can:  Preserve current owner  Set the owner to the current console user  Specify user and group Encryption You can encrypt the copy transport stream to protect the data sent across the network. By selecting the “Encrypt network data” option, you exchange performance for security. This option is also available in the Install Packages dialog. Copy Failure Handling By default, if a single computer fails to get the copied file, the copy operation continues to all participating computers. However, there may be times when you want a copy operation to stop if one of the copies fails. You can choose to cancel the entire copy operation if one participating computer reports a failure. This option is also available in the Install Packages dialog. Network Bandwidth Limits File copies are done at the maximum sustainable rate for the network. This allows Apple Remote Desktop to use all the resources at its disposal to quickly and efficiently finish the copy. Depending on what else is being done on the network, you may want to explicitly limit the copy data transfer rate. You can set an approximate maximum data rate in kilobytes per second for file copies. This option is also available in the Install Packages dialog.108 Chapter 8 Administering Client Computers More Options When the Item Already Exists If an item with the same name as the item you selected to copy already exists at the destination, you have several options for handing the name conflict. You can:  replace the existing item  replace the existing item if the existing item is older  rename the existing item  rename the item being copied  always ask which of the above options you want to use Post-Copy Action You can choose to open a copied item immediately after it’s copied. If you select this option, the file will open with the parent application that created it. Copying from Administrator to Clients Using Apple Remote Desktop, you can copy items to any number of client computers simultaneously. To copy items to clients: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the Remote Desktop window (or any window). 3 Choose Manage > Copy Items. 4 Add software to the “Items to copy” list. Click the Add button to browse local hard disks for items to copy, or drag files and folders to the list. If you want to remove an item from the list, select the item and click Remove. Repeat this step until all the software you want to copy is in the list. 5 Select your copy options. See “Copy Options” on page 107 for more information on the available options. 6 If you want to schedule this event for another time, or set it to repeat, click the Schedule button. See “Scheduled Tasks” on page 155 for more information about scheduling events. 7 Click Copy. The software is copied to the indicated destination. If the copy is unsuccessful, an error message appears in the task feedback window.Chapter 8 Administering Client Computers 109 Copying Using Drag and Drop Using Apple Remote Desktop, you can copy items by dragging them between Finder windows on your administrator computer, the Remote Desktop window, and control windows. For example, you can drag an item from a Finder window to a selected computer in the Remote Desktop window. You can use this feature to collect needed files from remote computers or distribute files between remote computers. Copying from the Finder to a Client You can copy files, applications, or folders from the administrator’s Finder windows to remote computers. You can also drag items directly on to a control window. To copy items from the Finder to a client: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers or select the desired Control window. 3 Switch to the Finder. 4 Locate the item you want to copy in the Finder. 5 Drag the item you want to copy from the Finder to the selected clients in the Remote Desktop window or control window. Copying onto a Control window puts the file wherever you drop it. 6 Select your copy options. See “Copy Options” on page 107 for more information on the available options for copy tasks. 7 Click Copy. Copying from a Client to the Finder Using Apple Remote Desktop, you can copy files, applications, or folders from a remote computer to the administrator’s computer. The process requires that you find the file you want to copy, using a report or locating them in a control window. Note: Copied items retain their original owners and permissions. To copy items from a client to the administrator’s computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose a file search report to find the item. See “Finding Files, Folders, and Applications” on page 116 for more information. 4 Select the item you want to copy in the report window. 5 Drag the item you want to copy from the report window to the administrator’s Finder, or click the Copy To This Computer button in the menu bar of the report window.110 Chapter 8 Administering Client Computers Alternatively, you can drag items from a control window to the administrator computer’s desktop. Restoring Items from a Master Copy Your client computers can restore non-system software from a master copy. This is helpful if you want to make sure each client computer has the same software. You can automate the software restore process by using the instructions in “Automating Functions” on page 152. You may want to start by creating a disk image that contains the Mac OS X applications and items you want to copy. Alternatively, you can copy files from any local disk, such as a hard disk, CD, disk partition, or other disk. The Copy Items command does not copy system software that is hidden (that is, not visible in the Finder). It can copy the Applications folder, Library folder, and Users folder, as well as any folders at the root of the hard disk that were created by the computer’s administrator user. Important: You cannot use the Copy Items feature to copy Mac OS X system software to client computers To restore files using the Copy Items command: 1 Make a master copy of the volume that has the files to be restored. You can use any volume, such as a spare hard disk, a CD, or a mounted disk image (.dmg) file. 2 Mount the master copy volume on the administrator computer. Master copy volumes must be local volumes, not mounted from over a network. 3 Open Remote Desktop. 4 Select a computer list in the Remote Desktop window. 5 Select one or more computers in the selected computer list. 6 Choose Manage > Copy Items. 7 Add the master copy volume to the Copy Items list. 8 Select your copy options. See “Copy Options” on page 107 for more information on the available options for copy tasks. 9 If you want to schedule this event for another time or set it to repeat, click the Schedule button. See “Scheduled Tasks” on page 155 for more information about scheduling events. 10 Click Copy.Chapter 8 Administering Client Computers 111 Creating Reports Apple Remote Desktop allows you to query client computers for many kinds of information, from installed software to network speed and reliability. Creating reports gives you valuable information about the client computers. Reports also help when you’re copying files and organizing computer lists. Collecting Report Data There are three search strategies that Apple Remote Desktop uses when searching for report information: new data, cached data, and Spotlight data. With a new data search, the Remote Desktop application queries a client directly, and waits for the client computer to respond with the desired information. A new data search gets the most recent information, but takes longer since the client computer has to gather all the data and send it over the network to the waiting administrator computer. New data reports are also generated by clients whose reporting policy is set to send data only in response to a report query. See “Setting the Client’s Data Reporting Policy” on page 152. The next source of information is a cached data search. With a cached data search, the application queries Apple Remote Desktop’s internal database of collected system information (such as hardware information and system settings), file information (including installed applications and versions, and software names), or both. You determine how often the data is collected, and what type of data is stored. See “Setting the Client’s Data Reporting Policy” on page 152.112 Chapter 8 Administering Client Computers The database, which is a PostgreSQL database located at /var/db/RemoteManagement/ RMDB/ can be accessed using other tools besides Remote Desktop. To find out more about the database schema, see “PostgreSQL Schema Sample” on page 180. The last kind of new data search is a Spotlight search. This is not a static report on saved data in a database, but it’s an interactive search of the client computers. A Spotlight search can only be done on client computers running Mac OS X 10.4 or later. Spotlight searches a comprehensive, constantly updated index that sees all the metadata inside supported files—the “what, when and who” of every piece of information saved on your Mac—including the kind of content, the author, edit history, format, size, and many more details. Spotlight searches are “live” meaning that the window reflects changes in the found files even after the command is executed. Using a Task Server for Report Data Collection You can use a computer other than the administrator computer to collect your report data, if you have another unlimited-managed computer license for Apple Remote Desktop. Using a server that is always running and has the benefits of uninterrupted power and steady uptime, you can dedicate those computing resources to report data collection. Such a server is referred to as a Task Server. To use a Task Server, you need:  a computer that will be running when the clients are set to upload their report data  an unlimited license for the Remote Desktop server  a separate unlimited license for the administrator computer To set up a Task Server, you need to: 1 Install Remote Desktop on the server. See “Installing the Remote Desktop Administrator Software” on page 40. 2 Configure the server to be the Task Server. You do this via the server settings in the Remote Desktop preferences. See “Designating the Task Server and Setting the Report Data Collection Location” on page 154 3 Install Remote Desktop on the administrator computer. See “Installing the Remote Desktop Administrator Software” on page 40. 4 Configure Remote Desktop on the administrator computer to use the Task Server as its source for report data. You do this using the server settings in the Remote Desktop preferences. See “Designating the Task Server and Setting the Report Data Collection Location” on page 154. 5 Set the client reporting policy to tell clients to send report information to the Task Server.Chapter 8 Administering Client Computers 113 You do this using the Get Info window of any client computer or the client’s own Apple Remote Desktop preferences. See “Setting the Client’s Data Reporting Policy” on page 152 and “Creating a Template Data Reporting Policy” on page 153. Report Database Recommendations and Bandwidth Usage You can have a single Apple Remote Desktop data collection database for any number of clients. However, avoid having all the clients upload their report information at the same time. As the number of clients grows, the network usage from the clients as they upload their report data could come in bursts over a short period of time overwhelming the network buffer on the Task Server. In such a case, you will probably give yourself your own denial-of-service attack. Increasing the number of Task Server computers can divide the network and computing load among several computers for better performance and better network citizenship. However, since there is no way to aggregate report data across several collectors and display it on one administrator computer, you would need multiple administrators to balance your network load in this manner. If you use a single database for a large number of clients, it is recommended that you stagger the generation of report caches over the time between which you want to run reports. For example, if you normally run a report every week, then set 1/7th of your clients to rebuild caches on day one, another 1/7th for the next day and so on. Additionally, they should stagger the cache rebuild over the course of the day as well. It is recommended that you keep in a given list the minimum number of computers necessary for your purposes. When a list is selected, the clients in the list send status updates at a minimum of every 20 seconds. If you have a large number of clients in a list (for example, 1000), this makes about 50 updates a second. Creating more lists doesn’t create more resource overhead for Remote Desktop, and can allow you to quickly and easily administer the clients you want with a minimum wait. Depending on your network and list sizes, you may find that smaller lists may result in more productive and reliable administration. What Bandwidth Does the Default System Overview Report Use on a LAN? The average System Overview Report cache is about 20 KB. While reporting, the admin and clients will always try to use all available bandwidth (most IP-based client/server applications work this way). Therefore, on a 10Mbit/sec. network, the report data collection for a single client may use 100% of the bandwidth for a period of 0.016 seconds. Assuming a list of 1000 computers, all trying to report at the same time, this may use 100% of the bandwidth for 16 seconds. Naturally, faster networks will perform better, and networks with a slow bottleneck like a DSL or modem line perform worse.114 Chapter 8 Administering Client Computers System Report Size The file system data which is uploaded to the report database (labeled “File Search data” in the Scheduling sheet of the Task Server preference pane) contains a significant amount of data. For a client with 10 GB of files on the hard disk, the report data uploaded can easily reach 5 MB in size. With hundreds or thousands of clients, this amount can add up quickly and might tax network resources. In addition, by choosing to upload user accounting data and application usage data, you are further increasing the size of the uploaded data for any one client. Since you may not want to store all the possible information for a given client computer, you can customize which type of data is collected, as desired. Auditing Client Usage Information With Apple Remote Desktop, you can get detailed information about who has been using the client computers and how. There are two reports that help you audit information about how the clients are being used:  the User History report  the Application Usage report Generating a User History Report The User History report is used to track who has logged in to a computer, when they logged in and out, and how they accessed the computer. The client stores 30 days of accumulated data, so the requested time can’t be more than the last 30 days. The report shows the following information:  computer name  user’s short name  access type (login window, tty, SSH)  login time  logout time  remote login host (originating host to the login session: localhost, or some remote computer) Note: Multiple users logged in via Fast User Switching can lead to confusing or conflicting reports. When a second or third user logs in to a computer, there is no way of knowing which user is the active user. Session length may not reflect actual usage, and login and logout times overlap. User History report information is collected by default if you are installing Remote Desktop for the first time. If you have upgraded an older version of Remote Desktop, you need to enable its collection explicitly in the clients’ reporting policy. See “Setting the Client’s Data Reporting Policy” on page 152 for instructions.Chapter 8 Administering Client Computers 115 To generate a User History report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > User History. 4 Select the time frame for the user history information. 5 Click Generate Report. The newly generated report window appears. Generating an Application Usage Report The Application Usage report shows which applications have been running on a given client, their launch and quit time, and who launched them. The client stores 30 days of accumulated data, so the requested time can’t be more than the last 30 days. The following fields are shown by default in the report:  Computer name  Name of application  Launch date  Total running time  Time as frontmost application  User name of process owner  Current state of application Application Usage report information is collected by default if you are installing Remote Desktop for the first time. If you have upgraded an older version of Remote Desktop, you need to enable its collection explicitly in the clients’ reporting policy. See “Setting the Client’s Data Reporting Policy” on page 152 for instructions. To generate an Application Usage report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Application Usage. 4 Select the time frame for application usage. 5 Click Generate Report. The newly generated report window appears.116 Chapter 8 Administering Client Computers Finding Files, Folders, and Applications Apple Remote Desktop allows you to search the contents of client computer hard disks for specific files, folders, or applications. Additionally, it can compare the results of such searches to the items on the administrator computer. These searches can compare software versions, fonts, applications, or installed packages. Using Spotlight to Find Items You can use Spotlight to find items on client computers. A Spotlight search can be done only on client computers running Mac OS X v10.4 or later. Spotlight searches are “live,” meaning that the window reflects changes in the found files even after the command is executed. Spotlight searches cannot be used for offline client computers. The Spotlight Search window is similar to the Spotlight Search window found locally on a Mac OS X v10.4 computer. It supports many of the same features and queries as Spotlight on a local computer. For more information on running a Spotlight search, see Spotlight Help. To search for software items using Spotlight: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Interact > Spotlight Search. 4 Choose the desired search parameters and enter a search term. The results are updated immediately in the window.Chapter 8 Administering Client Computers 117 The results of the search are listed in the pane at the bottom of the window. Note: The “Home” Spotlight search location means the Home folder of the currently logged in user. Generating a File Search Report The File Search report allows you to find up to a total of 32,000 items on selected computers. The items can be files, folders, or applications, but they can only be items accessible (or visible) in the Finder. The search parameters include:  Name  Parent path  Full path  Extension  Date created  Date modified  Size on disk  Kind  Version number  Version string  Owner  Group  Lock status The search parameters for Apple Remote Desktop are slightly different from those used by the Finder’s Find command. For example, Apple Remote Desktop does not search by visibility or by label. The report display can be customized as well. See “Changing Report Layout” on page 35 for more information. To search for software items: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > File Search. 4 Choose the desired search parameter from the pop-up menu and enter a search term. 5 If you want to customize the report display, do so now. For more information about the report display, see “Changing Report Layout” on page 35 for more information. 6 To search using new data, check Rebuild Data For Report; to search using saved data only, uncheck Rebuild Data For Report.118 Chapter 8 Administering Client Computers 7 Click Search. The newly generated report window appears. Comparing Software Apple Remote Desktop has several specialized reports for comparing software on client computers with software on the administrator computer. These reports can’t be run comparing two client computers. One computer in the comparison must be the administrator computer. Generating a Software Version Report The Software Version report compares application versions on client computers with application versions on the administrator computer. You can select up to 10 applications to compare. Command-line tools and unbundled Java (.jar) applications do not report their version. To generate a Software Version report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Software Version. 4 Select the software you want to compare, from the application list. You can select up to 10 applications. If the application you want doesn’t appear in the list, click the Add (+) button to browse for the application. 5 To search using new data, check Rebuild Data For Report. 6 Click Generate Report. The newly generated report window appears. Generating a Software Difference Report The Software Difference report compares the applications, fonts, and installed packages of the selected client computers with those on the administrator computer. The resulting report lists the items compared, their version, location, and whether or not they were found on the selected client computers. The Software Difference report can compare all executable Mac OS X and Classic applications. Unbundled Java (.jar) applications and command-line utilities are not included in the report. The report can compare all the fonts in the /System/Library/ Fonts/ and /Library/Fonts/, as well as the Fonts folder for the currently logged in user. Comparing installed packages returns a list of all package receipts in /Library/Receipts/. You can use this report to find out if your clients have the applications or fonts they need. Comparing differences in installed packages can help you troubleshoot software conflicts, and keep your client computers up to date.Chapter 8 Administering Client Computers 119 To generate a Software Difference report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Software Difference. 4 Select the software type you want to compare. Selecting Applications compares all executable applications. You can limit which folder on the administrator computer Remote Desktop uses to look for applications. Selecting Fonts compares all fonts in /Library/Fonts/, /System/Library/Fonts/, and user font directories. Selecting Installed Packages compares all package receipts in /Library/Receipts/. 5 To search using new data, select Rebuild data for report. 6 Click Generate Report. The newly generated report window appears. Auditing Hardware You can get a report about the hardware of any client computer. Hardware information can be accessed using a number of different reports. Although some basic hardware information can be found in the System Overview report, several more focused hardware reports provide more detailed information. To get a basic System Overview report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > System Overview. 4 Select or deselect hardware items as desired. 5 To search using new data, select Rebuild data for report. 6 Click Get Report. The newly generated report window appears.120 Chapter 8 Administering Client Computers Getting Serial Numbers Although there is no specific serial number report for Apple Remote Desktop, the serial number of any client is in the Computer section of the System Overview Report. In addition to using Apple Remote Desktop to retrieve a computer’s serial number, you could use the command-line tool systemprofiler with Apple Remote Desktop’s Send UNIX Command feature. To generate a serial number report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > System Overview. 4 Select Serial Number from the Computer section. 5 Select or deselect other items as desired. 6 To search using new data, check Rebuild Data For Report. 7 Click Get Report. The newly generated report window appears. Getting Storage Information The Storage report collects information about the client computer’s internal hard disks. It can get information about the hardware itself, the volumes on the disk, file system information, and journaling information for the disk. For a complete listing of Storage report options, see “Report Field Definitions Reference” on page 165. Basic information about hard disk volumes and size can also be found in the storage section of the System Overview report. To generate a Storage report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Storage. 4 Select the hard disk information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears.Chapter 8 Administering Client Computers 121 Getting FireWire Device Information The FireWire Devices report gets information about FireWire devices connected to the client computer. It can get the following information from a device:  Manufacturer  Model  Device speed  Software version  Firmware revision For more information about FireWire Devices report options, see “Report Field Definitions Reference” on page 165. The number of attached FireWire devices can also be found in the Devices section of System Overview report. To generate a FireWire Devices report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > FireWire Devices. 4 Select the FireWire information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears. Getting USB Device Information The USB Devices report gets information on Universal Serial Bus devices (scanners, keyboards, mice, and so forth) connected to the client computer. It can get the following information from a device:  Product name and ID  Vendor name and ID  Device speed  Bus power amps For more information about the USB Devices report options, see “Report Field Definitions Reference” on page 165. Basic information about attached USB devices can also be found in the Devices section of the System Overview report.122 Chapter 8 Administering Client Computers To generate a USB Devices report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > USB Devices. 4 Select the USB device information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears. Getting Network Interface Information The Network Interfaces report gets information for all network interfaces, including inactive interfaces. It also gets detailed network, output, and Ethernet statistics from client computers. The Network Interfaces report can be used to find network errors or faulty network equipment, troubleshoot network performance, and query the network settings of the client computers. All detailed statistics are refreshed when the client restarts, and address information may change if your client uses DHCP to get a network address. For a complete listing of Network Interfaces report options, see “Report Field Definitions Reference” on page 165. Basic information about network settings can also be found in the Network and AirPort section of the System Overview report. To generate a Network Interfaces report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Network Interfaces. 4 Select the interface information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Generate Report. The newly generated report window appears.Chapter 8 Administering Client Computers 123 Getting Memory Information The Memory report gets specific information about the installed memory in a client computer. In addition to reporting how much memory the client has, it shows information about each memory module, including the module’s:  Slot identifier  Size, type, and speed Memory reports can be used for managing computer resources, hardware troubleshooting, or deciding which client computer can handle a memory-intensive application or task. For more information about the Memory report options, see “Report Field Definitions Reference” on page 165. Basic information about system memory can also be found in the Computer section of the System Overview report. To generate a Memory report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Memory. 4 Select the module information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears. Getting PCI Card Information The PCI Cards report gets information about the PCI cards installed in a client computer. It shows information about each PCI card, including each card’s:  Slot name  Card name, type, memory, and revision  Vendor and device IDs  ROM revision For more information about the PCI Cards report options, see “Report Field Definitions Reference” on page 165. Basic information about a client’s PCI cards can also be found in the Computer section of the System Overview report.124 Chapter 8 Administering Client Computers To generate a PCI Cards report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > PCI Cards. 4 Select the PCI card information desired. 5 To search using new data, select Rebuild Data For Report. 6 Click Get Report. The newly generated report window appears. Testing Network Responsiveness Apple Remote Desktop can test network responsiveness between your administrator computer and client computers. It sends network packets to the clients and reports the time taken to receive confirmation from the clients. You can choose how many network packets to send, how often they are sent, and how long the administrator computer waits for a reply before listing a packet as lost. To generate a Network Test report: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > Network Test. 4 Select the options you want. Choose the number of packets sent from the Packets pop-up menu (Total Packets to Send). Choose how often to send the send packets from the Interval pop-up menu (Interval Between Packets). Choose how long to wait before reporting a packet as lost from the Time Out pop-up menu (Packet Time Out). 5 Click Get Report. The newly generated report window appears. Evaluating the Network Test Report You can use the Network Test report to diagnose whether task failures in Apple Remote Desktop are due to network congestion or to some other factor. You may, for example, find that a Copy Items task is failing on a particular subnet, due to network congestion on that subnet.Chapter 8 Administering Client Computers 125 Here are some suggestions for evaluating your network performance based on this report:  The number of routers between your computer and another computer can affect the time the packets take to return. When you evaluate the times for a computer, you should compare them to the times for a computer in the same area of the network or with the same number of intervening routers.  If the maximum time for a packet to return from a computer is significantly greater than the time for other computers in the same area of the network, there may be a problem with the computer.  If a single computer has a large number of lost packets, there may be a problem with the network connection to that computer.  If several computers in the same area of the network have a large number of lost packets, there may be a network connection problem or a problem with an intervening router or bridge. Exporting Report Information You can export reports into a comma-delimited or tab-delimited text file. All the columns of information in the report window are included, and the report rows are exported in the order they’re sorted at the time of export. Exported reports can be put into a database, spreadsheet, or word processor for further analysis or organization, or be sent to another administrator. You could even use certain reports as input files for network scanners for Remote Desktop. Alternatively, you could access the report’s SQL database directly with your own SQL query tools or applications. Using standard SQL database queries you can get any or all information out of the report database for use with other applications or databases. To export a report: 1 Generate any report, and bring the report window to the front. 2 If desired, sort the report rows by selecting a new column to sort by. 3 If you do not want to export the entire report, select the rows to be exported. 4 Choose File > Export Window. 5 Name the file, and choose a location to save to. 6 Select a text encoding.  Western (Mac OS Roman): Best choice if the report information uses the Roman alphabet, and the exported document will be opened in an application or on an operating system that does not support Unicode text encoding (for example, some installations of Mac OS 9).  Unicode (UTF-8): Best choice if the exported file will be opened on Mac OS X and contains no Asian language characters (such as Chinese or Japanese).126 Chapter 8 Administering Client Computers  Unicode (UTF-16): Best choice if the report contains Asian language characters. 7 Select a field separator.  Tab: Inserts a Tab character between column values.  Comma: Inserts a comma between column values. 8 If you have selected only some rows of the report and want to export only the selected rows, select Export Selected Items Only. 9 Click Save. Using Report Windows to Work with Computers After you’ve created a report, you can use it to select computers and then do any of the following:  Create new computer lists. Select computers in the report window and select File > New List From Selection.  Generate other reports. Select any number of rows in a report window; then choose another report from the Report menu. The new report will be generated based on the computers in the selected rows.  Initiate any management task. Select any row in a report window; then choose a management task from the Manage menu. This has the same effect as selecting the computer in an Apple Remote Desktop computer list.  Interact with users. Select any row in a report window; then choose a task from the Interact menu. This has the same effect as selecting the computer in an Apple Remote Desktop computer list.  Delete a file from a computer. Select a file in any file or software report window and click the Delete button.  Copy an item to your computer. Select an item in any software report window and click Copy to This Computer.Chapter 8 Administering Client Computers 127 Maintaining Systems Apple Remote Desktop provides easy and powerful tools for maintaining client computers, including tasks such as deleting files, emptying the Trash, and setting computer startup options. Deleting Items If you delete a file from a client computer, it is moved to the client’s Trash. To delete an item from a client: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Report > File Search. 4 Find the software you want to delete, using the File Search report. For more information, see “Finding Files, Folders, and Applications” on page 116. 5 Select the item or items you want to delete in the File Search report window. 6 Click Delete Selected in the report window. 7 Click Delete.128 Chapter 8 Administering Client Computers Emptying the Trash Apple Remote Desktop allows you to empty the Trash on clients to free up disk space. To find out how much free disk space is on a computer, create a System Overview or Storage report using the Report menu. As a part of routine maintenance for client computers, you can free disk space by emptying the Trash. Emptying the Trash completely removes any items you’ve previously deleted on the client. You can use the System Overview report to see how much disk space you can recover by emptying the Trash. To empty the Trash: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Empty Trash. 4 Click Empty. Setting the Startup Disk Apple Remote Desktop can set the startup disk on any client computer. You can choose between a volume on a local hard disk or any available NetBoot volume. The startup disk must have a valid operating system installed on it. To set the startup volume on a local hard disk for multiple computers at once, the local volume name must be the same for all computers. Alternatively, you can set the startup disk to be a NetBoot volume provided by Mac OS X Server. This allows you to start up a number of clients from a NetBoot server. To set the startup disk: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Set Startup Disk. The list that appears shows the client’s local hard disk, a custom NetBoot server item, and a list of all available NetBoot and Network Install servers available on the local network subnet. 4 Choose the client’s local hard disk or a NetBoot server volume. 5 If you want to choose a specific local hard disk volume, select Hard Disk, click Edit, and enter the desired volume name. 6 If you want to choose a custom NetBoot server volume, enter the server IP address or fully qualified domain name, and the NetBoot volume name. 7 If desired, select Restart When Done.Chapter 8 Administering Client Computers 129 If you select Restart When Done, the client computer will restart after having its startup volume set. You need to have Restart privileges to use this option. 8 Click Set. Renaming Computers Apple Remote Desktop can set the name that a client computer uses for file sharing. You can rename multiple computers with the same name followed by a number (such as Computer1, Computer2, and so on). This is especially useful for differentiating client computers after a clean system installation. Note: The Rename Computer feature does not change the Local Hostname or the DNS name of a client computer. To rename a computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Rename Computers. 4 Enter the new computer name. 5 If desired, select “Append a unique number for each computer.” Selecting this option appends a unique number to the end of the computer name. For example, if you rename three computers “Computer,” the computers will be named “Computer1,” “Computer2,” and “Computer3.” 6 Click Rename. Synchronizing Computer Time Maintaining synchronized clocks across your clients is essential for management reliability. Synchronized times allow for more precise audits and allow you to accurately correlate events between clients on the network. In addition, many internet services rely on, or benefit from, clock times that are synchronized to a Network Time Protocol (NTP) server. Any scheduled event benefits from synchronized client time. All Mac OS X clients can be set to automatically synchronize their clocks with an NTP server. Mac OS X Server can be configured to act as an NTP server as well. In order to maintain synchronization across your clients, you should choose a single NTP server to synchronize to. Apple provides an NTP server at time.apple.com. Setting computer time requires the use of Apple Remote Desktop’s Send UNIX Command feature and its built-in command-line tool, systemsetup. See “Built-in Command-Line Tools” on page 147 for more information about the tool.130 Chapter 8 Administering Client Computers To synchronize client computer clocks: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to set the time server (see “Send UNIX Command Templates” on page 143 for more information). a Select System Setup > Network Time from the Template pop-up menu. b Click Send. c Select System Setup > Network Time Server from the Template pop-up menu. Change the time server from time.apple.com to whichever time server you want, if desired. 5 Alternatively, manually enter the UNIX command. a Type or paste the following UNIX command: systemsetup -setusingnetworktime on -setnetworktimeserver b Set the user permissions for this command to be sent as the user “root.” 6 Click Send. Setting Computer Audio Volume You may want to standardize or otherwise configure the output volume of your computers. You could use this to silence a lab of computers all playing music, or turn up the volume on a single remote computer for a user’s benefit. You can also set the alert volume separately from the output volume and input volume. Additionally you can set “output muted.” Muting the volume causes the computer to remember what the previous volume level was and return to it when the sound is enabled again. Setting computer audio volume requires the use of Apple Remote Desktop’s Send UNIX Command feature, AppleScript, and the command-line tool osascript. See “UNIX Shell Commands” on page 143 for more information. See AppleScript’s StandardAdditions dictionary for information about using this tool. To set a computer’s audio volume: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to set the computer volume (see “Send UNIX Command Templates” on page 143 for more information). a Select Miscellaneous > Volume On from the Template pop-up menu. b Set the desired volume level in the Send UNIX Task dialog.Chapter 8 Administering Client Computers 131 5 Alternatively, manually enter the UNIX command. a Type or paste the following UNIX command: osascript -e 'set volume output volume any_number_from_0-100' b or for Mac OS X v.10.3 clients enter or paste the following: osascript -e 'set volume any_number_from_0-7' 6 Click Send. Repairing File Permissions Sometimes a client’s system file permissions can be corrupted or changed from their expected values. In such a case, it may be necessary to manually repair the permissions on the client. Repairing permissions returns system and library files to their default settings. Repairing file permissions requires the use of Apple Remote Desktop’s Send UNIX Command feature, and the command-line tool diskutil. See “UNIX Shell Commands” on page 143 for more information. For information about using this tool, see diskutil’s man page. To repair a computer’s file permissions: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type or paste the following UNIX command: diskutil repairPermissions / 5 Set the user permissions for this command to be sent as the user “root.” 6 Click Send. Adding Items to the Dock If you install software on your client computers by dragging and dropping, the file, folder, or application isn’t immediately added to the user’s Dock. The instructions provided here are a workaround for clients that are not part of a managed client environment. Note: Dock management is best done in a Mac OS X Server Workgroup Management environment. If you use Mac OS X Server to manage client settings and preferences, the correct place to change the Dock is within the management settings of Workgroup Manager. To add an application or other item to the Dock: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command.132 Chapter 8 Administering Client Computers 4 Type or paste the following UNIX command (replace /Path_To_Application with your own path to the desired application, and be sure to include the application file extension, .app): defaults write com.apple.dock persistent-apps -array-add 'tiledatafile-data _CFURLString/Path_To_Application _CFURLStringType0 ';killall -HUP Dock Use “persistent-others” instead of “persistent-apps” if the item is anything other than an application. 5 Set the permissions for those of currently logged-in user. 6 Click Send. Changing Energy Saver Preferences You can get and change the settings found in the Energy Saver pane of System Preferences. You can change the computer sleep time, as well as other Energy Saver Options. You can set all the clients to have the same sleep time and even turn on the preference necessary for them to respond to the Apple Remote Desktop Wake command (“Wake for Ethernet network administrator access”). Changing the Energy Saver preferences requires the use of Apple Remote Desktop’s Send UNIX Command, and its built-in systemsetup command-line tool. See “Built-in Command-Line Tools” on page 147 for more detailed information about the systemsetup tool. To change the Energy Saver preferences: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to set the energy saver preferences. a Select any one of the following Energy Saver items from the System Setup group:  Restart After Freeze  Restart After Power Failure  System Sleep Time  Display Sleep Time  Wake On Network Access  Wake On Modem Activity b Change the template values to the desired values, and click Send. 5 Alternatively, manually enter the UNIX command.Chapter 8 Administering Client Computers 133 a Type or paste the following UNIX command: systemsetup -setsleep minutes number_of_minutes_to_sleep -setwakeonmodem (on | off) -setwakeonnetworkaccess (on | off) -setrestartpowerfailure (on | off) -setrestartfreeze (on | off) b Set the permissions for this command to root. 6 Click Send. Changing Sharing Preferences for Remote Login Mac OS X’s Sharing System Preference pane allows you to enable or disable SSH login access to the computer. You can use Remote Desktop to change enable or disable a remote computer’s preference. Setting the remote login sharing preference requires the use of Apple Remote Desktop’s built-in command-line tool, systemsetup. See “Built-in Command-Line Tools” on page 147 for more detailed information about the tool. To change the Remote Login sharing preference: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to set the Remote Login (SSH) setting (see “Send UNIX Command Templates” on page 143 for more information). a Select System Setup > Remote Login (SSH) from the Template pop-up menu. b Set the login for on or off. 5 Alternatively, manually enter the UNIX command. a Type or paste the following UNIX command: systemsetup -setremotelogin (on | off) b Set the permissions for this command to root. 6 Click Send. Setting Printer Preferences You can set the default printer for your client computers so that they all have the same default and configured printer. There are several ways to set up printer preferences for a client computer. If you have a computer whose printer setup is correct, you can use Remote Desktop to copy the necessary configuration files to the client computers. If you don’t have a configured computer available, you can use the command-line tools in Mac OS X to set the printer preference. Setting the printer preference via Remote Desktop involves using the Copy Items task. See “Copying from Administrator to Clients” on page 108 for more information.134 Chapter 8 Administering Client Computers To set up printer preferences using Copy Items: 1 Set up a client computer’s print preference using the Printer Setup Utility. 2 Use the Copy Items task to copy the following file and folder to all the target computers: /private/etc/cups/printers.conf /private/etc/cups/ppd/ Because these files are hidden in the Finder, you may have to use the Terminal or the Finder’s “Go to Folder” command to add them to the “Items to copy” list. 3 Choose a “Same relative location” as the copy destination. 4 Choose to replace existing items. 5 Click Copy. 6 Restart the client computers’ printer process by restarting the clients. If you are comfortable with the command-line, you can use Remote Desktop’s Send UNIX Command to configure all the client computer preferences at once. Setting printer preferences using Send UNIX Command requires the use of the built-in lpadmin command-line tool. For more information, see the lpadmin man page. To set up printer preferences using Send UNIX Command: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type or paste the following UNIX command: lpadmin -p printer_name -E -v lpd://printer_and_queue_address -m printer_model_ppd_file -L “text_description_of_printer_location” 5 Set the user permissions for this command to “root.” 6 Click Send.Chapter 8 Administering Client Computers 135 Managing Computers Using Apple Remote Desktop, you can control multiple client computers simultaneously, issuing commands that are found in Mac OS X’s Apple menu (Log Out, Sleep, Restart, etc.), as well as other commands. Opening Files and Folders Apple Remote Desktop can open existing items (files, folders, and applications) on client computers. The item to open must be on the administrator computer, in addition to being on the client computers, and must have the same name, type, size, permissions, and file creation date as the item on the administrator computer. The Open Items command opens files in the application used to create them, if it exists on the client computer, or in the application assigned to open files with that file’s extension. Folders open in the Finder. Applications are opened, or brought to the front, if already open.136 Chapter 8 Administering Client Computers To open an item: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Open Items. 4 Click the Add (+) button and browse for the item on the administrator computer. Alternatively, drag the item from the administrator computer’s Finder to the Open Items dialog. 5 Click Open when the item is selected. The Open Items dialog shows the icon and name of the item to open. 6 Click Open. Opening Applications Apple Remote Desktop can open applications on client computers. The application to open must be on the administrator computer, in addition to being on client computers. If the application is already open, the Open Application command brings it to the front. You can open both Mac OS X and Classic applications with this command. The application on the administrator computer must have the same name, type, and permissions as the one to be opened on the client computer. To open an application: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Open Application. The Open Application dialog shows the applications installed and found in the Applications folder at the top level of the hard disk of the administrator’s computer. 4 Select the application or click the Add (+) button and browse to find the desired application on the administrator computer. Alternatively, drag the item from the administrator computer’s Finder to the Open Application dialog. The Open Application dialog shows the icon and name of the application to open. 5 Click Open.Chapter 8 Administering Client Computers 137 Quitting Applications Without Logging Out the User Apple Remote Desktop can quit running applications on client computers. You can quit both Mac OS X and Classic applications with this command. The administrator must be able to use the Send UNIX Command on the client computer. You can get more information on the killall command by seeing its man page. Note: Unsaved changes to documents on the client will be lost. To quit an open application: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Use the provided Templates for Send UNIX Command to quit an application (see “Send UNIX Command Templates” on page 143 for more information). a Select Miscellaneous > Quit Application from the Template pop-up menu. b Fill in the desired Application Name. 5 Alternatively, manually enter the UNIX command. a Type or paste the following UNIX command: killall “application_name” b Set the user permissions for this command to be sent as the user “root.” 6 Click Send. Putting a Computer to Sleep Apple Remote Desktop can put client computers to sleep. This has the same result as choosing the Sleep command on the client: the display sleeps, the hard disks spin down, and the computer’s central processor and network interface are put in a lowpower mode. Note: Although you can put computers to sleep which are on other network subnets besides your own, and via AirPort, you will not be able to wake them using Remote Desktop. To put a computer to sleep: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Sleep. 4 Click Sleep.138 Chapter 8 Administering Client Computers Waking Up a Computer Apple Remote Desktop can wake up computers that have gone to sleep or been put to sleep with Remote Desktop. To wake a computer using Remote Desktop, the computer’s networking hardware must support waking via network packet (wakeonlan), and the computer must have “Wake For Ethernet Network Administrator Access” enabled in the Wake Options of Energy Saver preferences. You cannot wake up computers connected to the network via AirPort or computers not located on your local subnet. Apple Remote Desktop uses a “wakeonlan” packet to wake sleeping client computers. The packet can only be delivered by way of a local broadcast address, so it only works on a local area network. Also, the network hardware still needs to be powered to receive and act on the packet. AirPort and other wireless network interfaces completely power down on sleep and therefore can’t receive or act on a wakeonlan packet. If you must wake computers on a different subnet, you may want to use a computer on that subnet as a type of sentry. It never sleeps, and runs another licensed copy of Remote Desktop, as well as allows itself to be controlled by your local copy of Remote Desktop. That way you can control the “sentry” computer and instruct it to wake client computers on its local subnet. To wake a computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers from the list that show a status as “Sleeping” or offline. 3 Choose Manage > Wake. 4 Click Wake. Locking a Computer Screen Apple Remote Desktop can lock a computer screen. When you lock a computer screen, no one can see the desktop or use the mouse and keyboard on that computer. By default, Apple Remote Desktop displays a picture of a padlock on locked screens, but you can display a custom picture. See “Displaying a Custom Picture on a Locked Screen” on page 139 for more information. You can continue to work with computers using Remote Desktop after you’ve locked their screens.Chapter 8 Administering Client Computers 139 To lock a computer screen: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Interact > Lock Screen. 4 Enter a message to be displayed on the locked screen, if desired. 5 Click Lock Screen. The client screen goes black, except for the administrator’s name, the default picture, and any message text. Displaying a Custom Picture on a Locked Screen You can display a picture of your choice on the client screen while it is locked by Apple Remote Desktop. When creating images, make sure the image size will fit on the client computer’s screen. For example, if you have clients with 800 x 600 screens, a picture that is 1024 x 768 will be scaled down to fit the screen. To create a custom locked screen picture: 1 Create a picture using a graphics program, such as AppleWorks. 2 Save the picture in PICT, TIFF, GIF, JPEG, or any other QuickTime-compatible static image format. QuickTime-compatible movies or QuickTime VR objects cannot be used. 3 Name the picture “Lock Screen Picture”. 4 Copy the “Lock Screen Picture” file to /Library/Preferences/ on the client computer. Unlocking a Computer Screen You must use Apple Remote Desktop to unlock any computer screen locked by Remote Desktop. When you unlock a computer screen, you restore the desktop and use of the mouse and keyboard on that computer. To unlock a computer screen: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers from the list that show a “Locked Screen” status. 3 Choose Interact > Unlock Screen. 4 Click Unlock Screen.140 Chapter 8 Administering Client Computers Disabling a Computer Screen Sometimes you may want to control a client computer with a user at the client computer, but you don’t want the user to see what you’re doing. In such a case, you can disable the client computers screen while preserving your own view of the client computer. This is a special control mode referred to as “curtain mode.” You can change what’s “behind the curtain” and reveal it when the mode is toggled back to the standard control mode. This feature only works with Mac OS X v.10.4 clients. To disable a computer screen while you work: 1 Control a client computer. See “Controlling Apple Remote Desktop Clients” on page 78 or “Controlling VNC Servers” on page 82 for detailed information. 2 Click the Lock Computer Screen While You Control button in the control window toolbar. Alternatively, if you are not currently in a Control window and have added the “Control Computer in Curtain Mode” button to your toolbar, click that toolbar icon. You can also select Interact > Curtain. Logging In a User at the Login Window Apple Remote Desktop can log in any user on a client computer by using AppleScript System Events and the Send UNIX Command feature. Using these powerful features you can log in any number of client computers to the same user name simultaneously from the login window. This script is for use on computers at the login screen only. To log in a user: This method uses the osascript command. For detailed information on osascript, see the osascript man page. 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type the following AppleScript in the UNIX Command window, adding the user name and password: osascript <" keystroke tab delay 0.5 keystroke "" delay 0.5 Chapter 8 Administering Client Computers 141 keystroke return end tell EndOfMyScript 5 Choose user “root” to run the command. 6 Click Send. The client computer executes the script. Logging Out the Current User Apple Remote Desktop can log out the current user on a client computer. Other users, besides the current active user, who are logged in using Fast User Switching are not logged out using this command. Using this command returns the client computer to the login window. Unsaved work will stop the logout process. To log out a user: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Log Out Current User. 4 Click Log Out. Restarting a Computer Apple Remote Desktop can restart a client computer. This has the same result as choosing the Restart command from the client computer’s Apple menu. This feature is especially useful when used with the Install Packages command. Install Packages doesn’t restart the computer, even if the package requires it. You can restart the computer using Remote Desktop after installing a package. To restart a computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Restart. 4 Select the type of restart. You can allow users to save files or cancel the restart, or you can force an immediate restart, which will cause the users to lose unsaved changes to any open files. 5 Click Restart.142 Chapter 8 Administering Client Computers Shutting Down a Computer Apple Remote Desktop can shut down a client computer. This has the same result as choosing the Shut Down command from the client computer’s Apple menu. Note: If you shut down an Apple Remote Desktop client, you cannot start it up using Remote Desktop. This command is especially useful when used with Energy Saver preferences. You can set your client computers to start up every morning at a designated time and use Remote Desktop to shut them down at night. The next morning, they will start up and be ready to administer. To shut down a computer: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Shut Down. 4 Select the type of shutdown. You can choose to allow users to save files or cancel the shutdown, or you can force an immediate shutdown, which will cause the users to lose unsaved changes to any open files. 5 Click Shut Down.Chapter 8 Administering Client Computers 143 UNIX Shell Commands In addition to its own tasks, Apple Remote Desktop provides a way to easily execute UNIX commands on client computers. In order to send UNIX commands to the client computers, the client computers must have the BSD subsystem installed. The UNIX commands are shell command, which means you can write a script with conditionals, loops, and other functions of the shell, and not just send a single command. Send UNIX Command Templates Remote Desktop has a few built-in UNIX shell command templates for use with Send UNIX Command. In the Send UNIX Command task configuration dialog, you can select any one of the commands from the Templates pop-up menu. Selecting a template pastes a generic script into the UNIX command field. All you have to do is customize the script to your situation. For example, if you want to set a manual IP address for a client computer, you would select the Manual IP template from the Template > Network Setup pop-up menu, replace the placeholder indicated in the pasted-in UNIX command with the real IP address, and send the command. You are free to make as many templates as your want from either existing templates or from scratch. Once saved, a template can be made the task’s default, with all new instances of the task opening with the default template settings.144 Chapter 8 Administering Client Computers For more information about Task Templates, see “Creating and Using Task Templates” on page 100. The built-in Send UNIX Command templates include: Template sub-menu Template name Network Setup  List All Services  Manual IP  DHCP  BOOTP  Manual with DHCP Router  DNS Servers  Search Domains  Web Proxy System Setup  Allow Power Button To Sleep  Bonjour Name  Current Date  Current Time  Time Zone  Network Time  Network Time Server  Remote Apple Events  Remote Login (SSH)  Restart After Freeze  Restart After Power Failure  System Sleep Time  Display Sleep Time  Hard Disk Sleep Time  Delay After Power Failure  Wake On Modem Activity  Wake On Network Access Miscellaneous  Login User  Quit Application  Volume Off  Volume On  List Required Software Updates  Install Required Software Updates  Repair Disk Permissions  Computer Uptime  Free Swap Space  Top UsersChapter 8 Administering Client Computers 145 Executing a Single UNIX Command Using the UNIX Command window, you can send a single command to the selected client computers. The command is executed using the bash shell. To execute a single UNIX command: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type or paste the command. If your command is a multi-line script, enter each command on its own line. If you want to break up a single-line command for better readability, use a backslash (\) to begin a new line. 5 Set the permissions used to execute the command. You can choose the currently logged-in user, or choose the name of another user on the client computers. 6 Click Send. Executing Scripts Using Send UNIX Command There are two kinds of scripts you can execute via the command line. First, and most common with command lines, is a shell script. A shell script is a file containing a collection of UNIX commands that are all executed in sequence. Shell scripts can have normal programming procedures like loops, conditionals, and variables. Shell scripts are text files with UNIX line endings. Shell scripts are interpreted using the bash shell. The second kind of script you can execute, and the most common in the Mac OS X environment, is an AppleScript. AppleScripts are files that contain English-like commands, using the AppleScript programming language and they are created using the Script Editor application. Running a UNIX command as the current user will fail if the target computer is at the login window, since there is no current user at that point. You can use root user for tasks by entering root in the specified user field of the task dialog. You don’t actually need to have the root account enabled on the client computer to specify the root user. You should never use sudo or su to do tasks as the root user. They are interactive and expect further input and response from your script. Instead, run your script as root or whatever user you were planning on. Executing Shell Scripts with Remote Desktop Shell scripts can be copied, then executed. If a script has any degree of complexity, or if it cannot be expressed on a single line, you can use Copy Items to copy the script file to the client computers, then execute it using Send UNIX Command. To send a single-line command you can simply use Send UNIX Command.146 Chapter 8 Administering Client Computers To copy and execute a script: 1 Prepare and save your script. Make sure your script is saved as plain text with UNIX line breaks. 2 Open Remote Desktop. 3 Select a computer list in the Remote Desktop window. 4 Select one or more computers in the selected computer list. 5 Use the Copy Items command to copy your script to the client computers. See “Copy Options” on page 107 and “Copying from Administrator to Clients” on page 108 for more information. 6 After copying the script, choose Manage > Send UNIX Command. 7 Execute the script by typing: sh script pathname 8 Click Send. Executing AppleScripts with Remote Desktop AppleScripts can be executed on client computers in two ways. They can be saved and executed as an application, or sent at once using the command line. To learn more about AppleScript, see AppleScript Help in Help Viewer or go to: www.apple.com/applescript/. To send and execute an AppleScript: 1 Save the AppleScript as an application. 2 Open Remote Desktop. 3 Select a computer list in the Remote Desktop window. 4 Select one or more computers in the selected computer list. 5 Use the Copy Items command with the Open Items option selected in the Copy Items dialog. See “Copy Options” on page 107 for more information. To execute an AppleScript using the Send UNIX Command: This method uses the osascript command. See the osascript man page for more information. 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose Manage > Send UNIX Command. 4 Type or paste the AppleScript in the UNIX Command window, like this: osascript -e 'First line of script' -e 'Next line of script' [ -e ... ]Chapter 8 Administering Client Computers 147 Alternatively, you could use a UNIX “read standard input” redirection which looks like: osascript < value must be a multiple of 30 seconds. Example: systemsetup - setWaitForStartupAfterPowerFailure 30 -setwakeonmodem ( on | off ) Use this command to specify whether or not the server will wake from sleep when modem activity is detected. Example: systemsetup -setwakeonmodem on -setwakeonnetworkaccess ( on | off ) Use this command to specify whether the server wakes from sleep when a network admin packet is sent to it. Example: systemsetup -setwakeonnetworkaccess on Flag DescriptionChapter 8 Administering Client Computers 151 Any command in the Mac OS X Server command-line guide that uses systemsetup can be used in Remote Desktop using the Send UNIX Command task. Using kickstart The kickstart command-line utility is embedded within the Apple Remote Desktop client software. It allows you to install, uninstall, activate, configure, and restart components of Apple Remote Desktop without restarting the computer. You can configure all the features found in the Remote Desktop section of the Sharing System Preferences. The kickstart utility can be used via SSH to configure remote computers, including Xserves. The kickstart utility is located at: /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/ Resources/kickstart. The syntax and list of actions possible with kickstart are available by running kickstart as follows: $sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/ Resources/kickstart -help If you are running the kickstart utility through Apple Remote Desktop’sSend UNIX Command function, you don’t need the full path, just the name kickstart and root as the command’s user. You can use the sudo command with an administrator account to use the kickstart utility, or you can use the root user via Send UNIX Command. All commands presented in this section should be typed as one line of text. It’s OK if the text wraps as you enter it; just be sure not to enter return characters. The following are some examples of actions possible with kickstart:  Activate Remote Desktop sharing, enable access privileges for all users, and restart the Apple Remote Desktop Agent: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -activate -configure -access -on -restart -agent -privs -all  Activate Remote Desktop sharing, enable access privileges for the users “admin”, grant full privileges for the users “admin,” and restart the Apple Remote Desktop Agent and Menu item: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -activate -configure -access -on -users admin -privs -all -restart -agent -menu  Activate Remote Desktop sharing, and disable access privileges for all users: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -activate -configure -access -off  Shut down the Apple Remote Desktop Agent process: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -agent -stop152 Chapter 8 Administering Client Computers  Deactivate Remote Desktop access for a computer: $ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/ Contents/Resources/kickstart -deactivate -configure -access -off Automating Functions You can automate any command or function in Remote Desktop. Additionally, Remote Desktop supports scripting (either UNIX or AppleScript) to help automate their client management. Setting the Client’s Data Reporting Policy To speed up reporting and allow reporting from offline clients, Apple Remote Desktop uses saved client system and file information. You can automate the collection of this information by setting the data reporting policy. This schedule determines how often the client updates its system and file information for reports. In accordance with the collection schedule you set, each client computer connects to a central reporting database and uploads the information you designate. There are certain trade-offs to the frequency of these updates. If you require all the clients to update their information too often, you run the risk of added network traffic and slower client performance during updates. If you don’t require the clients to update often enough, the report data that you receive may be out of date. You should take care to balance your reporting needs and your network and client performance needs. The collection policy includes four kinds of information: system data, file data, user accounting data, and application usage data. System data includes all possible reported information for the following reports:  System Overview  Storage  USB Devices  FireWire Devices  Memory  PCI Cards  Network Interfaces The file data includes all possible reported information for the following reports:  File Search  Software Version  Software DifferenceChapter 8 Administering Client Computers 153 The user accounting data includes all possible reported information for the following report:  User History The application usage data includes all possible reported information for the following report:  Application Usage To set a client’s data reporting policy: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose File > Get Info. 4 If you have selected only one computer, select the Data Settings tab, and click the Edit button. If you have selected more than one computer, this tab is already selected. 5 Select “Upload on a schedule.” To disable a client’s automatic data collection, deselect “Upload on a schedule.” 6 If you have already made a default schedule, you can use it by clicking “Use default schedule” to automatically fill in the appropriate information and click Done. Otherwise, choose the day or days the data collection should occur. For more information about setting a default schedule, see “Creating a Template Data Reporting Policy” on page 153. 7 Set the time at which the collection occurs. 8 Choose which data types to upload: System Data, File Search Data, Application Usage Data or User Accounting Data, or any combination. 9 In order to upload Application Usage Data and User Accounting Data, you need to specify collection of that data. Choose Collect Application Usage Data to tell a client computer to save report information for the Application Usage Report. Choose User Accounting Data to tell a client computer to save report information for the User History Report. 10 Click Apply. Creating a Template Data Reporting Policy To speed up client configuration for data reporting, you can set a default time and frequency of report data collection. This template must be applied to any computer or group of computers that you want to use it. Afterwards, the setting can be customized on a per-computer or group basis.154 Chapter 8 Administering Client Computers To set the default data reporting policy template: 1 Choose Remote Desktop > Preferences. 2 Select Task Server. 3 Check which additional data types the clients will collect: Application Usage Data, User Accounting Data, or both. 4 Check “Upload report data to the Task Server on a schedule.” 5 Click Change Schedule. 6 Choose the day or days the data collection should occur. 7 Set the time at which the collection should occur. 8 Choose which data types to upload: “System Data,” “File Search Data,” “Application Usage Data,” “User Accounting Data,” or any combination. 9 Click OK. Designating the Task Server and Setting the Report Data Collection Location To speed up reporting, Apple Remote Desktop uses a database of client system and file information. You can automate the collection of this data for reports, and determine where the database will reside. By default, the database is stored on the administrator computer. Use these instructions to change the data collection location. First, determine where the data will be located: on the administrator computer, or a remote computer (called a Task Server). A Task Server needs to be an unlimited-client licensed Apple Remote Desktop administrator computer and have TCP and UDP ports 3283 open to all of the reporting client computers (and TCP port 5900 open, if you want to control the clients). If you choose to use another Apple Remote Desktop administrator computer’s database, you must configure it to allow data access to other Apple Remote Desktop administrators. The default Task Server is the computer upon which you installed Remote Desktop. See also “Using a Task Server for Report Data Collection” on page 112. If you choose to store the data locally and you have an unlimited client license, you can allow other Apple Remote Desktop administrators with unlimited-managed computer licenses to access the database on your computer by selecting the “Allow remote connections to this server” option. Warning: If you change the location of the report database from the one selected in the initial setup, you will need to reset the collection policies for the client computers. The database will not be moved, but will be regenerated at the next collection interval.Chapter 8 Administering Client Computers 155 To set the Task Server location: 1 Open Remote Desktop. 2 Choose Remote Desktop > Preferences. 3 Click Task Server. 4 If you want to use the database on this administrator computer, select “Use Task Server on this computer.” 5 If you use your Remote Desktop administration computer as a Task Server on the local administrator computer, click “Allow remote connections to this server.” 6 If you want to use a database on another administrator computer, select “Use remote Task Server.” Then, enter the IP address or fully qualified domain name of the other Apple Remote Desktop administrator computer, and click Select. 7 Close the window to save changes. Scheduled Tasks You can use Apple Remote Desktop to automate and schedule almost any task. For example, you can make sure a particular application or a specific set of fonts is always available on a client computer by setting Remote Desktop to copy applications and fonts to the client every night. When you schedule an automated task, information about the scheduled task is saved on the administrator computer. At the appointed time, the client software on that computer activates and initiates the task. Remote Desktop must be open to perform a scheduled task. Setting Scheduled Tasks Any task with the Schedule Task button in the task configuration window can be scheduled. Tasks that you have scheduled appear on the left in the main Remote Desktop window. To schedule a task: 1 Select a computer list in the Remote Desktop window. 2 Select one or more computers in the selected computer list. 3 Choose the task you want to schedule from the menu bar. 4 Configure the task as needed. 5 Before executing the task, click the Schedule button. The scheduling information is revealed. 6 Choose when and how often you want the task to execute. 7 If you want the task to repeat, click Repeating Every then set the repeat interval.156 Chapter 8 Administering Client Computers 8 Click OK. 9 Save the task and choose where the task will appear in the Remote Desktop window. Editing Scheduled Tasks Once saved, a task can be changed and all future executions of the task will reflect the changes. You may want to edit which computers are affected by the task or any other task parameter. To edit a task schedule: 1 Double-click a scheduled task in the Remote Desktop window. 2 Edit the task, as needed. 3 Click the Schedule Task button. 4 Edit the task schedule, as needed. 5 Click OK. 6 Click Save. Deleting Scheduled Tasks Unneeded tasks can be deleted. If you want to keep the task, but stop it from repeating, you should edit the scheduled task instead of deleting it. See “Editing Scheduled Tasks” for more information. To delete a scheduled task: 1 Select the saved task in the Remote Desktop window. 2 Press the Delete key. 3 Click Delete. Using AppleScript with Remote Desktop AppleScript is a powerful and versatile scripting language that is built into Mac OS X. You can use AppleScript to create shortcuts, automate repetitive tasks, or even make custom applications that save you a great amount of time. AppleScript is an Englishlike language you can use to write scripts that contain commands. Scripts can make decisions based on user interaction, or by parsing and analyzing data, documents, or situations. Remote Desktop is scriptable, as are many other Mac OS X applications, and it can be controlled with AppleScript commands. AppleScript is a complete language with conditional statements, comparison and arithmetic operations, and the ability to store variables. This documentation doesn’t teach AppleScript language syntax or programming practices. For information about learning how to program with AppleScript, see the AppleScript online help. This section provides a brief description of AppleScript, a brief discussion of using the Remote Desktop AppleScript Dictionary, and a sample script.Chapter 8 Administering Client Computers 157 Remote Desktop’s AppleScript Basics AppleScript scripts consist of commands that are sent to objects. Objects can be a wide variety of things, including applications, scripts, windows, settings, or the Finder. These objects can receive a specific set of commands and respond with the desired actions. Essentially, a script tells an application (Remote Desktop in this case) to either complete a certain task or retrieve information. You can give the script decision-making capabilities by using conditional statements; you can give the script a memory by defining variables. Remote Desktop has made all of its fundamental functions scriptable. The tasks that you perform as an administrator by pointing and clicking the mouse can all be accomplished by running an AppleScript. For example, you can:  Get information on or rename a computer  Add computers to a list  Copy or install items  Execute a report task Using the Remote Desktop AppleScript Dictionary Each scriptable application contains an AppleScript dictionary—the list of objects and messages that an application can understand. For example, in Remote Desktop’s dictionary there is an object named “computer list” that has this entry: A “computer list” is an object which contains other objects (“computers” in this case) and has properties like its “id” and its “name.” When queried, this object can return the values for the properties (in Unicode text as indicated), but you can’t change “id” from within the script (it’s labeled r/o for read-only). This object can be acted upon by the “verbs,” or messages, in a script. The dictionary also contains “verbs,” or messages. These verbs are commands that act on the objects in the dictionary. For example, in Remote Desktop’s dictionary there is a verb named “add,” and this is its entry: computer list n [inh. item] : A list which holds computers. ELEMENTS contains computers; contained by application. PROPERTIES id (Unicode text, r/o) : The unique identifier (UUID) of the computer list. name (Unicode text) : The name of the computer list. add v : Add a computer to a task. add computer : The computer. to computer list : The computer list (or task) to add the computer to.158 Chapter 8 Administering Client Computers This entry tells you what the verb can act on and how. This entry says that Remote Desktop can add a specified computer to a computer list. The objects “computer” and “computer list” are being acted upon by “add.” To access the full AppleScript dictionary for Remote Desktop: 1 Launch Script Editor in the /Applications/AppleScript/ folder. 2 Select File > Open Dictionary. 3 Choose Remote Desktop. 4 Click Open. The AppleScript Dictionary for Remote Desktop is also available in Appendix C, “AppleScript Remote Desktop Suite.” Sample AppleScript This AppleScript is one that could be used to do a quick cleanup of a group of computers. First, it locks the computer screens to prevent interference. Second, it deletes all items left on the currently active desktops of the client computers. Finally, it finishes by emptying the clients’ trash and unlocking the screens. This script is for educational use only and no warranty is explicit or implied as to the suitability of this script for your computing environment. Additionally, this sample script deletes items on the target computers. Use at your own risk. -- Start commanding the local copy of Remote Desktop tell application "Remote Desktop" -- decide which list to perform this on, in this case it's called "Classroom" set these_computers to computer list "Classroom" -- decide what locked screen text you want displayed set screen_message to "Please wait" as Unicode text -- make a UNIX script which executes an AppleScript on the remote computers set the UNIX_script to "osascript -e 'tell application \"Finder\" to delete every item of the desktop whose class is not disk'" -- set the lock task parameters set lock_task to make new lock screen task with properties {name:”Lock Classroom”, message:screen_message} -- perform the task execute lock_task on these_computers -- set the UNIX script parameters set clean_task to make new send unix command task with properties {name:”Clean Desktop”, showing output:false, script:UNIX_script}Chapter 8 Administering Client Computers 159 -- perform the task execute clean_task on these_computers -- empty the trash afterward execute (make new empty trash task) on these_computers -- unlock the screen when finished execute (make new unlock screen task) on these_computers end tell Using Automator with Remote Desktop Accomplish all of your time-consuming, repetitive manual tasks quickly, efficiently, and effortlessly with Automator workflows. It’s simple to create custom workflows just by dragging items, pointing, and clicking. You can easily automate Remote Desktop tasks such as Lock Screen or Install Packages, then repeat those tasks again and again. Simple and easy-to-understand application actions are the building blocks, so you don’t have to write any code. Each actions has all of the options and settings available to you. Here’s the sample AppleScript above, but done using Automator:160 Chapter 8 Administering Client Computers Using Automator actions, you can even create your own interfaces to Apple Remote Desktop functions without having to give users access to Remote Desktop. For instance, say you wanted to give all your teachers a tool to lock and unlock screens in their classrooms. You still need to configure Remote Desktop and set up computer lists, but instead of giving the teachers all access to Remote Desktop, you can create an Automator plug-in or application. This plug-in lets them select only the computers in their classroom, and the plug-in does the rest of the work for them. You can create an Automator workflow, application, Finder plug-in, or iCal alarm similar to the AppleScript mentioned above. By stringing together Remote Desktop actions in Automator, you accomplish the same work as an AppleScript, but without having to write code. 161 A Appendix A Icon and Port Reference The following tables illustrate some of the icons found in the main window of Remote Desktop. The final table shows which network port numbers are in use by Apple Remote Desktop. Client Status Icons The following icons appear next to the names of computers in a scanner search results list. The icons show the status of each computer in the list. Apple Remote Desktop Status Icons The Apple Remote Desktop status icon appears in the menu bar of each Apple Remote Desktop client. The status icon has several states, depending on the status of the client computer. Icon What it means Accessible to Apple Remote Desktop Offline Apple Remote Desktop client Ping response at IP address, but no Apple Remote Desktop client response Icon What it means Not Active Apple Remote Desktop is installed but is not currently running on the client computer. Ready Apple Remote Desktop is installed and running on the client. Administered Apple Remote Desktop is installed and running on the client computer, the administrator is actively observing or controlling, and the client is set to indicate when it is being observed.162 Appendix A Icon and Port Reference List Menu Icons The following icons are used in the Apple Remote Desktop list area of Remote Desktop’s main window. Task Status Icons The following icons are used in task list areas of Remote Desktop’s main window. Icon What it means Master list Apple Remote Desktop list Smart list Scanner Active Task list Task History list Task Server queue Icon What it means Running Finished successfully Exited with error Incomplete Queued ScheduledAppendix A Icon and Port Reference 163 System Status Icons (Basic) The following icons are shown as initial high-level status indicators for observed client computers. System Status Icons (Detailed) The following icons are shown after further inspection of observed client computer status indicators. Icon Indicates or One or more service statistic is red. This takes precedence over any yellow or green indicator. or One or more service statistic is yellow This takes precedence over any green indicator Service is operating within established parameters. No service informaiton available. Service Icon Status CPU Usage Usage is at 60% or less Usage is between 60% to 85% Usage is at 85% or higher No status information is available DIsk Usage Usage is at 90% or less Usage is between 90% and 95% Usage is at 95% or higher No status information is available Free Memory Less than 80% used Between 80% and 95% used164 Appendix A Icon and Port Reference TCP and UDP Port Reference Apple Remote Desktop uses the following TCP and UDP ports for the functions indicated. Over 95% used No status information is available Service Icon Status Port Protocol Function 5900 TCP Observe and Control 5900 UDP Send screen, share screen 3283 TCP Reporting 3283 UDP Everything else 22 TCP Encrypted file transfer, observe, and control (via SSH tunnel) 165 B Appendix B Report Field Definitions Reference The following sections describe the available fields in some of the Apple Remote Desktop reports. For information on generating reports, see “Creating Reports” on page 111. The file search reports (File Search, Software Version, and Software Difference) are not included because their fields closely match those already found in the Finder. System Overview Report List category Field name Notes or example AirPort AirPort Active Yes/No AirPort Firmware Version Version number AirPort Hardware Address 00:30:65:01:79:EC AirPort Locale AirPort Type AirPort Installed Yes/No AirPort Network Channel Channel number 1-11 AirPort Network Name Network name AppleTalk AppleTalk Active Yes/No AppleTalk Network AppleTalk Node AppleTalk Zone Computer Active Processors Number of processors Available user memory Memory in KB Boot ROM ROM version number Bus Clock Speed In MHz Bus Data Size CPU Speed In MHz Serial number 166 Appendix B Report Field Definitions Reference Velocity Engine Yes/No L2 Cache Size In KB L3 Cache Size In KB Machine Model Memory In KB Empty RAM Slots PCI slots Used Processor Count CPU Type Internal value Sales Order Number VM Size Total RAM Slots Devices ATA Device Count Firewire Device Count Keyboard Connected Mouse Connected Optical Drive Type SCSI Device Count USB Device Count Display 2nd Monitor Depth In bits 2nd Monitor Type 2nd Monitor Resolution Pixels horizontal and vertical Monitor Depth In bits Monitor Type Monitor Resolution Pixels horizontal and vertical Modem Modem Country Modem Driver Modem Firmware Version Modem Installed Yes/No Modem Interface Modem Model Network First Ethernet Address en0 MAC address NetBooted Yes/No Primary IP Address Primary Network Collisions Primary Network Flags List category Field name Notes or exampleAppendix B Report Field Definitions Reference 167 Primary Network Hardware Address Primary Network Input Errors Primary Network Input Packets Primary Network Output Errors Primary Network Output Packets Primary Network Preferences Sleep Display Yes/No Sleep Hard Disk Yes/No Sleep Computer Yes/No Wake for Ethernet Access Yes/No Printing Printer Name Printer Sharing Yes/No Printer Type Printer Version Remote Desktop Computer Info #1 Computer Info #2 Computer Info #3 Computer Info #4 Sharing Computer Name File sharing name, “Bob’s Computer” FTP Access Yes/No Remote AppleEvents Yes/No Remote Login Yes/No UNIX hostname foo.example.com Web Sharing Yes/No Windows Sharing Yes/No Software Kernel Version System Version Mac OS X v10.4.2 (8C46) Storage Free Disk Space In KB, MB, or GB Total Disk Space In KB, MB, or GB Trash Size In KB, MB, or GB List category Field name Notes or example168 Appendix B Report Field Definitions Reference Storage Report List category Field name Notes or example Hardware Options Drive Manufacturer Drive Model Drive Revision Drive Protocol Removable Yes/No Serial Number Logical Unit Number Detachable Volume Options Creation date UNIX GMT format Disk Name Macintosh HD File Count Folder Count Total Disk Space Free Space In KB, MB, or GB Startup Disk UNIX Mount Point /dev/disk0s10 File System Options Disk Format HFS, HFS+, UFS Owner Group Yes/No Permission Modes Permissions Yes/No Write Access Modification date UNIX GMT format Case Sensitive Yes/No Preserves Case Yes/No Backup Options Journaling Capable Yes/No Journaled Yes/No Last Backup date UNIX GMT format Last Check date UNIX GMT formatAppendix B Report Field Definitions Reference 169 USB Devices Report FireWire Devices Report Memory Report PCI Cards Report Field name Notes or example Product Name Product ID Vendor ID Vendor Name Device Speed 1.5Mb, 12Mb Bus Power In mA Date collected Field name Notes or example Device Speed 200, 400, 800 Mbits per second Software Version Manufacturer Model Firmware Revision Date collected Field name Notes or example Slot Identifier DIMM0/J21 Size In MB Speed PC133-222 (Mac OS X 10.3 only) Type SDRAM Date collected Field name Notes or example Card Name Slot Name Slot4 Card Type Display Vendor ID Device ID170 Appendix B Report Field Definitions Reference Network Interfaces Report ROM Revision Displays only Card Revision Card Memory Displays only Date collected Field name Notes or example List category Field name Notes or example Network Overview Name Location name Active Yes/No Primary Yes/No Configured With Ethernet Hardware Address 00:30:65:01:79:EC Interface Name en0 Flags Active Interface Domain example.com Router Address IP Address Broadcast Address DNS Server Subnet Mask IP Addresses Broadcast Addresses DNS Servers Subnet Masks Network Statistics Network Collisions Network Input Errors Network Input Packets Network Output Errors Network Output Packets Output Statistics Output Queue Capacity Output Queue Size Output Queue Peak Size Output Queue Drop Count Output Queue Output Count Output Queue Retry CountAppendix B Report Field Definitions Reference 171 Output Queue Stall Count Ethernet Statistics Ethernet Alignment Errors Ethernet FCS Errors Frame Check Sequence errors Ethernet Single Collision Frames Ethernet Multiple Collision Frames Ethernet SQE Test Errors “heartbeat” test errors Ethernet Deferred Transmissions Ethernet Late Collisions Ethernet Excessive Collisions Ethernet Internal MACTransmit Errors Ethernet Carrier Sense Errors Ethernet Frame Too Long Ethernet Internal Mac Receive Errors Ethernet Chip Set Ethernet Missed Frames Ethernet Receiver Overruns Ethernet Receiver Watchdog Timeouts Ethernet Receiver Frame Too Short Ethernet Receiver Collision Errors Ethernet Receiver PHY Errors Ethernet Receiver Timeouts Ethernet Receiver Interrupts Ethernet Receiver Resets Ethernet Receiver Resource Errors Ethernet Transmitter Underruns Ethernet Transmitter Jabber Events Ethernet Transmitter PHY Errors Physical Errors Ethernet Transmitter Timeouts Ethernet Transmitter Interrupts Ethernet Transmitter Resets List category Field name Notes or example172 Appendix B Report Field Definitions Reference Network Test Report Administration Settings Report Ethernet Transmitter Resource Errors Ethernet Collision Frequencies List category Field name Notes or example Field name Notes or example Computer Computer sharing name Min,. Time Shortest time for ping response Max. TIme Longest time for a ping response Avg. Time Average time for ping response Lost Packets Number of pings without a response Total Packets Number of pings sent. List category Field name Notes or example Computer Computer sharing name Privileges Generate Reports On or off Send Messages On or off Open & Quit On or off Restart & Shutdown On or off Change Settings On or off Copy Items On or off Delete Items On or off Control On or off Observe On or off Show Observe On or off Data Settings Collect Application Usage Data On or off Collect User Accounting Data On or off Upload Schedule Time and days to upload information Upload System Data On or off Upload File Data On or off Upload Application Usage Data On or off Upload User Accounting Data On or offAppendix B Report Field Definitions Reference 173 Application Usage Report User History Report General Version Apple Remote Desktop version and build number Last Contacted Relative date List category Field name Notes or example Field name Notes or example Computer name File sharing computer name Name Application name Launch date 24 hour local time and date Total run time Length of time the application was running Frontmost Length of time the application was the frontmost application User name Short user name of application process owner State What the application is doing now (running, terminated, etc.) Field name Notes or example Computer name file sharing computer name User name Login type) Console, tty, ssh Login time Date and 24 hour format local time Logout time Date 24 hour format local time Remote Login Host Originating host to the login session, localhost, or some remote computer174 C Appendix C AppleScript Remote Desktop Suite This appendix shows the contents of Remote Desktop’s AppleScript Dictionary. This appendix is not a substitute for the AppleScript Dictionary view in Script Editor. It is included as a quick reference so that AppleScript commands might be found by a search of PDF contents. The Dictionary itself has the most recent information about scriptable objects and events in Remote Desktop, and better usability. Classes and Commands for the Remote Desktop Application. add v: Add a computer to a task. add computer: The computer. to computer list: The computer list (or task) to add the computer to. control v: Start a control session with the computer. control computer: The computer to control. execute v: Executes a task. execute task: The task to execute. [on computer list]: The computer list (or computer) on which to run the task. observe v: Start an observation session. observe item: The computer, list, or computer list to observe. release v: Release computers from a control or observation session. release item: The computer, list, or computer list to release. remove v: Remove a computer from a task. remove computer: The computer to remove. from computer list: The computer list (or task) to remove the computer from. stop v: Stops an executing share screen task. stop task: The task to stop.Appendix C AppleScript Remote Desktop Suite 175 application n [inh. application; see also Standard Suite]: Remote Desktop’s top level scripting object. ELEMENTS contains computers, computer lists, copy items tasks, copy to me tasks, documents, empty trash tasks, install package tasks, lock screen tasks, logout tasks, open application tasks, open item tasks, rename computer tasks, restart tasks, send message tasks, send unix command tasks, set local startup disk tasks, set network startup disk tasks, share screen tasks, shutdown tasks, sleep tasks, unlock screen tasks, upgrade client tasks, wake up tasks, windows. PROPERTIES selection (item, r/o): The current selection. computer n [inh. item]: A physical computer. ELEMENTS contained by application, computer lists. PROPERTIES boot volume (Unicode text, r/o): The boot volume of the computer. CPU (Unicode text, r/o): The CPU type of the computer. current application (Unicode text, r/o): The current frontmost application on the computer. current user (Unicode text, r/o): The currently logged in user on the computer. DNS name (Unicode text, r/o): The DNS name of the computer. id (Unicode text, r/o): The unique identifier (UUID) of the computer. Internet address (Unicode text, r/o): The Internet address of the computer. last activity (date, r/o): The time of the most recent activity on the computer. last contacted (date, r/o): The time of last contact with the computer. machine model (Unicode text, r/o): The model of the computer. name (Unicode text, r/o): The name of the computer. physical memory (Unicode text, r/o): The physical ram installed in the computer. primary Ethernet address (Unicode text, r/o): The primary ethernet address of the computer. remote desktop version (Unicode text, r/o): The version of the Remote Desktop client running on the computer. status message (Unicode text, r/o): The current status of the computer. system version (Unicode text, r/o): The Mac OS version running on the computer. computer list n [inh. item]: A list which holds computers. ELEMENTS contains computers; contained by application. PROPERTIES id (Unicode text, r/o): The unique identifier (UUID) of the computer list. name (Unicode text): The name of the computer list.176 Appendix C AppleScript Remote Desktop Suite copy items task n [inh. task > item]: Copy items to the target computers. ELEMENTS contained by application. PROPERTIES bandwidth limit (integer): Network usage limit in kilobytes per second (0 = unlimited). conflict resolution (ask what to do/rename the existing item/rename the item being copied/replace/replace if older): Specifies what to do if the item(s) already exist in this location. copy items (list): A list of files and/or folders to copy. destination group (Unicode text): If ownership is set to a ‘specific owner’, a valid group name on the destination computer. destination owner (Unicode text): If ownership is set to a ‘specific owner’, a valid user name on the destination computer. destination path (alias): If the location is ‘specific folder’, a fully specified path to the destination folder. encrypting (boolean): Should the items be encrypted during copying location (applications folder/current users desktop folder/current users home directory/ same relative location/specific folder/system folder/system fonts folder/system preferences folder/top folder of the boot disk): The target location to copy to. ownership (current console user/current owner/destination folder owner/specific owner): Specifies the new ownership of the copied item(s). should open (boolean): Should the items be opened after being copied stopping on error (boolean): Should the copy terminate if an error occurs during copying copy to me task n [inh. task > item]: Copy items from the target computers to the administrator computer. ELEMENTS contained by application. PROPERTIES bandwidth limit (integer): Network usage limit in kilobytes per second (0 = unlimited). conflict resolution (ask what to do/rename the existing item/rename the item being copied/replace/replace if older): Specifies what to do if the item(s) already exist in this location. copy items (list): A list of files and/or folders to copy. destination path (alias): If the location is ‘specific folder’, a fully specified path to the destination folder. encrypting (boolean): Should the items be encrypted during copying location (applications folder/current users desktop folder/current users home directory/ same relative location/specific folder/system folder/system fonts folder/system preferences folder/top folder of the boot disk): The target location to copy to.Appendix C AppleScript Remote Desktop Suite 177 empty trash task n [inh. task > item]: Empty the trash on the target computers. ELEMENTS contained by application. install package task n [inh. task > item]: Install package(s) on the target computers. ELEMENTS contained by application. PROPERTIES after installing (attempt restart/do nothing/force immediate restart): Specifies what to do after installing the package(s). bandwidth limit (integer): Network usage limit in kilobytes per second (0 = unlimited). delegating to task server (boolean): Should this task be delegated to the task server encrypting (boolean): Should the packages be encrypted during copying packages (list): A list of packages to install. stopping on error (boolean): Should the copy terminate if an error occurs during copying lock screen task n [inh. task > item]: Lock the screen(s) on the target computers. ELEMENTS contained by application. PROPERTIES message (Unicode text): Message to display on the screen(s). logout task n [inh. task > item]: Log out the current user on the target computers. ELEMENTS contained by application. open application task n [inh. task > item]: Launch an application on the target computers. ELEMENTS contained by application. PROPERTIES application (alias): The path to the application to open. open item task n [inh. task > item]: Open files on the target computers. ELEMENTS contained by application. PROPERTIES files (list): A list of files to open. rename computer task n [inh. task > item]: Change the name of the target computers. ELEMENTS contained by application. PROPERTIES178 Appendix C AppleScript Remote Desktop Suite naming uniquely (boolean): Should each machine be forced to have a numerically unique name target name (Unicode text): The new name for the computer. restart task n [inh. task > item]: Restart the target computers. ELEMENTS contained by application. PROPERTIES user can save changes or cancel (boolean): Is the user allowed to save changes or cancel the restart send message task n [inh. task > item]: Send a text message to the target computers. ELEMENTS contained by application. PROPERTIES message (Unicode text): Message to display on the screen(s). send unix command task n [inh. task > item]: Send a UNIX command or script to the target computers. ELEMENTS contained by application. PROPERTIES script (Unicode text): The command string to be executed. showing output (boolean): Should the complete output of command be displayed in a window user (Unicode text): The user to execute the command as. set local startup disk task n [inh. task > item]: Set the startup volume on the target computers. ELEMENTS contained by application. PROPERTIES boot volume (Unicode text): Specific volume of drive to boot (optional). restarting (boolean): Should the machine be restarted after setting the startup volume set network startup disk task n [inh. task > item]: Set the startup volume on the target computers. ELEMENTS contained by application. PROPERTIES from server (Unicode text): Internet address of the server to boot from. mount volume (Unicode text): Volume name on server to mount. restarting (boolean): Should the machine be restarted after setting the startup volume Appendix C AppleScript Remote Desktop Suite 179 share screen task n [inh. task > item]: Share a computers screen to the target computers. ELEMENTS contained by application. PROPERTIES source computer (computer): The computer (other than the admin) whose screen to share. shutdown task n [inh. task > item]: Shutdown the target computers. ELEMENTS contained by application. PROPERTIES user can save changes or cancel (boolean): Is the user allowed to save changes or cancel the shutdown sleep task n [inh. task > item]: Put the target computers to sleep. ELEMENTS contained by application. task n [inh. item]: A task. This abstract class represents the tasks which can be executed by Remote Desktop. There are subclasses for each specific type of task. ELEMENTS contained by application. PROPERTIES computer list (computer list): The computer list associated with the task. id (Unicode text, r/o): The unique identifier (UUID) of the computer. name (Unicode text): The name of the task. recurrence (Unicode text, r/o): A string which describes the task recurrence, if defined. starting at (date): If the task is scheduled, the date and time of the first execution. unlock screen task n [inh. task > item]: Release the screen(s) of the target computers. ELEMENTS contained by application. upgrade client task n [inh. task > item]: Upgrade the Remote Desktop client on the target computers. ELEMENTS contained by application. wake up task n [inh. task > item]: Wake up the target computers. ELEMENTS contained by application.180 D Appendix D PostgreSQL Schema Sample This chapter contains SQL commands to assist SQL programmers in obtaining the database schema used in Apple Remote Desktop’s report database. You can use this knowledge about the schema to create your own applications that access Apple Remote Desktop report information. Sample list of main database schema Command: /System/Library/CoreServices/RemoteManagement/rmdb.bundle/bin/psql -U ard -c "\\d propertynamemap" ard Output: Table "public.propertynamemap" Column | Type | Modifiers ---------------+------------------------+----------- objectname | character varying(128) | not null propertyname | character varying(128) | not null propertymapid | integer | Sample list of system information table Command: /System/Library/CoreServices/RemoteManagement/rmdb.bundle/bin/psql -U ard -c "\\d systeminformation" ard Output: Table "public.systeminformation" Column | Type | Modifiers --------------+--------------------------+----------- computerid | character(17) | not null objectname | character varying(128) | not null propertyname | character varying(128) | not null itemseq | integer | value | character varying(512) | Appendix D PostgreSQL Schema Sample 181 lastupdated | timestamp with time zone | Sample list of property names Command: /System/Library/CoreServices/RemoteManagement/rmdb.bundle/bin/psql -U ard -c "select * from propertynamemap" ard Output: objectname | propertyname | propertymapid -----------------------+------------------------------+--------------- Mac_SystemInfoElement | WirelessCardIsActive | 0 Mac_SystemInfoElement | WirelessCardFirmwareVersion | 1 Mac_SystemInfoElement | WirelessCardHardwareAddress | 2 Mac_SystemInfoElement | WirelessCardLocale | 3 Mac_SystemInfoElement | WirelessCardType | 4 Mac_SystemInfoElement | WirelessCardInstalled | 5 Mac_SystemInfoElement | WirelessChannelNumber | 6 Mac_SystemInfoElement | WirelessNetworkAvailable | 7 Mac_SystemInfoElement | WirelessIsComputerToComputer | 8 ...... Sample list of table from one computer Command: /System/Library/CoreServices/RemoteManagement/rmdb.bundle/bin/psql -U ard -c "select * from systeminformation" ard Output: computerid | objectname | propertyname | itemseq | value | lastupdated -------------------+----------------------+-----------------+---------+----- ----------------+------------------------ 00:03:93:af:15:cc | Mac_HardDriveElement | CreationDate | 0 | 2005-02-25T03:30:07Z| 2005-02-26 22:21:38-08 00:03:93:af:15:cc | Mac_HardDriveElement | FileSystemType | 0 | 18475 | 2005-02-26 22:21:38-08 00:03:93:af:15:cc | Mac_HardDriveElement | FreeSpace | 0 | 4101610 | 2005-02-26 22:21:38-08 00:03:93:af:15:cc | Mac_HardDriveElement | GroupName | 0 | admin | 2005-02-26 22:21:38-08Index 182 Index A aborting a task 98 access changing privileges 69 group-based 62 via local account 61 Access Privileges 59 adding Dock items 131 administrator announce 92 Apple keyboard keys 79 Apple Remote Desktop menu icon 94, 95 application use report 115 asset tracking application use 115 FireWire devices 121 hardware 119 management 118 memory 123 PCI cards 123 software 118 software changes 118 USB devices 121 B basic file copy 108 best practices networking 71 reporting 113–114 security 73 C chat 92 cleaning up hard disks 128 client data upload policy 152 clipboard sharing 82 computer audio volume 130 computer list making a new 54 removing 54 smart 54 computer lists 49 description of 53 computer sharing names 129 Control/Observe preferences 36 controlling a client 78 control window 32 buttons 79–82 Copy and Open 108 copying items data encryption 107 overview 106 UNIX permissions 107 copying to relative locations 107 Copy Items options 107 CPU serial number, accessing 120 Create Custom Installer 43, 44 curtain mode 81, 140 customizing reports 35 D Dashboard observe 91 deleting files 128 demonstration mode 93 designated data collector 112 directory services 62 drag and drop copies 109 installation 104 E enabling SSH on clients 133 encryption one-time use 76 scheme description 75 setting defaults 75 Ethernet address tracking 122 F file mirroring 110 file system maintenance 131 finding free disk space 120 firewall settings 49 full screen display 81Index 183 G General preferences 36 group-based authorization 65 guest access 65 H hard disk maintenance 131 hardware asset management 119 Help Desk Mode. See sharing control human interface customizing 36 icons 29 tips and shortcuts 37 I installation, Remote Desktop 40 Install Packages options 107 K keyboard shortcut exceptions 78 kickstart tool 147, 151 L launching remote applications 136 limiting access privileges 66 limiting features to administrators 66 logging in remote users 140 logging out users 141 M main window 29 Managed Client settings 46 mcx_setting attribute 62, 64 metadata search 116 mirroring a folder 110 moving computer lists 56–57 multi-observe 85, 91 window 33 muting a computer 130 N NetBoot 128 networking best practices 71 networking with AirPort 72 Network Install 128 network interface audit 122 network performance tuning 73 networksetup tool 147 Network Time Protocol (NTP) server 129 notification script 97 O observation settings 87, 88 Observe Widget 91 observe window 32, 33 offline installation 103 Open Directory 62 P package installation 101, 105 preferences 36 preference standardization 133 printer setup 133 Property List Editor tool 62 putting wired clients to sleep 137 Q quitting applications 137 R reclaiming hard disk space 127 Remote 42 removing client software 47, 48 removing files 127 removing Remote Desktop 46 renaming copied items 108 multiple computers 129 repairing UNIX permissions 131 replacing copied items 108 report access privileges 69 Application Usage 115 File Search 117 Software Difference 118 Software Version 118 System Overview 119 User History 114 report data sources 111 reporting best practices 113–114 reporting policy template 153 report window 34 restarting client computers 141 reusing tasks 99, 100 S saving reporting policy preferences 153 saving reports 125 saving settings 99 saving tasks 99, 100 scan file import 52 IP range 50, 52 LAN 50 scanner display 49 scanners 49 screen pushing 93 screen sharing console 94 Scripting Remote Desktop AppleScript 156–159184 Index Automator 159 Secure Screen Blanking. See curtain mode. security best practices 73 preferences 36 sending scripts via UNIX command 145–147 serial number 40 setting boot disk 128 setting encryption defaults 75 setting Energy Saver preferences 132 setting up a Task Server 154 setting wake-on-LAN 132 sharing control 80 Sharing Preference 59 sharing screens 93 software installation 101 software version report 105 Spotlight search 116 SSH access description 68 start VNC server 68 system requirements 39 systemsetup tool 132, 133, 147, 149 T task history 96 task progress 96, 98 task results 99 task schedules 155 Task Server data collection 112 Install Package 103 preferences 36 setup 154 task status 98 task templates saving 100 UNIX commands 143 templates UNIX commands 143 temporary access 65 testing network performance 124–125 text announce 92 text chat 92 third-party installers 104 Tiger-only features Spotlight search 116 tips using report windows 126 using the observe window 90 tracking. See asset tracking. trashing files 127, 128 U uninstalling client software 47, 48 uninstalling Remote Desktop 46 unique computer names 129 UNIX command templates 143 updating software 118 upgrading client software 42 Remote Desktop 41 user history report 114 user interface. See human interface. user login report 114 user mode 66 user requests, viewing 93 using a time server 129 V VNC 67 connecting to server 82 Control-Alt-Delete 83 custom display designation 84 Mac OS X Client as VNC server 85 non–Mac OS X basic set-up 83 port customization 84 W wakeonlan packet 138 waking wired clients 138 window, shortcuts 37 Workgroup Manager 46, 131 X XML 64 Finger Tips Quick Start Guide Welcome to iPhone. This Quick Start guide tells you how to set up your iPhone and use its key features. To start, turn on your iPhone by pressing and holding the On/Off button for a few seconds. Then follow the onscreen instructions to set up your iPhone. Button basics. To turn off or restart iPhone, press and hold the On/Off button for a few seconds, then drag the slider to confirm. To turn off the screen but still receive calls, press On/Off once. Press the Home button at any time to return to the Home screen. To quickly switch between recently used apps, double-click the Home button and tap an app icon. Voice Control. Use Voice Control to make a hands-free call or play music. To activate Voice Control, hold down the Home button or the center button on the iPhone headset until the Voice Control screen appears. After the tone, speak a command such as “call Elliot” or “dial 555-1212.” You can also ask iPhone to play a specific album, artist, or playlist or to “play more songs like this.” You can even ask iPhone “what’s playing?” or say “play songs by the Rolling Stones,” for example. Notifications. When you receive a notification, it appears briefly at the top of the screen without interrupting what you’re doing. Ignore it or tap it to respond right away. To see a summary of your recent notifications, swipe down from the top of any screen. You can access a new notification from the Lock screen by sliding its icon to the right. Messages. Tap the Messages icon to send an iMessage to other iPhone, iPad, and iPod touch users running iOS 5, or to send an SMS or MMS to other mobile phone users. Type a name or phone number in the To field or select someone from your contacts. Type your message, then tap Send. To send photos or video, tap the Camera button. Make a call. Tap a phone number in Contacts, Favorites, an email, a text message, or almost anywhere in iPhone to make a call. Or open the Phone app and tap the Keypad button to dial manually. To silence an incoming call, press the On/Off button once. To send a call directly to voicemail, press On/Off twice. To answer a call while using the iPhone headset, press the center button once. Press it again to end your call. Search. To search your iPhone or the web, go to the main Home screen and press the Home button or swipe the screen from left to right. Type in what you’d like to find—a name, app, song, artist, movie, or any keyword. iPhone offers suggestions as you type to make searching even faster. To search within an app like Mail, Contacts, or Messages, tap the status bar. Intelligent keyboard. iPhone automatically corrects and suggests words as you type. So if you tap a wrong letter, just keep typing. To accept the suggested word, tap the space bar. Or tap the “x” to ignore the suggestion. The keyboard automatically inserts apostrophes in contractions. If you tap the space bar twice, it adds a period. You can double-tap a word to look it up in the dictionary. Cut, copy, and paste. Tap the text you want to edit, or touch and hold to bring up the magnifying glass, then slide your finger to move the insertion point. You can select a word by double-tapping it, and select more or less text by dragging the grab points. Then tap to cut, copy, or paste. To copy text from web pages, email, or text messages, touch and hold to select the text, then tap Copy. On/Off Sleep/Wake Ring/Silent Volume Up/Down HomeNot all features are available in all areas. TM and © 2011 Apple Inc. Designed by Apple in California. Printed in China. 034-6177-A Learn more. Learn more about iPhone features at www.apple.com/iphone. For the iPhone User Guide and important information, visit support.apple.com/manuals/ iphone. To view the guide on iPhone, download it from the iBookstore or use the Safari bookmark. Get support. Contact your wireless service provider for support on network services, voicemail, and billing. Visit www.apple.com/support/ iphone for support on iPhone and iTunes. Photos. Tap the Photos icon on the Home screen to see your pictures. Flick right or left to move between images. Double-tap or pinch to zoom. Tap once to bring up the onscreen controls. You can edit or enhance a photo, share it, print it, and more. If you have Photo Stream enabled in iCloud, new pictures you take are automatically pushed to all your other devices. Cars 2 will be available on iTunes beginning November 1, 2011. Cars 2 © Disney/Pixar. *Requires second-generation Apple TV. Video and song controls. While playing music or watching a movie, tap anywhere on the screen to bring up the controls. Tap again to hide them. To stream your music or video to an Apple TV, tap the AirPlay button.* From the Lock screen, you can double-click the Home button to quickly access your audio controls. See the web up close. In Safari, double-tap any element on a web page—picture or text—to zoom in. Doubletap again to zoom back out. Rotate iPhone to see the web in widescreen. Tap the Reader button at the top of the screen to view an article without clutter. Tap the Multi-page button to flick between multiple web pages or open a new one. Google, the Google logo, and Google Maps are trademarks of Google Inc. © 2011. All rights reserved. Find location. Search surroundings. To see where you are on a map, tap the Location button. A blue dot appears at your current position. To see which way you’re facing, tap the Location button again to turn on compass view. Find places around you by typing words like “Starbucks” or “pizza” in the search field. Double-tap to zoom in. Tap once with two fingers to zoom out. You can also get directions or tap the Page Curl button for additional map views. App Store. Tap the App Store icon to browse hundreds of thousands of apps in categories like games, business, travel, social networking, and more. Browse by Featured, Categories, or Top 25 or search by name. To purchase and download an app directly to your iPhone, tap Buy Now. Many apps are free. iTunes Store. You can access the iTunes Store by tapping the iTunes icon. Search the store for music, movies, TV shows, music videos, and more. Browse, purchase, and download from the store directly to your iPhone. Tap any item to hear or see a preview. Create folders. Organize apps. Touch and hold any app icon until it starts to jiggle. Then drag one app onto another to create a folder. Folders are automatically named by category, or you can rename them. You can customize your Home screen by dragging apps and folders to different positions and screens. When you’re done, press the Home button. Get directions. In Maps, tap Directions, then enter start and end points. You can use your current location, type in an address, or select an address from your contacts or bookmarked locations. Tap Route to display driving directions. Tap the Walk button for walking directions or the Bus button to view transit routes and times. iPhone can track and show your progress along whichever route you take. iCloud. iCloud stores your music, photos, apps, calendars, documents, and more. It’s seamlessly integrated into your apps and wirelessly pushes your content to all your devices. Tap the Settings icon and choose iCloud to turn on Photo Stream and other iCloud features. You can also download music and apps you’ve previously purchased from the iTunes Store and the App Store. This guide contains all the information you need to get from setup to your sofa. Welcome. You’re watching Apple TV.Contents 3 Contents Chapter 1: Connect. 7 What’s in the Box 8 Apple TV at a Glance 10 What You Need 11 Setting Up Apple TV Chapter 2: Configure. 16 Network Configuration 17 Connecting to iTunes Chapter 3: Watch. 20 Using Your Apple Remote 21 Basic Remote Functions 21 Pairing Apple TV with a Remote 22 Unpairing Apple TV from a Remote 23 Changing the Remote Battery 24 Renting Movies and Purchasing TV Shows4 Contents Chapter 4: Problem? No Problem. 26 Troubleshooting 31 Status Light 32 Service and Support 32 Serial Number 33 Care and Cleaningwww.apple.com/support/appletv Connect. 16 Chapter 1 Connect. Chapter 1 Connect. With Apple TV, you can rent high-definition movies, purchase TV shows, watch streaming content from Netflix, and enjoy podcasts, YouTube and Vimeo videos, and Internet radio. And, you can stream your personal iTunes content wirelessly from a Mac or PC, and view photos from your computer or Flickr on your widescreen HDTV, from the comfort of your couch. And with AirPlay, you can wirelessly stream videos, music, and photos from your iPhone, iPad, and iPod touch to Apple TV. Note:  Content availability varies by region. For information about See What you need to get started “What You Need” on page 10 Setting up Apple TV “Setting Up Apple TV” on page 11 Setting up your network connection “Network Configuration” on page 16 Using the Apple Remote “Using Your Apple Remote” on page 20 Troubleshooting Apple TV “Troubleshooting” on page 26 Apple TV safety and warranty The Apple TV Important Product Information GuideChapter 1 Connect. Chapter 1 Connect. 7 What’s in the Box AC power cord Apple Remote Note:  Your power cord may look different from the one pictured here.8 Chapter 1 Connect. Chapter 1 Connect. Apple TV at a Glance IR receiver Status light £ HDMI port d Micro USB port Optical digital audio port Power port G Ethernet portChapter 1 Connect. Chapter 1 Connect. 9 IR receiver Use with the included Apple Remote to control Apple TV. Status light The status light flashes slowly when Apple TV starts up.When Apple TV is on, the status light glows. See “Status Light” on page 31. d Micro USB port For service and diagnostics. ≤ Power port Connect the included AC power cord to the power port on Apple TV. G Ethernet port If your network is Ethernet-based, connect an Ethernet cable. £ HDMI port Connect Apple TV to the HDMI port of a high-definition TV using an HDMI cable. Optical digital audio port Connect Apple TV to a home theater receiver that has an optical digital audio port, using an optical digital audio (also called S/PDIF or TOSLINK) cable. Z Built-in 802.11n Wi-Fi technology Connect Apple TV to your wireless network.10 Chapter 1 Connect. Chapter 1 Connect. What You Need To start using Apple TV, you need the following: High-Definition TV A high-definition TV capable of displaying 720p video Cables  An HDMI cable to connect Apple TV to your TV  An optical digital audio cable (if you plan to use one) Network  An 802.11b, g, or n Wi-Fi wireless network (wireless video streaming requires 802.11g or 802.11n), or 10/100Base-T Ethernet network  A broadband Internet connection (DSL, cable, or LAN)  Your wireless network name and password (if you use one) Software and Accounts To play content from a Mac or PC on Apple TV, you need the following:  An Apple ID to rent movies or purchase TV shows from the iTunes store, and to use Home Sharing to stream content from a Mac or PC  iTunes 10.2 or later  A Netflix account to stream contentChapter 1 Connect. Chapter 1 Connect. 11 Setting Up Apple TV Apple TV connects to your TV through an HDMI port that delivers both audio and video. Before you set up Apple TV, look at the ports on the back of your TV to make sure you have the right cables. You can connect Apple TV to a high-definition TV or home theater receiver that has an HDMI port, using an HDMI cable for both video and audio. You can also use an optical digital audio cable to connect Apple TV to a receiver for audio. Important:  Before you connect Apple TV to a power outlet, carefully read these installation instructions and the safety information in the included Important Product Information Guide.12 Chapter 1 Connect. Chapter 1 Connect. Step 1: Connecting the cables 1 Connect one end of an HDMI cable to the back of your TV. 2 Connect the other end of the cable to the HDMI port on the back of Apple TV. 3 If you’re using an optical digital audio cable for audio, connect one end of the cable to the audio input port on your receiver or TV, and the other end to the optical digital audio port on the back of Apple TV. Apple TV Television HDMI port HDMI port HDMI cable Note:  The built-in 802.11 Wi-Fi technology connects Apple TV to your wireless network. If your network is Ethernet-based, connect Apple TV to your network using an Ethernet cable.Chapter 1 Connect. Chapter 1 Connect. 13 Step 2: Connect the power cord Connect one end of the power cord to the power port on the back of Apple TV and the other end to a power outlet. Power port Important:  Don’t place anything on top of Apple TV. Objects placed on top may interfere with the wireless signal. Don’t place Apple TV on other electronic equipment in a media cabinet. Step 3: Turn on your TV and select the input The first time you use Apple TV, it helps you choose a language, select a network, and configure Apple TV to work with your network (if necessary). See Chapter 2, “Configure.” on page 15. If you see just a black screen the first time you use Apple TV, make sure the input setting you’ve selected on your TV matches the input you connected the cables to on your TV or home theater receiver. See Chapter 4,“Problem? No Problem.” on page 25, and refer to the documentation that came with your TV for information about its inputs.www.apple.com/support/appletv Configure. 216 Chapter 2 Configure. Chapter 2 Configure. Apple TV helps you select and configure your wireless network connection, and, if you want to watch or listen to the contents of your iTunes library, connect to iTunes on your computer. Network Configuration Have your network name and password (if you use one) and your Apple Remote handy when you configure Apple TV. Make sure there are no obstructions between the remote and Apple TV. For information about using your remote, see Chapter 3,“Watch.” on page 19. If you:  Use a wired Ethernet network to connect, Apple TV automatically detects your network.  Use a wireless network to connect, Apple TV helps you select and configure your network connection. Connecting to Your Wireless Network Apple TV helps you connect to your wireless network. If you use a name and password to access your network, have them ready. Use the Apple Remote to: 1 Select your network from the list, or enter your network name if the network is hidden. 2 Enter your network password (if you use one).Chapter 2 Configure. Chapter 2 Configure. 17 If you don’t connect using DHCP, you may need to enter your IP address, subnet mask, router address, and DNS address. To complete the network connection, follow the onscreen instructions. Connecting to iTunes To access the content in your iTunes library on Apple TV, you need iTunes 10.2 or later installed on your computer. For a complete list of system requirements, see “Software and Accounts” on page 10. Updating Your iTunes Software You can update to the latest version of iTunes.  On a Mac, use Software Update to update to the latest version of iTunes. To use Software Update, choose Apple () > Software Update.  On a Windows-based computer, go to iTunes Help to update to the latest version of iTunes. Open iTunes, and then choose Help > Check for Updates. Setting Up Home Sharing After you set up your network connection, you need to set up iTunes and Apple TV to share the contents of your iTunes library. Use Home Sharing in iTunes and on Apple TV to share the iTunes library of any computer on your local network that has Home Sharing set up.18 Chapter 2 Configure. To set up Home Sharing in iTunes: 1 Open iTunes on your computer. 2 Choose Advanced > Turn On Home Sharing. 3 Type your Apple ID and password, and then click Create Home Share. 4 Repeat steps 1 through 3 on each computer you want to use for Home Sharing. For more information about iTunes, open iTunes and choose Help > iTunes Help. To set up Home Sharing on Apple TV: 1 On Apple TV, choose Settings > Computers. 2 Choose Turn On Home Sharing, and then enter the same Apple ID and password you entered on your computer.www.apple.com/support/appletv Watch. 320 Chapter 3 Watch. Chapter 3 Watch. Read on to learn about pairing and using your Apple Remote with Apple TV. Using Your Apple Remote Use the Apple Remote to control Apple TV settings and navigate your content. Make sure there are no obstructions between the remote and Apple TV. MENU Up Down Menu Play/Pause Left Right SelectChapter 3 Watch. Chapter 3 Watch. 21 Basic Remote Functions Your Apple Remote has the basic functions described below. To Do this Move through the menu options Press Up, Down, Left, or Right Select an option from a menu Press Select Return to a previous menu Press Menu Return to the main menu Hold down Menu Reset Apple TV Hold down Menu and Down until the Apple TV status light blinks rapidly Pair Apple TV and a remote Hold down Menu and Right for 6 seconds Up and Down on the Apple Remote don’t control the volume on your TV or home theater receiver. Use the remote that came with your TV or receiver to change the volume. Pairing Apple TV with a Remote The Apple Remote works with the built-in IR receiver on Apple TV. You can set Apple TV to work only with the included remote by pairing Apple TV and the remote.22 Chapter 3 Watch. Chapter 3 Watch. To pair Apple TV with the included remote: 1 Choose Settings from the Apple TV main menu. 2 Choose General > Remotes > Pair Apple Remote. You can also hold down Menu and Right for 6 seconds to pair Apple TV and the Apple Remote. When you successfully pair your Apple Remote, Apple TV displays a chainlink symbol ( ) above a picture of a remote. Apple TV now works only with the paired remote. Unpairing Apple TV from a Remote If you lose the Apple Remote that you paired Apple TV with, you can use any Apple Remote to unpair Apple TV from the lost remote by holding down Menu and Left for 6 seconds. You can also follow these steps. To unpair Apple TV from a paired remote: 1 Choose Settings from the Apple TV main menu. 2 Choose General > Remotes > Unpair Apple Remote. When you successfully unpair the lost remote, Apple TV displays a broken chainlink symbol ( ) above a picture of a remote. You can now pair Apple TV with a different remote.Chapter 3 Watch. Chapter 3 Watch. 23 Changing the Remote Battery When the battery charge in your Apple Remote is low, Apple TV displays a picture of a remote and a warning symbol (·). Replace the battery with a CR2032 battery. Battery compartment To replace the battery: 1 Use a coin to remove the battery compartment cover. 2 Remove the battery. 3 Insert a CR2032 battery with the positive side (∂) facing up. 4 Replace the battery compartment cover and use a coin to tighten it. Important:  Dispose of the used battery according to your local environmental laws and guidelines.24 Chapter 3 Watch. Renting Movies and Purchasing TV Shows You can rent standard or high-definition movies and purchase TV shows directly on Apple TV (where available). Follow the onscreen instructions to find out when a rented movie expires. Purchased TV shows don’t expire. When a rented movie expires, it’s no longer available for playback. To watch it again, you can rent it again from iTunes. Note:  Rented movies are not available in all regions.www.apple.com/support/appletv Problem? No Problem. 426 Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. Most problems with Apple TV can be solved quickly by following the advice in this chapter. For additional tips and troubleshooting information, see the Apple TV Support page at www.apple.com/support/appletv. Troubleshooting If you have a problem with Apple TV, there’s usually a quick and simple solution. First, make sure:  The cables between Apple TV and your TV are pushed in all the way.  The power cords for Apple TV and your TV are securely connected to a working power source.  Your TV is turned on and set to the correct input.  Apple TV is connected to your network. Go to the Settings menu on Apple TV, select Network, and see if Apple TV has an IP address.  Your network and Internet connections are on and working properly. If you still have trouble, try resetting your equipment by disconnecting Apple TV, your TV, your wireless networking equipment or base station, and your router from the power outlet.Wait 30 seconds, and then reconnect everything. If the remote isn’t working  Point the remote directly at Apple TV.  If you paired Apple TV with an Apple Remote, make sure you’re using the paired remote.Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. 27  If the Apple TV status light flashes once when you press buttons on the paired remote, the problem isn’t with the remote. See “If you can see a picture but Apple TV isn’t responding” on page 28.  If you’re using an unpaired remote, the Apple TV status light flashes three times.  If you paired Apple TV with an Apple Remote and you can’t find the paired remote, set Apple TV to work with any Apple Remote by holding down Menu and Left for 6 seconds on another remote.  Make sure the front of Apple TV isn’t blocked.  If Apple TV displays a picture of a remote and a warning symbol (·), you need to replace the battery in the remote. See “Changing the Remote Battery” on page 23. If Apple TV can’t access the network  Check the IP address Apple TV is using. If it starts with 169.x.x.x, the router or base station may not be configured properly. Check to see if DHCP access is available, or configure Apple TV with a manual IP address.  Check for any obstructions, and adjust the location of the base station or Apple TV.  If security is enabled on the network, temporarily disable it on the base station and try connecting again.  Apple TV cannot connect to a wireless network that contains high (extended) ASCII or double-byte (Unicode) characters (such as Japanese, Korean, or Chinese) in the name or password.  If your network has security enabled, make sure you enter the correct password.28 Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. If your TV screen appears fuzzy or black  Make sure you’re using the correct HDMI cable and that it’s connected firmly to Apple TV and to your TV.  Make sure the input setting on your TV matches the input port the HDMI cable is connected to. For information, see the documentation that came with your TV.  Make sure your HDTV supports 720p video. If you can see a picture but Apple TV isn’t responding  Hold down Menu on the Apple Remote to return to the Apple TV main menu.  Make sure your TV is turned on and functioning properly. For information, see the documentation that came with your TV.  If you paired an Apple Remote with Apple TV, make sure you’re using the paired remote. See “Pairing Apple TV with a Remote” on page 21.  Reset Apple TV by doing one of the following:  Hold down both Menu and Down on the Apple Remote until the Apple TV status light blinks rapidly.  Disconnect Apple TV from the power outlet, wait about five seconds, and then reconnect it.  Choose General > Reset Settings from the main menu on Apple TV.Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. 29 If Apple TV doesn’t respond, try restoring it  On Apple TV, choose Settings > General > Reset, and then select Restore. Restoring Apple TV can take some time, so be patient.  If your network doesn’t use DHCP, choose Configure TCP/IP and enter the TCP/IP configuration.  If Apple TV still doesn’t respond:  Disconnect the power and HDMI cables from Apple TV.  Connect one end of a micro USB cable (sold separately) to the back of Apple TV, and the other end to your computer.  Open iTunes on your computer, select Apple TV in the Source list, and then click Restore. If you can’t hear sound  If Apple TV is connected to a home theater receiver, make sure the receiver is turned on.  Make sure the input setting you selected on your TV or receiver matches the input you have your audio cable connected to. For more information, see the documentation that came with your receiver.  Make sure the volume on your TV or receiver is turned up and isn’t muted.  Make sure you’re using the correct audio cable and that it’s connected firmly to Apple TV and to your TV or receiver.  If you’re using the HDMI port for audio, make sure your TV supports audio through its HDMI port. The HDMI ports on some older TVs support only video.30 Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. If Apple TV isn’t playing your photo albums or slideshows  Make sure you have photos in your photo library or in a folder on your computer.  Make sure Apple TV and the computer you’re using are set up for Home Sharing. See “Setting Up Home Sharing” on page 17.  Make sure the photos you want to share are selected. In iTunes, choose Advanced >“Choose Photos to Share,” and then select the photos you want to share.  Make sure Apple TV and your computer are on the same local network.  Make sure Apple TV and your computer are using the same Home Sharing account. If noise is coming from your TV speakers:  If your TV or speakers support Dolby Digital audio, make sure the Dolby Digital Out setting is correct for your TV or speakers. On Apple TV, choose Settings > Audio & Video > Dolby Digital Out, and select On or Off. If you don’t see your iTunes library under Computers on Apple TV:  Make sure Apple TV and your computer are on the same local network.  Make sure Apple TV and iTunes are using the same account name and password.Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. 31 Status Light The status light on the front of Apple TV indicates what’s happening. If Apple TV is The status light On Glows Off or in standby Is off Starting up Flashes slowly Accepting a command from the remote Flashes once Rejecting a command from the remote (you paired a remote with Apple TV, but you’re using a remote that’s not paired) Flashes three times Having problems Flashes quickly32 Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. Service and Support More information about using Apple TV is available in iTunes onscreen help and on the web. The following table describes where to get software and service information. To learn about Do this Service and support, discussions, tutorials, and Apple software downloads Go to: www.apple.com/support/appletv Using iTunes Open iTunes and choose Help > iTunes Help. For an onscreen iTunes tutorial (available in some areas only), go to: www.apple.com/support/itunes Using iPhoto (in Mac OS X) Open iPhoto and choose iPhoto > iPhoto Help Safety and regulatory compliance information See the Important Product Information Guide that comes with Apple TV. Serial Number The serial number is printed on the bottom of Apple TV. You can also find the serial number in the Apple TV Settings menu. On Apple TV, choose Settings > General > About.Chapter 4 Problem? No Problem. Chapter 4 Problem? No Problem. 33 Care and Cleaning NOTICE:  Failure to follow these care and cleaning instructions could result in damage to Apple TV or other property. Using Connectors and Ports Never force a connector into a port. Check for obstructions on the port. If the connector and port don’t join with reasonable ease, they probably don’t match. Make sure that the connector matches the port and that you have positioned the connector correctly in relation to the port. Keeping Apple TV Within Acceptable Temperatures Operate Apple TV in a place where the temperature is always between 0º and 40º C (32º to 104º F). Keeping the Outside of Apple TV Clean To clean Apple TV, unplug the power cord and all cables. Then use a soft, lint-free cloth. Avoid getting moisture in openings. Don’t use window cleaners, household cleaners, aerosol sprays, solvents, alcohol, ammonia, or abrasives to clean Apple TV. Disposing of Apple TV Properly For information about the proper disposal of Apple TV, and for other important regulatory compliance information, see the Important Product Information Guide.K Apple Inc. © 2011 Apple Inc. All rights reserved. Under the copyright laws, this manual may not be copied, in whole or in part, without the written consent of Apple. Every effort has been made to ensure that the information in this manual is accurate. Apple is not responsible for printing or clerical errors. Apple 1 Infinite Loop Cupertino, CA 95014 408-996-1010 www.apple.com The Apple logo is a trademark of Apple Inc., registered in the U.S. and other countries. Use of the “keyboard”Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair competition in violation of federal and state laws. Apple, the Apple logo, AirPlay, Apple TV, iPad, iPhone, iPhoto, iPod touch, iTunes, Mac, and Mac OS are trademarks of Apple Inc., registered in the U.S. and other countries. Apple Store and iTunes Store are service marks of Apple Inc., registered in the U.S. and other countries. Manufactured under license from Dolby Laboratories.“Dolby,”“Pro Logic,” and the double-D symbol are trademarks of Dolby Laboratories. Confidential Unpublished Works, © 1992-1997 Dolby Laboratories, Inc. All rights reserved. Other company and product names mentioned herein may be trademarks of their respective companies. Mention of third-party products is for informational purposes only and constitutes neither an endorsement nor a recommendation. Apple assumes no responsibility with regard to the performance or use of these products. USB Device Interface GuideContents Introduction to USB Device Interface Guide 4 Organization of This Document 4 See Also 4 USB Device Overview 6 USB Device Types and Bus Speeds 6 USB Device Architecture and Terminology 7 USB Device Component Descriptors 8 USB Composite Class Devices 8 USB Transfer Types 8 Stalls and Halts 9 Data Synchronization in Non-Isochronous Transfers 10 USB 2.0 and Isochronous Transfers 10 USB Devices on OS X 11 Finding USB Devices and Interfaces 12 USB Family Error Codes 14 Determining Which Interface Version to Use 14 Tasks and Caveats 15 Handling Stalls, Halts, and Data Toggle Resynchronization 15 Using the Low Latency Isochronous Functions 15 Errors Reported by the EHCI Hub 17 Changes in Isochronous Functions to Support USB 2.0 17 USB Device Access in an Intel-Based Macintosh 18 Working With USB Device Interfaces 20 Using USB Device Interfaces 20 Accessing a USB Device 22 Definitions and Global Variables 22 The main Function 23 Working With the Raw Device 27 Working With the Bulk Test Device 34 Working With Interfaces 36 Document Revision History 46 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 2Tables and Listings USB Device Overview 6 Table 1-1 Examples of USB devices 6 Table 1-2 Keys for finding a USB device 12 Table 1-3 Keys for finding a USB interface 13 Working With USB Device Interfaces 20 Listing 2-1 Definitions and global variables 22 Listing 2-2 The main function 24 Listing 2-3 Accessing and programming the raw device 27 Listing 2-4 Releasing the raw device objects 30 Listing 2-5 Configuring a USB device 30 Listing 2-6 Two functions to download firmware to the raw device 32 Listing 2-7 Accessing the bulk test device 34 Listing 2-8 Finding interfaces on the bulk test device 36 Listing 2-9 Two asynchronous I/O completion functions 43 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 3Note: This document was previously titled Working With USB Device Interfaces. The I/O Kit provides a device interface mechanism that allows applications to communicate with and control hardware from outside the kernel. This document focuses on how to use that mechanism to create an application that detects the attachment of a USB device, communicates with it, and detects its detachment. This document does not describe how to develop an in-kernel driver for a USB modem or networking device. If you need to do this, refer to the documentation and sample code listed in “See Also” (page 4). Important: If your application is sandboxed, it must request the com.apple.security.device.usb entitlement in order to access USB devices. Organization of This Document This document contains the following chapters: ● “USB Device Overview” (page 6) provides an overview of USB device architecture and terminology and describes how USB devices are represented in OS X. ● “Working With USB Device Interfaces” (page 20) describes how to use the device interface mechanism to create a command-line tool that accesses a USB device. ● “Document Revision History” (page 46) lists the revisions of this document. See Also The ADC Reference Library contains several documents on device driver development for OS X and numerous sample drivers and applications. ● Accessing Hardware From Applications describes various ways to access devices from outside the kernel, including the device interface mechanism provided by the I/O Kit. For an overview of the I/O Kit terms and concepts used in this document, read the chapter Device Access and the I/O Kit. 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 4 Introduction to USB Device Interface Guide● I/O Kit Framework Reference contains API reference for I/O Kit methods and functions and for specific device families. ● Sample Code > Hardware & Drivers > USB includes both application-level and in-kernel code samples. Of particular relevance to this document is the application-level sample USBPrivateDataSample . ● OS X Man Pages provides access to existing reference documentation for BSD and POSIX functions and tools in a convenient HTML format. ● The usb mailing list provides a forum for discussing technical issues relating to USB devices in OS X. If you need to develop an in-kernel driver for a USB modem or networking device, refer to the following: ● I/O Kit Fundamentals describesthe architecture ofthe I/OKit,the object-oriented framework for developing OS X device drivers. ● ADC members can view the AppleUSBCDCDriver project in the source code for OS X v10.3.7 and later, available at Darwin Releases. To find the source code, select a version of OS X equal to or greater than v10.3.7 and click Source (choose the source for the PPC version, if there's a choice). This displays a new page, which lists the open source projects available for the version of OS X you've chosen. Scroll down to AppleUSBCDCDriver and click it to view the source. Be prepared to supply your ADC member name and password. ● Additional code samples that demonstrate specific in-kernel driver programming techniques are included as part of the OS X Developer Toolsinstallation package in /Developer/Examples/Kernel/IOKit/usb. If you're ready to create a universal binary version of your USB device-access application to run in an Intel-based Macintosh,seeUniversalBinaryProgrammingGuidelines.TheUniversalBinaryProgrammingGuidelines describes the differences between the Intel and PowerPC architectures and provides tips for developing a universal binary. If you are working with a device that complies with the USB mass storage specification but declares its device class to be vendor specific, see Mass Storage Device Driver Programming Guide for information on how to ensure the correct built-in driver loads for the device. Apple provides additional USB information (including the OS X USB Debug Kits) at http://developer.apple.com/hardwaredrivers/usb/index.html. A detailed description of the USB device specification is beyond the scope of this document—for more information, see Universal Serial Bus Specification Revision 2.0 available at http://www.usb.org. Introduction to USB Device Interface Guide See Also 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 5This chapter provides a summary of USB device architecture and describes how USB devices are represented in OS X. It also presents a few specific guidelines for working with USB devices in an application.For details on the USB specification, see http://www.usb.org. USB Device Types and Bus Speeds The USB specification supports a wide selection of devices that range from lower-speed devices such as keyboards, mice, and joysticks to higher-speed devices such as scanners and digital cameras. The specification lists a number of device classes that each define a set of expected device behaviors. Table 1-1 (page 6) lists some examples of USB devices, categorized by class. Table 1-1 Examples of USB devices USB device class USB devices in class Audio class Speakers, microphones Chip Card Interface Device Class Smart cards, chip cards Communication class Speakerphone, modem A device in which all class-specific information is embedded in its interfaces Composite class HID class Keyboards, mice, joysticks, drawing tablets Hub class Hubs provide additional attachment points for USB devices Hard drives, flash memory readers, CD Read/Write drives, digital cameras, and high-end media players Mass storage class Printing class Printers A device that doesn’t fit into any other predefined class or one that doesn’t use the standard protocols for an existing class Vendor specific Digital camcorders, webcams, digital still cameras that support video streaming Video class 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 6 USB Device OverviewVersion 1.1 of the USB specification supports two bus speeds: ● Low speed (1.5 Mbps) ● Full speed (12 Mbps) Version 2.0 of the specification adds another bus speed to this list: ● High speed (480 Mbps) The USB 2.0 specification is fully compatible with low-speed and full-speed USB devices and even supports the use of cables and connectors made to meet earlier versions of the specification. Apple provides USB 2.0 ports on all new Macintosh computers and fully supports the new specification with Enhanced Host Controller Interface (EHCI) controllers and built-in, low-level USB drivers. For the most part, you do not have to change existing applications to support the faster data rate because the speed increase and other enhancements are implemented at such a low level. The exceptions to this are some differences in isochronous transfers. For information on how the USB 2.0 specification affects isochronous transfers, see “USB 2.0 and Isochronous Transfers” (page 10). USB Device Architecture and Terminology The architecture of a generic USB device is multi-layered. A device consists of one or more configurations, each of which describes a possible setting the device can be programmed into. Such settings can include the power characteristics of the configuration (for example, the maximum power consumed by the configuration and whether it is self-powered or not) and whether the configuration supports remote wake-up. Each configuration contains one or more interfacesthat are accessible after the configuration isset. An interface provides the definitions of the functions available within the device and may even contain alternate settings within a single interface. For example, an interface for an audio device may have different settings you can select for different bandwidths. Each interface contains zero or more endpoints. An endpoint is a uniquely identifiable portion of a USB device that is the source or sink of information in a communication flow between the host and the device. Each endpoint has characteristics that describe the communication it supports, such as transfer type (control, isochronous, interrupt, or bulk, described in “USB Transfer Types” (page 8)), maximum packet size, and transfer direction (input or output). Communication with a USB device is accomplished through a pipe, a logical association between an endpoint and software running on the host. Endpoint and pipe are often used synonymously although an endpoint is a component of a USB device and a pipe is a logical abstraction of the communications link between endpoint and host. USB Device Overview USB Device Architecture and Terminology 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 7USB Device Component Descriptors Each layer of a USB device providesinformation about its attributes and resource requirementsin its descriptor, a data structure accessible through device interface functions. By examining the descriptors at each layer, you can determine exactly which endpoint you need to communicate successfully with a particular device. At the top layer is the device descriptor, which has fields associated with information such as the device’s class and subclass, vendor and product numbers, and number of configurations. Each configuration in turn has a configuration descriptor containing fields that describe the number of interfaces it supports and the power characteristics of the device when it is in that configuration, along with other information. Each interface supported by a configuration has its own descriptor with fields for information such as the interface class, subclass, and protocol, and the number of endpoints in that interface. At the bottom layer are the endpoint descriptors that specify attributes such as transfer type and maximum packet size. The USB specification defines a name for each descriptor field, such as the bDeviceClass field in the device descriptor and the bNumInterfaces field in the configuration descriptor, and each field is associated with a value. For a complete listing of all descriptor fields, see the USB specification at www.usb.org. The USB family defines structures that represent the descriptors defined by the USB specification. For the definitions of these structures, see USB in Kernel Framework Reference . USB Composite Class Devices The USB specification defines a composite class device as a device whose device-descriptor fields for device class (bDeviceClass) and device subclass (bDeviceSubClass) both have the value 0. A composite class device appears to the system as a USB device using a single bus address that may present multiple interfaces, each of which represents a separate function. A good example of a composite class device is a multifunction device, such as a device that performs printing, scanning, and faxing. In such a device, each function is represented by a separate interface. In OS X, the I/O Kit loads the AppleUSBComposite device driver for composite class devices that do not already have vendor-specific device drivers to drive them. The AppleUSBComposite driver configures the device and causes drivers to be loaded for each USB interface. Although most multifunction USB devices are composite class devices, not all composite class devices are multifunction devices. The manufacturer of a single-function USB device is at liberty to classify the device as a composite class device as long as the device meets the USB specifications. For more information on how OS X represents USB devices and interfaces, see “USB Devices on OS X” (page 11). USB Transfer Types The USB specification defines four types of pipe transfer: ● Control—intended to support configuration, command, and status communication between the host software and the device. Control transfers support error detection and retry. USB Device Overview USB Device Architecture and Terminology 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 8● Interrupt—used to support small, limited-latency transfers to or from a device such as coordinates from a pointing device or status changes from a modem. Interrupt transfers support error detection and retry. ● Isochronous—used for periodic, continuous communication between the host and the device, usually involving time-relevant information such as audio or video data streams. Isochronous transfers do not support error detection or retry. ● Bulk—intended for non-periodic, large-packet communication with relaxed timing constraints such as between the host software and a printer or scanner. Bulk transfers support error detection and retry. Pipes also have a transfer direction associated with them. A control pipe can support bidirectional communication but all other pipes are strictly uni-directional. Therefore, two-way communication requires two pipes, one for input and one for output. Every USB device is required to implement a default control pipe that provides access to the device’s configuration, status, and control information. This pipe, implemented in the IOUSBDevice nub object (described in “USB Devices on OS X” (page 11)), is used when a driver such as the AppleUSBComposite driver configures the device or when device-specific control and status information is needed. For example, your application would use the default control pipe if it needs to set or choose a configuration for the device. The default control pipe is connected to the default endpoint (endpoint 0). Note that endpoint 0 does not provide an endpoint descriptor and it is never counted in the total number of endpoints in an interface. The interfaces associated with a configuration can contain any combination of the three remaining pipe types (interrupt, isochronous, and bulk), implemented in the IOUSBInterface nub objects (described in “USB Devices on OS X” (page 11)). Your application can query the interface descriptors of a device to select the pipe most suited to its needs. Stalls and Halts Although a stall and a halt are different, they are closely related in their effect on data transmission. Halt is a feature of an endpoint and it can be set by either the host or the device itself in response to an error. A stall is a type of handshake packet an endpoint returns when it is unable to transmit or receive data or when its halt feature is set (the host never sends a stall packet). When an endpoint sends a stall packet, the host can halt the endpoint. Depending on the precise circumstances and on how compliant the device is, the halt feature must be cleared in the host, the endpoint, or both before data transmission can resume. When the halt is cleared the data toggle bit, used to synchronize data transmission, is also reset (see “Data Synchronization in Non-Isochronous Transfers” (page 10) for more information about the data toggle). For information on how to handle these conditions in your application, see “Handling Stalls, Halts, and Data Toggle Resynchronization” (page 15). USB Device Overview USB Device Architecture and Terminology 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 9Data Synchronization in Non-Isochronous Transfers The USB specification defines a simple protocol to provide data synchronization across multiple packets for non-isochronoustransfers(recall that isochronoustransfers do notsupport error recovery or retry). The protocol is implemented by means of a data toggle bit in both the host and the endpoint which is synchronized at the start of a transaction (or when a reset occurs). The precise synchronization mechanism varies with the type of transfer; see the USB specification for details. Both the host and the endpoint begin a transaction with their data toggle bitsset to zero. In general, the entity receiving data toggles its data toggle bit when it is able to accept the data and it receives an error-free data packet with the correct identification. The entity sending the data toggles its data toggle bit when it receives a positive acknowledgement from the receiver. In this way, the data toggle bits stay synchronized until, for example, a packet with an incorrect identification is received. When this happens, the receiver ignores the packet and does not increment its data toggle bit. When the data toggle bits get out of synchronization (for this or any other reason), you will probably notice that alternate transactions are not getting through in your application. The solution to this is to resynchronize the data toggle bits. For information on how to do this, see “Handling Stalls, Halts, and Data Toggle Resynchronization” (page 15). USB 2.0 and Isochronous Transfers The USB 2.0 specification supports the same four transfer types as earlier versions of the specification. In addition to supporting a higher transfer rate, the new specification defines an improved protocol for high-speed transfers and new ways of handling transactions for low-speed and full-speed devices. For details on the protocols and transaction-handling methods, see the specification at http://www.usb.org. For the most part, these enhancements are implemented at the hostsoftware level and do not require changes to your code. For isochronous transfers, however, you should be aware of the following differences: ● Earlier versions of the specification divide bus time into 1-millisecond frames, each of which can carry multiple transactionsto multiple destinations. (A transaction containstwo or more packets: a token packet and one or more data packets, a handshake packet, or both.) The USB 2.0 specification divides the 1-millisecond frame into eight, 125-microsecond microframes, each of which can carry multiple transactions to multiple destinations. ● The maximum amount of data allowed in a transaction is increased to 3 KB. ● Any isochronous endpoints in a device’s default interface must have a maximum packet size of zero. (This means that the default setting for an interface containing isochronous pipes is alternate setting zero and the maximum packet size for that interface’s isochronous endpoints must be zero.) This ensures that the host can configure the device no matter how busy the bus is. For a summary of how these differences affect the OS X USB API, see “Changes in Isochronous Functions to Support USB 2.0” (page 17). USB Device Overview USB Device Architecture and Terminology 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 10USB Devices on OS X When a USB device is plugged in, the OS X USB family abstracts the contents of the device descriptor into an I/O Kit nub object called an IOUSBDevice. This nub object is attached to the IOService plane of the I/O Registry as a child of the driver for the USB controller. The IOUSBDevice nub object is then registered for matching with the I/O Kit. If the device is a composite class device with no vendor-specific driver to match against it, the AppleUSBComposite driver matches against it and starts as its provider. The AppleUSBComposite driver then configures the device by setting the configuration in the device’s list of configuration descriptors with the maximum power usage that can be satisfied by the port to which the device is attached. This allows a device with a low power and a high power configuration to be configured differently depending on whether it’s attached to a bus-powered hub or a self-powered hub. In addition, if the IOUSBDevice nub object has the “Preferred Configuration” property, the AppleUSBComposite driver will always use that value when it attempts to configure the device. The configuration of the device causes the USB family to abstract each interface descriptor in the chosen configuration into an IOUSBInterface nub object. These nub objects are attached to the I/O Registry as children of the original IOUSBDevice nub object and are registered for matching with the I/O Kit. Important: Because a composite class device is configured by the AppleUSBComposite driver, setting the configuration again from your application will result in the destruction of the IOUSBInterface nub objects and the creation of new ones. In general, the only reason to set the configuration of a composite class device that’s matched by the AppleUSBComposite driver is to choose a configuration other than the first one. For non-composite class devices or composite class devices with vendor-specific drivers that match against them, there is no guarantee that any configuration will be set and you may have to perform this task within your application. It's important to be mindful of the difference between a USB device (represented in the I/O Registry by an IOUSBDevice nub object) and its interfaces (each represented by an IOUSBInterface nub object). A multifunction USB device, for example, is represented in the I/O Registry by one IOUSBDevice object and one IOUSBInterface object for each interface. The distinction between interface and device isimportant because it determines which object your application must find in the I/O Registry and which type of device interface to get. For example, if your application needs to communicate with a specific interface in a multifunction USB device, it must find that interface and get an IOUSBInterfaceInterface to communicate with it. An application that needs to communicate with the USB device as a whole, on the other hand, would need to find the device in the I/O Registry and get an IOUSBDeviceInterface to communicate with it. For more information on finding devices and interfaces in USB Device Overview USB Devices on OS X 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 11the I/O Registry, see “Finding USB Devices and Interfaces” (page 12); for more information on how to get the proper device interface to communicate with a device or interface, see “Using USB Device Interfaces” (page 20). Finding USB Devices and Interfaces To find a USB device or interface, use the keys defined in the Universal Serial Bus Common Class Specification, Revision 1.0 (available for download from http://www.usb.org/developers/devclass_docs/usbccs10.pdf) to create a matching dictionary that defines a particular search. If you are unfamiliar with the concept of device matching, see the section “Finding Devices in the I/O Registry” in Accessing Hardware From Applications. The keys defined in the specification are listed in the tables below. Each key consists of a specific combination of elements in a device or interface descriptor. In the tables below, the elements in a key are separated by the ‘+’ character to emphasize the requirement that all a key’s elements must appear together in your matching dictionary. Both tables present the keys in order of specificity: the first key in each table defines the most specific search and the last key defines the broadest search. Before you build a matching dictionary, be sure you know whether your application needs to communicate with a device or a specific interface in a device. It’s especially important to be aware of this distinction when working with multifunction devices. A multifunction device is often a composite class device that defines a separate interface for each function. If, for example, your application needs to communicate with the scanning function of a device that does scanning, faxing, and printing, you need to build a dictionary to match on only the scanning interface (an IOUSBInterface object), not the device as a whole (an IOUSBDevice object). In this situation, you would use the keys defined for interface matching (those shown in Table 1-3 (page 13)), not the keys for device matching. Table 1-2 (page 12) lists the keys you can use to find devices (not interfaces). Each key element is a piece of information contained in the device descriptor for a USB device. Table 1-2 Keys for finding a USB device Key Notes bcdDevice contains the release number of the device idVendor + idProduct + bcdDevice idVendor + idProduct Use this key only if the device’s bDeviceClass is $FF idVendor + bDeviceSubClass + bDeviceProtocol Use this key only if the device’s bDeviceClass is $FF idVendor + bDeviceSubClass USB Device Overview USB Devices on OS X 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 12Key Notes Use this key only if the device’s bDeviceClass is not $FF bDeviceClass + bDeviceSubClass + bDeviceProtocol Use this key only if the device’s bDeviceClass is not $FF bDeviceClass + bDeviceSubClass Table 1-3 (page 13) lists the keys you can use to find interfaces (not devices). Each key element is a piece of information contained in an interface descriptor for a USB device. Table 1-3 Keys for finding a USB interface Key Notes idVendor + idProduct + bcdDevice + bConfigurationValue + bInterfaceNumber idVendor + idProduct + bConfigurationValue + bInterfaceNumber Use this key only if bInterfaceClass is $FF idVendor + bInterfaceSubClass + bInterfaceProtocol Use this key only if bInterfaceSubClass is $FF idVendor + bInterfaceSubClass Use this key only if bInterfaceSubClass is not $FF bInterfaceClass + bInterfaceSubClass + bInterfaceProtocol Use this key only if bInterfaceSubClass is not $FF bInterfaceClass + bInterfaceSubClass For a successful search, you must add the elements of exactly one key to your matching dictionary. If your matching dictionary contains a combination of elements not defined by any key, the search will be unsuccessful. For example, if you create a matching dictionary containing values representing a device’s vendor, product, and protocol, the search will be unsuccessful even if a device with those precise values in its device descriptor is currently represented by an IOUSBDevice nub in the I/O Registry. This is because there is no key in Table 1-2 (page 12) that combines the idVendor, idProduct, and bDeviceProtocol elements. USB Device Overview USB Devices on OS X 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 13USB Family Error Codes As you develop an application to access a USB device or interface, you will probably encounter error codes specific to the OS X USB family. If you are using Xcode, you can search for information about these error codes in the Xcode documentation window. To find error code documentation, select Documentation from the Xcode Help menu. Select Full-Text Search from the pull-down menu associated with the search field (click the magnifying glass icon to reveal the menu). Select Reference Library in the Search Groups pane at the left of the window. Type an error code number in the search field, such as 0xe0004057, and press Return. Select the most relevant entry in the search results to display the document in the lower portion of the window. Use the Find command (press Command-F) to find the error code in this document. Using the example of error code 0xe0004057, you’ll see that this error is returned when the endpoint has not been found. For help with deciphering I/O Kit error codes in general, see Technical Q&A QA1075, “Making sense of I/O Kit error codes.” Determining Which Interface Version to Use As described in “USB Devices on OS X” (page 11), the OS X USB family provides an IOUSBDeviceInterface object you use to communicate with a USB device as a whole and an IOUSBInterfaceInterface object you use to communicate with an interface in a USB device. There are a number of different versions of the USB family, however, some of which provide new versions of these interface objects. (One way to find the version of the USB family installed in your computer is to view the Finder preview information for the IOUSBFamily.kext located in /System/Library/Extensions.) This section describes how to make sure you use the correct interface object and how to view the documentation for the interface objects. The first version of the USB family was introduced in OS X v10.0 and contains the first versions of the interface objects IOUSBDeviceInterface and IOUSBInterfaceInterface. When new versions of the USB family introduce new functions for an interface object, a new version of the interface object is created, which gives access to both the new functions and all functions defined in all previous versions of that interface object. For example, the IOUSBDeviceInterface197 object provides two new functions you can use with version 1.9.7 of the USB family (available in OS X v10.2.3 and later), in addition to all functions available in the previous device interface objects IOUSBDeviceInterface187, IOUSBDeviceInterface182, and IOUSBDeviceInterface. As you develop an application that accesses a USB device or interface, you should use the latest version of the interface object that is available in the earliest version of OS X that you want to support. For example, if your application must run in OS X v10.0, you must use the IOUSBDeviceInterface and IOUSBInterfaceInterface objects. If, however, you develop an application to run in OS X v10.4 and later, you use the IOUSBDeviceInterface197 object to access the device as a whole and the USB Device Overview USB Devices on OS X 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 14IOUSBInterfaceInterface220 object to access an interface in it. This is because IOUSBDeviceInterface197 is available inOS X version 10.2.3 and later and IOUSBInterfaceInterface220 is available in OS X v10.4 and later. Note: When you view the documentation for these interface objects, notice that each version is documented separately. For example, the documentation for IOUSBDeviceInterface197 contains information about the two new functions introduced in this version, but does not repeat the documentation for the functions introduced in IOUSBDeviceInterface187, IOUSBDeviceInterface182, and IOUSBDeviceInterface. Tasks and Caveats This section presents some specific tasks your application might need to perform, along with some caveats related to USB 2.0 support of which you should be aware. Handling Stalls, Halts, and Data Toggle Resynchronization As described in “Stalls and Halts ” (page 9), stalls and halts are closely related in their effect on data transmission. To simplify the API, the USB family uses the pipe stall terminology in the names of the functions that handle these conditions: ● ClearPipeStall ● ClearPipeStallBothEnds The ClearPipeStall function operates exclusively on the host controller side, clearing the halt feature and resetting the data toggle bit to zero. If the endpoint’s halt feature and data toggle bit must be reset as well, your application must do so explicitly, using one of the ControlRequest functions to send the appropriate device request. See the documentation for the USB.h header file in I/O Kit Framework Reference for more information about standard device requests. In OS X version 10.2 and later, you can use the ClearPipeStallBothEnds function which, as its name suggests, clears the halt and resets the data toggle bit on both sides at the same time. Using the Low Latency Isochronous Functions In OS X, the time between when an isochronous transaction completes on the USB bus and when you receive your callback can stretch to tens of milliseconds. This is because the callback happens on the USB family work loop, which runs at a lower priority than some other threads in the system. In most cases, you can work around USB Device Overview Tasks and Caveats 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 15this delay by queuing read and write requests so that the next transaction is scheduled and ready to start before you receive the callback from the current transaction. In fact, this scheme is a good way to achieve higher performance whether or not low latency is a requirement of your application. In a few cases, however, queuing isochronous transactions to keep the pipe busy is not enough to prevent a latency problem that a user might notice. Consider an application that performs audio processing on some USB input (from a musical instrument, for example) before sending the processed data out to USB speakers. In this scenario, a user hears both the raw, unprocessed output of the instrument and the processed output of the speakers. Of course, some small delay between the time the instrument creates the raw sound waves and the time the speaker emits the processed sound waves is unavoidable. If this delay is greater than about 8 milliseconds, however, the user will notice. In OS X version 10.2.3 (version 1.9.2 of the USB family) the USB family solves this problem by taking advantage of the predictability of isochronous data transfers. By definition, isochronous mode guarantees the delivery of some amount of data every frame or microframe. In earlier versions of OS X, however, it was not possible to find out the exact amount of data that was transferred by a given time. This meant that an application could not begin processing the data until it received the callback associated with the transaction, telling it the transfer status and the actual amount of data that was transferred. Version 1.9.2 of the USB family introduced the LowLatencyReadIsochPipeAsync and LowLatencyWriteIsochPipeAsync functions. These functions update the frame list information (including the transferstatus and the number of bytes actually transferred) at primary interrupt time. Using these functions, an application can request that the frame list information be updated as frequently as every millisecond. This means an application can retrieve and begin processing the number of bytes actually transferred once a millisecond, without waiting for the entire transaction to complete. Important: Because these functions cause processing at primary interrupt time, it is essential you use them only if it is absolutely necessary. Overuse of these functions can cause degradation of system performance. To support the low latency isochronous read and write functions, the USB family also introduced functions to create and destroy the buffers that hold the frame list information and the data. Although you can choose to create a single data buffer and a single frame list buffer or multiple buffers of each type, you must use the LowLatencyCreateBuffer function to create them. Similarly, youmust use the LowLatencyDestroyBuffer function to destroy the buffers after you are finished with them. This restricts all necessary communication with kernel entities to the USB family. For reference documentation on the low latency isochronous functions, see the IOUSBLib.h documentation in I/O Kit Framework Reference . USB Device Overview Tasks and Caveats 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 16Errors Reported by the EHCI Hub The EHCI hub that supports high-speed devices (as well as low-speed and full-speed devices) provides coarser-grained error reporting than the OHCI hub does. For example, with an OHCI hub, you might receive an “endpoint timed out” error if you unplug the device while it is active. If you perform the same action with an EHCI hub, you might receive a “pipe stalled” error instead. The Apple EHCI hub driver cannot get more detailed error information from the hub, so it alternates between reporting “device not responding” and “pipe stalled” regardless of the actual error reported by the device. To avoid problems with your code, be sure your application does not rely on other, more specific errors to make important decisions. Changes in Isochronous Functions to Support USB 2.0 Recall that the USB 2.0 specification divides the 1-millisecond frame into eight, 125-microsecond microframes. The USB family handles this by reinterpreting some function parameters (where appropriate) and adding a couple of new functions. This section summarizes these changes; for reference documentation, see documentation for IOUSBLib.h in I/O Kit Framework Reference . The functions you use to read from and write to isochronous endpoints are ReadIsochPipeAsync and WriteIsochPipeAsync. Both functions include the following two parameters: ● numFrames—The number of frames for which to transfer data ● frameList—A pointer to an array of structures that describe the frames If you need to handle high-speed isochronous transfers, you can think of these parameters as referring to “transfer opportunities” instead of frames. In other words, numFrames can refer to a number of frames for full-speed devices or to a number of microframes for high-speed devices. Similarly, frameList specifies the list of transfers you want to occur, whether they are in terms of frames or microframes. Note: The ReadIsochPipeAsync and WriteIsochPipeAsync functions also have the frameStart parameter in common, but it does not get reinterpreted. Thisis because all isochronoustransactions, including high-speed isochronoustransactions,start on a frame boundary, not amicroframe boundary. To help you determine whether a device isfunctioning in full-speed or high-speed mode, the USB family added the GetFrameListTime function, which returns the number of microseconds in a frame. By examining the result (kUSBFullSpeedMicrosecondsInFrame or kUSBHighSpeedMicrosecondsInFrame) you can tell in which mode the device is operating. USB Device Overview Tasks and Caveats 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 17The USB family also added the GetBusMicroFrameNumber function which is similar to the GetBusFrameNumber function, except that it returns both the current frame and microframe number and includes the time at which that information was retrieved. To handle the new specification’s requirement that isochronous endpoints in a device’s default interface have a maximum packetsize of zero, the USB family added functionsthat allow you to balance bandwidth allocations among isochronous endpoints. A typical scenario is this: 1. Call GetBandwidthAvailable (available inOS X version 10.2 and later)to determine howmuch bandwidth is currently available for allocation to isochronous endpoints. 2. Call GetEndpointProperties (available in OS X version 10.2 and later) to examine the alternate settings of an interface and find one that uses an appropriate amount of bandwidth. 3. Call SetAlternateInterface (available in OS X version 10.0 and later) to create the desired interface and allocate the pipe objects. 4. Call GetPipeProperties (available in OS X version 10.0 and later) on the chosen isochronous endpoint. Thisis a very importantstep because SetAlternateInterface willsucceed, even if there is not enough bandwidth for the endpoints. Also, another device might have claimed the bandwidth that was available at the time the GetBandwidthAvailable function returned. If this happens, the maximum packet size for your chosen endpoint (contained in the maxPacketSize field) is now zero, which means that the bandwidth is no longer available. In addition, in OS X version 10.2, the USB family added the SetPipePolicy function, which allows you to relinquish bandwidth that might have been specified in an alternate setting. USB Device Access in an Intel-Based Macintosh This section provides an overview of some of the issues related to developing a universal binary version of an application that accesses a USB device. Before you read this section, be sure to read Universal Binary Programming Guidelines. That document covers architectural differences and byte-ordering formats and provides comprehensive guidelines for code modification and building universal binaries. The guidelines in that document apply to all types of applications, including those that access hardware. Before you build your application as a universal binary, make sure that: ● You port your project to GCC 4 (Xcode uses GCC 4 to target Intel-based Macintosh computers) ● You install the OS X v10.4 universal SDK ● You develop your project in Xcode 2.1 or later USB Device Overview USB Device Access in an Intel-Based Macintosh 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 18The USB bus is a little-endian bus. Structured data appears on the bus in the little-endian format regardless of the native endian format of the computer an application isrunning in. If you've developed a USB device-access application to run in a PowerPC-based Macintosh, you probably perform some byte swapping on data you read from the USB bus because the PowerPC processor uses the big-endian format. For example, the USB configuration descriptor structure contains a two-byte field that holds the descriptor length. If your PowerPC application reads this structure from the USB bus (instead of receiving it from a USB device interface function), you need to swap the value from the USB bus format (little endian) to the PowerPC format (big endian). The USB family provides several swapping macros that swap from USB to host and from host to USB (for more information on these macros, see USB.h). The Kernel framework also provides byte-swapping macros and functions you can use in high-level applications (see the OSByteOrder.h header file in libkern). If you use these macros in your application, you shouldn't have any trouble developing a universal binary version of your application. This is because these macros determine at compile time if a swap is necessary. If, however, your application uses hard-coded swaps from little endian to big endian, your application will not run correctly in an Intel-based Macintosh. As you develop a universal binary version of your application, therefore, be sure to use the USB family swapping macros or the macros in libkern/OSByteOrder.h for all byte swapping. Although you may need to perform byte swapping on values your application reads from the USB bus, you do not need to perform any byte swapping on values you pass in arguments to functions in the USB family API. You should pass argument values in the computer's host format. Likewise, any values you receive from the USB family functions will be in the computer's host format. USB Device Overview USB Device Access in an Intel-Based Macintosh 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 19This chapter describes how to develop a user-space tool that finds and communicates with an attached USB device and one of its interfaces. Important: The sample code featured in this document isintended to illustrate how to access a USB device from an application. It is not intended to provide guidance on error handling and other features required for production-quality code. Using USB Device Interfaces Applications running in OS X get access to USB devices by using I/O Kit functions to acquire a device interface, a type of plug-in that specifies functions the application can call to communicate with the device. The USB family provides two types of device interface: ● IOUSBDeviceInterface for communicating with the device itself ● IOUSBInterfaceInterface for communicating with an interface in the device Both device interfaces are defined in /System/Library/Frameworks/IOKit.framework/Headers/usb/IOUSBLib.h. Communicating with the device itself is usually only necessary when you need to set or change its configuration. For example, vendor-specific devices are often not configured because there are no default drivers that set a particular configuration. In this case, your application must use the device interface for the device to set the configuration it needs so the interfaces become available. Important: If your application is sandboxed, it must request the com.apple.security.device.usb entitlement in order to access USB devices. The process of finding and communicating with a USB device is divided into two sets of steps. The first set outlines how to find a USB device, acquire a device interface of type IOUSBDeviceInterface for it, and set or change its configuration. The second set describes how to find an interface in a device, acquire a device interface of type IOUSBInterfaceInterface for it, and use it to communicate with that interface. If you need to communicate with an unconfigured device or if you need to change a device’s configuration, you follow both sets of steps. If you need to communicate with a device that is already configured to your 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 20 Working With USB Device Interfacesspecification, you follow only the second set of steps. The sample code in “Accessing a USB Device” (page 22) follows both sets of steps and extends them to include setting up notifications it can receive when devices are dynamically added or removed. Follow this first set of steps only to set or change the configuration of a device. If the device you’re interested in is already configured for your needs, skip these steps and follow the second set of steps. 1. Find the IOUSBDevice object that represents the device in the I/O Registry. This includes setting up a matching dictionary with a key from the USB Common Class Specification (see “Finding USB Devices and Interfaces” (page 12)). The sample code usesthe key elements kUSBVendorName and kUSBProductName to find a particular USB device (this is the second key listed in Table 1-2 (page 12)). 2. Create a device interface of type IOUSBDeviceInterface for the device. This device interface provides functionsthat perform taskssuch assetting or changing the configuration of the device, getting information about the device, and resetting the device. 3. Examine the device’s configurations with GetConfigurationDescriptorPtr, choose the appropriate one, and call SetConfiguration to set the device’s configuration and instantiate the IOUSBInterface objects for that configuration. Follow thissecond set ofstepsto find and choose an interface, acquire a device interface for it, and communicate with the device. 1. Create an interface iterator to iterate over the available interfaces. 2. Create a device interface for each interface so you can examine its properties and select the appropriate one. To do this, you create a device interface of type IOUSBInterfaceInterface. This device interface providesfunctionsthat perform taskssuch as getting information about the interface,setting the interface’s alternate setting, and accessing its pipes. 3. Use the USBInterfaceOpen function to open the selected interface. This will cause the pipes associated with the interface to be instantiated so you can examine the properties of each and select the appropriate one. 4. Communicate with the device through the selected pipe. You can write to and read from the pipe synchronously or asynchronously—the sample code in “Accessing a USB Device” (page 22) shows how to do both. Working With USB Device Interfaces Using USB Device Interfaces 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 21Accessing a USB Device This section provides snippets of sample code that show how to access a Cypress EZ-USB chip with an 8051 microcontroller core. The sample code followsthe firstset ofstepsin section “Using USB Device Interfaces” (page 20) to find the Cypress EZ-USB chip in its default, unprogrammed state (also referred to as the “raw device”). It then configures the device and downloads firmware provided by Cypress to program the chip to behave as a device that echoes all information it receives on its bulk out pipe to its bulk in pipe. Once the chip has been programmed, the device nub representing the default, unprogrammed device is detached from the I/O Registry and a new device nub, representing the programmed chip, is attached. To communicate with the programmed chip (also referred to as the “bulk test device”), the sample code must perform the first set of steps again to find the device, create a device interface for it, and configure it. Then it performs the second set of steps to find an interface, create a device interface for it, and test the device. The sample code also shows how to set up notifications for the dynamic addition and removal of a device. Important: If your application is sandboxed, it must request the com.apple.security.device.usb entitlement in order to access USB devices. Definitions and Global Variables The code in the USB Notification Example uses the definitions and global variables shown in Listing 2-1 (page 22). The definition of USE_ASYNC_IO allows you to choose to use either synchronous or asynchronous calls to read from and write to the chip by commenting out the line or leaving it in, respectively. The definition of kTestMessage sets up a simple message to write to the device. The remaining definitions are specific to the Cypress EZ-USB chip. Listing 2-1 Definitions and global variables #define USE_ASYNC_IO //Comment this line out if you want to use //synchronous calls for reads and writes #define kTestMessage "Bulk I/O Test" #define k8051_USBCS 0x7f92 #define kOurVendorID 1351 //Vendor ID of the USB device #define kOurProductID 8193 //Product ID of device BEFORE it //is programmed (raw device) #define kOurProductIDBulkTest 4098 //Product ID of device AFTER it is //programmed (bulk test device) //Global variables Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 22static IONotificationPortRef gNotifyPort; static io_iterator_t gRawAddedIter; static io_iterator_t gRawRemovedIter; static io_iterator_t gBulkTestAddedIter; static io_iterator_t gBulkTestRemovedIter; static char gBuffer[64]; The main Function The main function in the USB Notification Example project (contained in the file main.c) accomplishes the following tasks. ● It establishes communication with the I/O Kit and sets up a matching dictionary to find the Cypress EZ-USB chip. ● It sets up an asynchronous notification to be called when an unprogrammed (raw) device is first attached to the I/O Registry and another to be called when the device is removed. ● It modifies the matching dictionary to find the programmed (bulk test) device. ● It sets up additional notifications to be called when the bulk test device is first attached or removed. ● It starts the run loop so the notifications that have been set up will be received. The main function uses I/O Kit functions to set up and modify a matching dictionary and set up notifications, and Core Foundation functions to set up the run loop for receiving the notifications. It calls the following functions to access both the raw device and the bulk test device. ● RawDeviceAdded, shown in Listing 2-3 (page 27), iterates over the set of matching devices and creates a device interface for each one. It calls ConfigureDevice (shown in Listing 2-5 (page 30)) to set the device’s configuration, and then DownloadToDevice (shown in Listing 2-6 (page 32)) to download the firmware to program it. ● RawDeviceRemoved,shown in Listing 2-4 (page 30), iterates over the set of matching devices and releases each one in turn. ● BulkTestDeviceAdded, shown in Listing 2-7 (page 34), iterates over the new set of matching devices, creates a device interface for each one, and calls ConfigureDevice (shown in Listing 2-5 (page 30)) to set the device’s configuration. It then calls FindInterfaces (shown in Listing 2-8 (page 36)) to get access to the interfaces on the device. ● BulkTestDeviceRemoved iterates over the new set of matching devices and releases each one in turn. This function is not shown in this chapter; see RawDeviceRemoved (Listing 2-4 (page 30)) for a nearly identical function. Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 23Listing 2-2 The main function int main (int argc, const char *argv[]) { mach_port_t masterPort; CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; kern_return_t kr; SInt32 usbVendor = kOurVendorID; SInt32 usbProduct = kOurProductID; // Get command line arguments, if any if (argc > 1) usbVendor = atoi(argv[1]); if (argc > 2) usbProduct = atoi(argv[2]); //Create a master port for communication with the I/O Kit kr = IOMasterPort(MACH_PORT_NULL, &masterPort); if (kr || !masterPort) { printf("ERR: Couldn’t create a master I/O Kit port(%08x)\n", kr); return -1; } //Set up matching dictionary for class IOUSBDevice and its subclasses matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (!matchingDict) { printf("Couldn’t create a USB matching dictionary\n"); mach_port_deallocate(mach_task_self(), masterPort); return -1; } //Add the vendor and product IDs to the matching dictionary. //This is the second key in the table of device-matching keys of the //USB Common Class Specification Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 24CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorName), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor)); CFDictionarySetValue(matchingDict, CFSTR(kUSBProductName), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); //To set up asynchronous notifications, create a notification port and //add its run loop event source to the program’s run loop gNotifyPort = IONotificationPortCreate(masterPort); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); //Retain additional dictionary references because each call to //IOServiceAddMatchingNotification consumes one reference matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict); matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict); matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict); //Now set up two notifications: one to be called when a raw device //is first matched by the I/O Kit and another to be called when the //device is terminated //Notification of first match: kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, matchingDict, RawDeviceAdded, NULL, &gRawAddedIter); //Iterate over set of matching devices to access already-present devices //and to arm the notification RawDeviceAdded(NULL, gRawAddedIter); //Notification of termination: kr = IOServiceAddMatchingNotification(gNotifyPort, kIOTerminatedNotification, matchingDict, RawDeviceRemoved, NULL, &gRawRemovedIter); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 25//Iterate over set of matching devices to release each one and to //arm the notification RawDeviceRemoved(NULL, gRawRemovedIter); //Now change the USB product ID in the matching dictionary to match //the one the device will have after the firmware has been downloaded usbProduct = kOurProductIDBulkTest; CFDictionarySetValue(matchingDict, CFSTR(kUSBProductName), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); //Now set up two notifications: one to be called when a bulk test device //is first matched by the I/O Kit and another to be called when the //device is terminated. //Notification of first match kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, matchingDict, BulkTestDeviceAdded, NULL, &gBulkTestAddedIter); //Iterate over set of matching devices to access already-present devices //and to arm the notification BulkTestDeviceAdded(NULL, gBulkTestAddedIter); //Notification of termination kr = IOServiceAddMatchingNotification(gNotifyPort, kIOTerminatedNotification, matchingDict, BulkTestDeviceRemoved, NULL, &gBulkTestRemovedIter); //Iterate over set of matching devices to release each one and to //arm the notification. NOTE: this function is not shown in this document. BulkTestDeviceRemoved(NULL, gBulkTestRemovedIter); //Finished with master port mach_port_deallocate(mach_task_self(), masterPort); masterPort = 0; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 26//Start the run loop so notifications will be received CFRunLoopRun(); //Because the run loop will run forever until interrupted, //the program should never reach this point return 0; } Working With the Raw Device Now that you’ve obtained an iterator for a set of matching devices, you can use it to gain access to each raw device, configure it, and download the appropriate firmware to it. The function RawDeviceAdded (shown in Listing 2-3 (page 27)) uses I/O Kit functions to create a device interface for each device and then calls the following functions to configure the device and download firmware to it. ● ConfigureDevice, shown in Listing 2-5 (page 30), uses device interface functions to get the number of configurations, examine the first one, and set the device’s configuration. ● DownloadToDevice, shown in Listing 2-6 (page 32), downloads the firmware in bulktest.c to the device. Listing 2-3 Accessing and programming the raw device void RawDeviceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; IOCFPlugInInterface **plugInInterface = NULL; IOUSBDeviceInterface **dev = NULL; HRESULT result; SInt32 score; UInt16 vendor; UInt16 product; UInt16 release; while (usbDevice = IOIteratorNext(iterator)) { //Create an intermediate plug-in Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 27kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); //Don’t need the device object after intermediate plug-in is created kr = IOObjectRelease(usbDevice); if ((kIOReturnSuccess != kr) || !plugInInterface) { printf("Unable to create a plug-in (%08x)\n", kr); continue; } //Now create the device interface result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *)&dev); //Don’t need the intermediate plug-in after device interface //is created (*plugInInterface)->Release(plugInInterface); if (result || !dev) { printf("Couldn’t create a device interface (%08x)\n", (int) result); continue; } //Check these values for confirmation kr = (*dev)->GetDeviceVendor(dev, &vendor); kr = (*dev)->GetDeviceProduct(dev, &product); kr = (*dev)->GetDeviceReleaseNumber(dev, &release); if ((vendor != kOurVendorID) || (product != kOurProductID) || (release != 1)) { printf("Found unwanted device (vendor = %d, product = %d)\n", vendor, product); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 28(void) (*dev)->Release(dev); continue; } //Open the device to change its state kr = (*dev)->USBDeviceOpen(dev); if (kr != kIOReturnSuccess) { printf("Unable to open device: %08x\n", kr); (void) (*dev)->Release(dev); continue; } //Configure device kr = ConfigureDevice(dev); if (kr != kIOReturnSuccess) { printf("Unable to configure device: %08x\n", kr); (void) (*dev)->USBDeviceClose(dev); (void) (*dev)->Release(dev); continue; } //Download firmware to device kr = DownloadToDevice(dev); if (kr != kIOReturnSuccess) { printf("Unable to download firmware to device: %08x\n", kr); (void) (*dev)->USBDeviceClose(dev); (void) (*dev)->Release(dev); continue; } //Close this device and release object kr = (*dev)->USBDeviceClose(dev); kr = (*dev)->Release(dev); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 29} } The function RawDeviceRemoved simply uses the iterator obtained from the main function (shown in Listing 2-2 (page 24)) to release each device object. This also has the effect of arming the raw device termination notification so it will notify the program of future device removals. RawDeviceRemoved is shown in Listing 2-4 (page 30). Listing 2-4 Releasing the raw device objects void RawDeviceRemoved(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t object; while (object = IOIteratorNext(iterator)) { kr = IOObjectRelease(object); if (kr != kIOReturnSuccess) { printf("Couldn’t release raw device object: %08x\n", kr); continue; } } } Although every USB device has one or more configurations, unless the device is a composite class device that’s been matched by the AppleUSBComposite driver which automatically sets the first configuration, none of those configurations may have been set. Therefore, your application may have to use device interface functions to get the appropriate configuration value and use it to set the device’s configuration. In the sample code, the function ConfigureDevice (shown in Listing 2-5 (page 30)) accomplishes this task. In fact, it is called twice: once by RawDeviceAdded to configure the raw device and again by BulkTestDeviceAdded (shown in Listing 2-7 (page 34)) to configure the bulk test device. Listing 2-5 Configuring a USB device IOReturn ConfigureDevice(IOUSBDeviceInterface **dev) Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 30{ UInt8 numConfig; IOReturn kr; IOUSBConfigurationDescriptorPtr configDesc; //Get the number of configurations. The sample code always chooses //the first configuration (at index 0) but your code may need a //different one kr = (*dev)->GetNumberOfConfigurations(dev, &numConfig); if (!numConfig) return -1; //Get the configuration descriptor for index 0 kr = (*dev)->GetConfigurationDescriptorPtr(dev, 0, &configDesc); if (kr) { printf("Couldn’t get configuration descriptor for index %d (err = %08x)\n", 0, kr); return -1; } //Set the device’s configuration. The configuration value is found in //the bConfigurationValue field of the configuration descriptor kr = (*dev)->SetConfiguration(dev, configDesc->bConfigurationValue); if (kr) { printf("Couldn’t set configuration to value %d (err = %08x)\n", 0, kr); return -1; } return kIOReturnSuccess; } Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 31Now that the device is configured, you can download firmware to it. Cypress makes firmware available to program the EZ-USB chip to emulate different devices. The sample code in this document uses firmware that programs the chip to be a bulk test device, a device that takes the data it receives from its bulk out pipe and echoesit to its bulk in pipe. The firmware, contained in the file bulktest.c, is an array of INTEL_HEX_RECORD structures (defined in the file hex2c.h). The function DownloadToDevice uses the function WriteToDevice (shown together in Listing 2-6 (page 32)) to prepare the device to receive the download and then to write information from each structure to the appropriate address on the device. When all the firmware has been downloaded, DownloadToDevice calls WriteToDevice a last time to inform the device that the download is complete. At this point, the raw device detaches itself from the bus and reattaches as a bulk test device. This causes the device nub representing the raw device to be removed from the I/O Registry and a new device nub, representing the bulk test device, to be attached. Listing 2-6 Two functions to download firmware to the raw device IOReturn DownloadToDevice(IOUSBDeviceInterface **dev) { int i; UInt8 writeVal; IOReturn kr; //Assert reset. This tells the device that the download is //about to occur writeVal = 1; //For this device, a value of 1 indicates a download kr = WriteToDevice(dev, k8051_USBCS, 1, &writeVal); if (kr != kIOReturnSuccess) { printf("WriteToDevice reset returned err 0x%x\n", kr); (*dev)->USBDeviceClose(dev); (*dev)->Release(dev); return kr; } //Download firmware i = 0; while (bulktest[i].Type == 0) //While bulktest[i].Type == 0, this is Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 32{ //not the last firmware record to //download kr = WriteToDevice(dev, bulktest[i].Address, bulktest[i].Length, bulktest[i].Data); if (kr != kIOReturnSuccess) { printf("WriteToDevice download %i returned err 0x%x\n", i, kr); (*dev)->USBDeviceClose(dev); (*dev)->Release(dev); return kr; } i++; } //De-assert reset. This tells the device that the download is complete writeVal = 0; kr = WriteToDevice(dev, k8051_USBCS, 1, &writeVal); if (kr != kIOReturnSuccess) printf("WriteToDevice run returned err 0x%x\n", kr); return kr; } IOReturn WriteToDevice(IOUSBDeviceInterface **dev, UInt16 deviceAddress, UInt16 length, UInt8 writeBuffer[]) { IOUSBDevRequest request; request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBDevice); request.bRequest = 0xa0; request.wValue = deviceAddress; request.wIndex = 0; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 33request.wLength = length; request.pData = writeBuffer; return (*dev)->DeviceRequest(dev, &request); } Working With the Bulk Test Device After you download the firmware to the device, the raw device is no longer attached to the bus. To gain access to the bulk test device, you repeat most of the same steps you used to get access to the raw device. ● Use the iterator obtained by a call to IOServiceAddMatchingNotification in the main function (shown in Listing 2-2 (page 24)) to iterate over a set of matching devices. ● Create a device interface for each device. ● Configure the device. This time, however, the next step is to find the interfaces on the device so you can choose the appropriate one and get access to its pipes. Because of the similarities of these tasks, the function BulkTestDeviceAdded follows the same outline of the RawDeviceAdded function except that instead of downloading firmware to the device, it calls FindInterfaces (shown in Listing 2-8 (page 36)) to examine the available interfaces and their pipes. The code in Listing 2-7 (page 34) replaces most of the BulkTestDeviceAdded function’s code with comments, focusing on the differences between it and the RawDeviceAdded function. Listing 2-7 Accessing the bulk test device void BulkTestDeviceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; IOUSBDeviceInterface **device=NULL; while (usbDevice = IOIteratorNext(iterator)) { //Create an intermediate plug-in using the //IOCreatePlugInInterfaceForService function //Release the device object after getting the intermediate plug-in Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 34//Create the device interface using the QueryInterface function //Release the intermediate plug-in object //Check the vendor, product, and release number values to //confirm we’ve got the right device //Open the device before configuring it kr = (*device)->USBDeviceOpen(device); //Configure the device by calling ConfigureDevice //Close the device and release the device interface object if //the configuration is unsuccessful //Get the interfaces kr = FindInterfaces(device); if (kr != kIOReturnSuccess) { printf("Unable to find interfaces on device: %08x\n", kr); (*device)->USBDeviceClose(device); (*device)->Release(device); continue; } //If using synchronous IO, close and release the device interface here #ifndef USB_ASYNC_IO kr = (*device)->USBDeviceClose(device); kr = (*device)->Release(device); #endif } } Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 35The function BulkTestDeviceRemoved simply uses the iterator obtained from the main function (shown in Listing 2-2 (page 24)) to release each device object. This also has the effect of arming the bulk test device termination notification so it will notify the program of future device removals.The BulkTestDeviceRemoved function is identical to the RawDeviceRemoved function (shown in Listing 2-4 (page 30)), with the exception of the wording of the printed error statement. Working With Interfaces Now that you’ve configured the device, you have access to its interfaces. The FindInterfaces function (shown in Listing 2-8 (page 36)) creates an iterator to iterate over all interfaces on the device and then creates a device interface to communicate with each one. For each interface found, the function opens the interface, determines how many endpoints (or pipes) it has, and prints out the properties of each pipe. Because opening an interface causes its pipes to be instantiated, you can get access to any pipe by using its pipe index. The pipe index is the number of the pipe within the interface, ranging from one to the number of endpoints returned by GetNumEndpoints. You can communicate with the default control pipe (described in “USB Transfer Types” (page 8)) from any interface by using pipe index 0, but it is usually better to use the device interface functions for the device itself (see the use of IOUSBDeviceInterface functions in Listing 2-5 (page 30)). The sample code employs conditional compilation using #ifdef and #ifndef to demonstrate both synchronous and asynchronous I/O. If you’ve chosen to test synchronous I/O, FindInterfaces writes the test message (defined in Listing 2-1 (page 22)) to pipe index 2 on the device and readsits echo before returning. For asynchronous I/O, FindInterfaces first creates an event source and adds it to the run loop created by the main function (shown in Listing 2-2 (page 24)). It then sets up an asynchronous write and read that will cause a notification to be sent upon completion. The completion functions WriteCompletion and ReadCompletion are shown together in Listing 2-9 (page 43). Listing 2-8 Finding interfaces on the bulk test device IOReturn FindInterfaces(IOUSBDeviceInterface **device) { IOReturn kr; IOUSBFindInterfaceRequest request; io_iterator_t iterator; io_service_t usbInterface; IOCFPlugInInterface **plugInInterface = NULL; IOUSBInterfaceInterface **interface = NULL; HRESULT result; SInt32 score; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 36UInt8 interfaceClass; UInt8 interfaceSubClass; UInt8 interfaceNumEndpoints; int pipeRef; #ifndef USE_ASYNC_IO UInt32 numBytesRead; UInt32 i; #else CFRunLoopSourceRef runLoopSource; #endif //Placing the constant kIOUSBFindInterfaceDontCare into the following //fields of the IOUSBFindInterfaceRequest structure will allow you //to find all the interfaces request.bInterfaceClass = kIOUSBFindInterfaceDontCare; request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; request.bAlternateSetting = kIOUSBFindInterfaceDontCare; //Get an iterator for the interfaces on the device kr = (*device)->CreateInterfaceIterator(device, &request, &iterator); while (usbInterface = IOIteratorNext(iterator)) { //Create an intermediate plug-in kr = IOCreatePlugInInterfaceForService(usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); //Release the usbInterface object after getting the plug-in kr = IOObjectRelease(usbInterface); if ((kr != kIOReturnSuccess) || !plugInInterface) { printf("Unable to create a plug-in (%08x)\n", kr); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 37break; } //Now create the device interface for the interface result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID *) &interface); //No longer need the intermediate plug-in (*plugInInterface)->Release(plugInInterface); if (result || !interface) { printf("Couldn’t create a device interface for the interface (%08x)\n", (int) result); break; } //Get interface class and subclass kr = (*interface)->GetInterfaceClass(interface, &interfaceClass); kr = (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass); printf("Interface class %d, subclass %d\n", interfaceClass, interfaceSubClass); //Now open the interface. This will cause the pipes associated with //the endpoints in the interface descriptor to be instantiated kr = (*interface)->USBInterfaceOpen(interface); if (kr != kIOReturnSuccess) { printf("Unable to open interface (%08x)\n", kr); (void) (*interface)->Release(interface); break; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 38} //Get the number of endpoints associated with this interface kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); if (kr != kIOReturnSuccess) { printf("Unable to get number of endpoints (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); break; } printf("Interface has %d endpoints\n", interfaceNumEndpoints); //Access each pipe in turn, starting with the pipe at index 1 //The pipe at index 0 is the default control pipe and should be //accessed using (*usbDevice)->DeviceRequest() instead for (pipeRef = 1; pipeRef <= interfaceNumEndpoints; pipeRef++) { IOReturn kr2; UInt8 direction; UInt8 number; UInt8 transferType; UInt16 maxPacketSize; UInt8 interval; char *message; kr2 = (*interface)->GetPipeProperties(interface, pipeRef, &direction, &number, &transferType, &maxPacketSize, &interval); if (kr2 != kIOReturnSuccess) printf("Unable to get properties of pipe %d (%08x)\n", pipeRef, kr2); else Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 39{ printf("PipeRef %d: ", pipeRef); switch (direction) { case kUSBOut: message = "out"; break; case kUSBIn: message = "in"; break; case kUSBNone: message = "none"; break; case kUSBAnyDirn: message = "any"; break; default: message = "???"; } printf("direction %s, ", message); switch (transferType) { case kUSBControl: message = "control"; break; case kUSBIsoc: message = "isoc"; break; case kUSBBulk: message = "bulk"; break; case kUSBInterrupt: message = "interrupt"; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 40break; case kUSBAnyType: message = "any"; break; default: message = "???"; } printf("transfer type %s, maxPacketSize %d\n", message, maxPacketSize); } } #ifndef USE_ASYNC_IO //Demonstrate synchronous I/O kr = (*interface)->WritePipe(interface, 2, kTestMessage, strlen(kTestMessage)); if (kr != kIOReturnSuccess) { printf("Unable to perform bulk write (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); break; } printf("Wrote \"%s\" (%ld bytes) to bulk endpoint\n", kTestMessage, (UInt32) strlen(kTestMessage)); numBytesRead = sizeof(gBuffer) - 1; //leave one byte at the end //for NULL termination kr = (*interface)->ReadPipe(interface, 9, gBuffer, &numBytesRead); if (kr != kIOReturnSuccess) { printf("Unable to perform bulk read (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 41break; } //Because the downloaded firmware echoes the one’s complement of the //message, now complement the buffer contents to get the original data for (i = 0; i < numBytesRead; i++) gBuffer[i] = ~gBuffer[i]; printf("Read \"%s\" (%ld bytes) from bulk endpoint\n", gBuffer, numBytesRead); #else //Demonstrate asynchronous I/O //As with service matching notifications, to receive asynchronous //I/O completion notifications, you must create an event source and //add it to the run loop kr = (*interface)->CreateInterfaceAsyncEventSource( interface, &runLoopSource); if (kr != kIOReturnSuccess) { printf("Unable to create asynchronous event source (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); break; } CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); printf("Asynchronous event source added to run loop\n"); bzero(gBuffer, sizeof(gBuffer)); strcpy(gBuffer, kTestMessage); kr = (*interface)->WritePipeAsync(interface, 2, gBuffer, strlen(gBuffer), WriteCompletion, (void *) interface); if (kr != kIOReturnSuccess) Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 42{ printf("Unable to perform asynchronous bulk write (%08x)\n", kr); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); break; } #endif //For this test, just use first interface, so exit loop break; } return kr; } When an asynchronous write action is complete, the WriteCompletion function is called by the notification. WriteCompletion then calls the interface function ReadPipeAsync to perform an asynchronous read from the pipe. When the read is complete, control passes to ReadCompletion which simply prints status messages and adds a NULL termination to the global buffer containing the test message read from the device. The WriteCompletion and ReadCompletion functions are shown together in Listing 2-9 (page 43). Listing 2-9 Two asynchronous I/O completion functions void WriteCompletion(void *refCon, IOReturn result, void *arg0) { IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **) refCon; UInt32 numBytesWritten = (UInt32) arg0; UInt32 numBytesRead; printf("Asynchronous write complete\n"); if (result != kIOReturnSuccess) { printf("error from asynchronous bulk write (%08x)\n", result); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); return; } Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 43printf("Wrote \"%s\" (%ld bytes) to bulk endpoint\n", kTestMessage, numBytesWritten); numBytesRead = sizeof(gBuffer) - 1; //leave one byte at the end for //NULL termination result = (*interface)->ReadPipeAsync(interface, 9, gBuffer, numBytesRead, ReadCompletion, refCon); if (result != kIOReturnSuccess) { printf("Unable to perform asynchronous bulk read (%08x)\n", result); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); return; } } void ReadCompletion(void *refCon, IOReturn result, void *arg0) { IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **) refCon; UInt32 numBytesRead = (UInt32) arg0; UInt32 i; printf("Asynchronous bulk read complete\n"); if (result != kIOReturnSuccess) { printf("error from async bulk read (%08x)\n", result); (void) (*interface)->USBInterfaceClose(interface); (void) (*interface)->Release(interface); return; } //Check the complement of the buffer’s contents for original data for (i = 0; i < numBytesRead; i++) gBuffer[i] = ~gBuffer[i]; Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 44printf("Read \"%s\" (%ld bytes) from bulk endpoint\n", gBuffer, numBytesRead); } Working With USB Device Interfaces Accessing a USB Device 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 45This table describes the changes to USB Device Interface Guide . Date Notes 2012-01-09 Added information about App Sandbox. 2007-09-04 Made minor corrections. Described how to determine which version of an interface object to use when accessing a USB device or interface. 2007-02-08 2006-04-04 Made minor corrections. Emphasized which type of device interface to get for USB devices and interfaces and clarified definition of composite class device. 2006-03-08 2005-11-09 Made minor corrections. Added information about creating a universal binary for an application that accesses a USB device. 2005-09-08 2005-08-11 Made minor bug fixes. Added information about low latency isochronous transactions and functions. 2005-06-04 Included discussion of USB 2.0 and associated changes to isochronous functions. Changed title from "Working With USB Device Interfaces." 2005-04-29 2004-05-27 Fixed URL for USB Common Class Specification. 2002-11-15 First version. 2012-01-09 | © 2002, 2012 Apple Inc. All Rights Reserved. 46 Document Revision HistoryApple Inc. © 2002, 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Finder, Mac, Macintosh, OS X, Pages, Sand, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. Intel and Intel Core are registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries. PowerPC and the PowerPC logo are trademarks of International Business Machines Corporation, used under license therefrom. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Core Data Model Versioning and Data Migration Programming GuideContents Core Data Model Versioning and Data Migration 5 At a Glance 5 Prerequisites 6 Understanding Versions 7 Model File Format and Versions 10 Lightweight Migration 12 Core Data Must Be Able to Infer the Mapping 12 Request Automatic Migration Using an Options Dictionary 13 Use a Migration Manager if Models Cannot Be Found Automatically 14 Mapping Overview 17 Mapping Model Objects 17 Creating a Mapping Model in Xcode 19 The Migration Process 20 Overview 20 Requirements for the Migration Process 20 Custom Entity Migration Policies 21 Three-Stage Migration 21 Initiating the Migration Process 23 Initiating the Migration Process 23 The Default Migration Process 24 Customizing the Migration Process 26 Is Migration Necessary 26 Initializing a Migration Manager 27 Performing a Migration 28 Multiple Passes—Dealing With Large Datasets 29 Migration and iCloud 30 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 2Document Revision History 31 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsFigures and Listings Understanding Versions 7 Figure 1-1 Recipes models “Version 1.0” 7 Figure 1-2 Recipes model “Version 1.1” 7 Figure 1-3 Recipes model “Version 2.0” 8 Model File Format and Versions 10 Figure 2-1 Initial version of the Core Recipes model 10 Figure 2-2 Version 2 of the Core Recipes model 11 Mapping Overview 17 Figure 4-1 Mapping model for versions 1-2 of the Core Recipes models 19 Initiating the Migration Process 23 Listing 6-1 Opening a store using automatic migration 24 Customizing the Migration Process 26 Listing 7-1 Checking whether migration is necessary 26 Listing 7-2 Initializing a Migration Manager 27 Listing 7-3 Performing a Migration 28 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 4Core Data provides support for managing changes to a managed object model as your application evolves. You can only open a Core Data store using the managed object model used to create it. Changing a model will therefore make it incompatible with (and so unable to open) the stores it previously created. If you change your model, you therefore need to change the data in existing stores to new version—changing the store format is known as migration. To migrate a store, you need both the version of the model used to create it, and the current version of the model you want to migrate to. You can create a versioned model that contains more than one version of a managed object model. Within the versioned model you mark one version as being the current version. Core Data can then use this model to open persistent stores created using any of the model versions, and migrate the stores to the current version. To help Core Data perform the migration, though, you may have to provide information about how to map from one version of the model to another. This information may be in the form of hints within the versioned model itself, or in a separate mapping model file that you create. At a Glance Typically, as it evolves from one version to another, numerous aspects of your application change: the classes you implement, the user interface, the file format, and so on. You need to be aware of and in control of all these aspects; there is no API that solves the problems associated with all these—for example Cocoa does not provide a means to automatically update your user interface if you add a new attribute to an entity in your managed object model. Core Data does not solve all the issues of how you roll out your application. It does, though, provide support for a small—but important and non-trivial—subset of the tasks you must perform as your application evolves. ● Model versioning allows you to specify and distinguish between different configurations of your schema. There are two distinct views of versioning: your perspective as a developer, and Core Data’s perspective. These may not always be the same. The differences are discussed in “Understanding Versions” (page 7). The format of a versioned managed object model, and how you add a version to a model, is discussed in “Model File Format and Versions” (page 10). ● Core Data needs to know how to map from the entities and properties in a source model to the entities and properties in the destination model. 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 5 Core Data Model Versioning and Data MigrationIn many cases, Core Data can infer the mapping from existing versions of the managed object model. This is described in “Lightweight Migration” (page 12). If you make changes to your models such that Core Data cannot infer the mapping from source to destination, you need to create a mapping model. A mapping model parallels a managed object model, specifying how to transform objects in the source into instances appropriate for the destination. How you create a mapping model is discussed in “Mapping Overview” (page 17). ● Data migration allows you to convert data from one model (schema) to another, using mappings. The migration process itself is discussed in “The Migration Process” (page 20). How you perform a migration is discussed in “Initiating the Migration Process” (page 23). You can also customize the migration process—that is, how you programmatically determine whether migration is necessary; how you find the correct source and destination models and the appropriate mapping model to initialize the migration manager; and then how you perform the migration. You only customize the migration process if you want to initiate migration yourself. You might do this to, for example, search locations other than the application’s main bundle for models or to deal with large data sets by performing the migration in several passes using different mapping models. How you can customize the process is described in “Customizing the Migration Process” (page 26). ● If you are using iCloud, there are some constraints on what migration you can perform. If you are using iCloud, you must use lightweight migration. Other factors to be aware of are described in “Migration and iCloud” (page 30). Although Core Data makes versioning and migration easier than would typically otherwise be the case, these processes are still non-trivial in effect. You still need to carefully consider the implications of releasing and supporting different versions of your application. Prerequisites This document assumes that you are familiar with the Core Data architecture and the fundamentals of using Core Data. You should be able to identify the parts of the Core Data stack and understand the roles of the model, the managed object context, and the persistent store coordinator. You need to know how to create a managed object model, how to create and programmatically interact with parts of the Core Data stack. If you do not meet these requirements, you should first read the Core Data Programming Guide and related materials. You are strongly encouraged also to work through the Core Data Utility Tutorial . Core Data Model Versioning and Data Migration Prerequisites 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 6There are two distinct views of versioning: your perspective as a developer, and Core Data’s perspective. These may not always be the same—consider the following models. Figure 1-1 Recipes models “Version 1.0” Recipe Attributes cuisine directions name Relationships chef ingredients Chef Attributes name training Relationships recipes Ingredient Attributes amount name Relationships recipes Figure 1-2 Recipes model “Version 1.1” Recipe Attributes cuisine directions name Relationships chef ingredients Chef Attributes name training Relationships recipes Ingredient Attributes amount name Relationships recipes Recipe changes: • Add validation rules • Change User Info values • Use custom class 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 7 Understanding VersionsFigure 1-3 Recipes model “Version 2.0” Recipe Attributes directions name rating Relationships chef cuisines ingredients Chef Attributes firstName lastName Relationships recipes Ingredient Attributes amount name Relationships recipe Cuisine Attributes name Relationships recipes As a developer, your perspective is typically that a version is denoted by an identifier—a string or number, such as “9A218”, “2.0.7”, or “Version 1.1”. To support this view, managed object models have a set of identifiers (see versionIdentifiers)—typically for a single model you provide a single string (the attribute itself is a set so that if models are merged all the identifiers can be preserved). How the identifier should be interpreted is up to you, whether it represents the version number of the application, the version that was committed prior to going on vacation, or the last submission before it stopped working. Core Data, on the other hand, treats these identifiers simply as “hints”. To understand why, recall that the format of a persistent store is dependent upon the model used to create it, and that to open a persistent store you must have a model that is compatible with that used to create it. Consider then what would happen if you changed the model but not the identifier—for example, if you kept the identifier the same but removed one entity and added two others. To Core Data, the change in the schema is significant, the fact that the identifier did not change is irrelevant. Core Data’s perspective on versioning isthat it is only interested in features of the model that affect persistence. This means that for two models to be compatible: ● For each entity the following attributes must be equal: name, parent, isAbstract, and properties. className, userInfo, and validation predicates are not compared. ● For each property in each entity, the following attributes must be equal: name, isOptional, isTransient, isReadOnly, for attributes attributeType, and for relationships destinationEntity, minCount, maxCount, deleteRule, and inverseRelationship. userInfo and validation predicates are not compared. Notice that Core Data ignores any identifiers you set. In the examples above, Core Data treats version 1.0 (Figure 1-1 (page 7)) and 1.1 (Figure 1-2 (page 7)) as being compatible. Understanding Versions 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 8Rather than enumerating through all the relevant parts of a model, Core Data creates a 32-byte hash digest of the components which it compares for equality (see versionHash (NSEntityDescription) and versionHash (NSPropertyDescription)). These hashes are included in a store’s metadata so that Core Data can quickly determine whether the store format matches that of the managed object model it may use to try to open the store. (When you attempt to open a store using a given model, Core Data compares the version hashes of each of the entities in the store with those of the entities in the model, and if all are the same then the store is opened.) There is typically no reason for you to be interested in the value of a hash. There may, however, be some situations in which you have two versions of a model that Core Data would normally treat as equivalent that you want to be recognized as being different. For example, you might change the name of the class used to represent an entity, or more subtly you might keep the model the same but change the internal format of an attribute such as a BLOB—this is irrelevant to Core Data, but it is crucial for the integrity of your data. To support this, Core Data allows you to set a hash modifier for an entity or property see versionHashModifier (NSEntityDescription) and versionHashModifier (NSPropertyDescription). In the examples above, if you wanted to force Core Data to recognize that “Version 1.0” (Figure 1-1 (page 7)) and “Version 1.1” (Figure 1-2 (page 7)) of your models are different, you could set an entity modifier for the Recipe entity in the second model to change the version hash Core Data creates. Understanding Versions 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 9A managed object model that supports versioning is represented in the filesystem by a .xcdatamodeld document. An .xcdatamodeld document is a file package (see “Document Packages”) that groups versions of the model, each represented by an individual .xcdatamodel file, and an Info.plist file that contains the version information. The model is compiled into a runtime format—a file package with a .momd extension that containsindividually compiled model files with a .mom extension. You load the .momd model bundle using NSManagedObjectModel’s initWithContentsOfURL:. To add a version to a model, you start with a model such as that illustrated in Figure 2-1. Figure 2-1 Initial version of the Core Recipes model 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 10 Model File Format and VersionsTo add a version, select Editor > Add Model Version. In the sheet that appears, you enter the name of the new model version and select the model on which it should be based. To set the new model asthe current version of the model,select the .xcdatamodeld document in the project navigator, then select the new model in the pop-up menu in the Versioned Core Data Model area in the Attributes Inspector (see Figure 2-2). Figure 2-2 Version 2 of the Core Recipes model Model File Format and Versions 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 11If you just make simple changes to your model (such as adding a new attribute to an entity), Core Data can perform automatic data migration, referred to aslightweightmigration. Lightweight migration isfundamentally the same as ordinary migration, except that instead of you providing a mapping model (as described in “Mapping Overview” (page 17)), Core Data infers one from differences between the source and destination managed object models. Lightweight migration is especially convenient during early stages of application development, when you may be changing your managed object model frequently, but you don’t want to have to keep regenerating test data. You can migrate existing data without having to create a custom mapping model for every model version used to create a store that would need to be migrated. A further advantage of using lightweight migration—beyond the fact that you don’t need to create the mapping model yourself—is that if you use an inferred model and you use the SQLite store, then Core Data can perform the migration in situ (solely by issuing SQL statements). This can represent a significant performance benefit as Core Data doesn’t have to load any of your data. Because of this, you are encouraged to use inferred migration where possible, even if the mapping model you might create yourself would be trivial. Core Data Must Be Able to Infer the Mapping To perform automatic lightweight migration, Core Data needs to be able to find the source and destination managed object models itself at runtime. Core Data looks for models in the bundles returned by NSBundle’s allBundles and allFrameworks methods. If you store your models elsewhere, you must follow the steps described in “Use a Migration Manager if Models Cannot Be Found Automatically ” (page 14). Core Data must then analyze the schema changes to persistent entities and properties and generate an inferred mapping model. For Core Data to be able to generate an inferred mapping model, changes must fit an obvious migration pattern, for example: ● Simple addition of a new attribute ● Removal of an attribute ● A non-optional attribute becoming optional ● An optional attribute becoming non-optional, and defining a default value 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 12 Lightweight Migration● Renaming an entity or property If you rename an entity or property, you can set the renaming identifier in the destination model to the name of the corresponding property or entity in the source model. You set the renaming identifier in the managed object model using the Xcode Data Modeling tool’s property inspector (for either an entity or a property). For example, you can: ● Rename a Car entity to Automobile ● Rename a Car’s color attribute to paintColor The renaming identifier creates a “canonical name,” so you should set the renaming identifier to the name of the property in the source model (unless that property already has a renaming identifier). This means you can rename a property in version 2 of a model then rename it again version 3, and the renaming will work correctly going from version 2 to version 3 or from version 1 to version 3. In addition, Core Data supports: ● Adding relationships and changing the type of relationship ● You can add a new relationship or delete an existing relationship. ● Renaming a relationship (by using a renaming identifier, just like an attribute) ● Changing a relationship from a to-one to a to-many, or a non-ordered to-many to ordered (and visa-versa) ● Changing the entity hierarchy ● You can add, remove, rename entities ● You can create a new parent or child entity and move properties up and down the entity hierarchy ● You can move entities out of a hierarchy You cannot, however, merge entity hierarchies; if two existing entities do not share a common parent in the source, they cannot share a common parent in the destination Request Automatic Migration Using an Options Dictionary You request automatic lightweight migration using the options dictionary you pass in addPersistentStoreWithType:configuration:URL:options:error:, by setting values corresponding to both the NSMigratePersistentStoresAutomaticallyOption and the NSInferMappingModelAutomaticallyOption keys to YES: NSError *error = nil; Lightweight Migration Request Automatic Migration Using an Options Dictionary 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 13NSURL *storeURL = <#The URL of a persistent store#>; NSPersistentStoreCoordinator *psc = <#The coordinator#>; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; BOOL success = [psc addPersistentStoreWithType:<#Store type#> configuration:<#Configuration or nil#> URL:storeURL options:options error:&error]; if (!success) { // Handle the error. } If you want to determine in advance whether Core Data can infer the mapping between the source and destination models without actually doing the work of migration, you can use NSMappingModel’s inferredMappingModelForSourceModel:destinationModel:error: method. Thisreturnsthe inferred model if Core Data is able to create it, otherwise nil. Use a Migration Manager if Models Cannot Be Found Automatically To perform automatic migration, Core Data has to be able to find the source and destination managed object models itself at runtime (see “Core Data Must Be Able to Infer the Mapping” (page 12)). If you need to put your models in the locations not checked by automatic discovery, then you need to generate the inferred model and initiate the migration yourself using a migration manager (an instance of NSMigrationManager). The following code sample illustrates how to generate an inferred model and initiate the migration using a migration manager. The code assumes that you have implemented two methods—sourceModel and destinationModel—that return the source and destination managed object models respectively. - (BOOL)migrateStore:(NSURL *)storeURL toVersionTwoStore:(NSURL *)dstStoreURL error:(NSError **)outError { // Try to get an inferred mapping model. NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:[self sourceModel] destinationModel:[self destinationModel] error:outError]; Lightweight Migration Use a Migration Manager if Models Cannot Be Found Automatically 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 14// If Core Data cannot create an inferred mapping model, return NO. if (!mappingModel) { return NO; } // Create a migration manager to perform the migration. NSMigrationManager *manager = [[NSMigrationManager alloc] initWithSourceModel:[self sourceModel] destinationModel:[self destinationModel]]; BOOL success = [manager migrateStoreFromURL:storeURL type:NSSQLiteStoreType options:nil withMappingModel:mappingModel toDestinationURL:dstStoreURL destinationType:NSSQLiteStoreType destinationOptions:nil error:outError]; return success; } Lightweight Migration Use a Migration Manager if Models Cannot Be Found Automatically 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 15Note: Prior to OS X v10.7 and iOS 4, you need to use a store-specific migration manager to perform lightweight migration. You get the migration manager for a given persistent store type using migrationManagerClass, as illustrated in the following example. - (BOOL)migrateStore:(NSURL *)storeURL toVersionTwoStore:(NSURL *)dstStoreURL error:(NSError **)outError { // Try to get an inferred mapping model. NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:[self sourceModel] destinationModel:[self destinationModel] error:outError]; // If Core Data cannot create an inferred mapping model, return NO. if (!mappingModel) { return NO; } // Get the migration manager class to perform the migration. NSValue *classValue = [[NSPersistentStoreCoordinator registeredStoreTypes] objectForKey:NSSQLiteStoreType]; Class sqliteStoreClass = (Class)[classValue pointerValue]; Class sqliteStoreMigrationManagerClass = [sqliteStoreClass migrationManagerClass]; NSMigrationManager *manager = [[sqliteStoreMigrationManagerClass alloc] initWithSourceModel:[self sourceModel] destinationModel:[self destinationModel]]; BOOL success = [manager migrateStoreFromURL:storeURL type:NSSQLiteStoreType options:nil withMappingModel:mappingModel toDestinationURL:dstStoreURL destinationType:NSSQLiteStoreType destinationOptions:nil error:outError]; return success; } Lightweight Migration Use a Migration Manager if Models Cannot Be Found Automatically 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 16In many cases, Core Data may be able to infer how to transform data from one schema to another (see “Lightweight Migration” (page 12). If Core Data cannot infer the mapping from one model to another, you need a definition of how to perform the transformation. This information is captured in a mapping model. A mapping model is a collection of objects that specifies the transformations that are required to migrate part of a store from one version of your model to another (for example, that one entity is renamed, an attribute is added to another, and a third split into two). You typically create a mapping model in Xcode. Much as the managed object model editor allows you to graphically create the model, the mapping model editor allows you to customize the mappings between the source and destination entities and properties. Mapping Model Objects Like a managed object model, a mapping model is a collection of objects. Mapping model classes parallel the managed object model classes—there are mapping classes for a model, an entity, and a property (NSMappingModel, NSEntityMapping, and NSPropertyMapping respectively). ● An instance of NSEntityMapping specifies a source entity, a destination entity (the type of object to create to correspond to the source object) and mapping type (add, remove, copy as is, or transform). ● An instance of NSPropertyMapping specifiesthe name of the property in the source and in the destination entity, and a value expression to create the value for the destination property. The model does not contain instances of NSEntityMigrationPolicy or any of its subclasses, however amongst other attributes instance of NSEntityMapping can specify the name of an entity migration policy class (a subclass of NSEntityMigrationPolicy) to use to customize the migration. For more about entity migration policy classes, see “Custom Entity Migration Policies” (page 21). You can handle simple property migration changes by configuring a custom value expression on a property mapping directly in the mapping model editor in Xcode. For example, you can: ● Migrate data from one attribute to another. To rename amount to totalCost, enter the custom value expression for the totalCost property mapping as $source.amount. ● Apply a value transformation on a property. 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 17 Mapping OverviewTo convert temperature from Fahrenheit to Celsius, use the custom value expression ($source.temperature - 32.0) / 1.8. ● Migrate objects from one relationship to another. To rename trades to transactions, enter the custom value expression for the transactions property mapping as FUNCTION($manager, "destinationInstancesForEntityMappingNamed:sourceInstances:", "TradeToTrade", $source.trades). (This assumes the entity mapping that migrates Trade instances is named TradeToTrade.) There are six predefined keys you can reference in custom value expressions. To access these keys in source code, you use the constants as declared. To access them in custom value expression strings in the mapping model editor in Xcode, follow the syntax rules outlined in the predicate format string syntax guide and refer to them as: NSMigrationManagerKey: $manager NSMigrationSourceObjectKey: $source NSMigrationDestinationObjectKey: $destination NSMigrationEntityMappingKey: $entityMapping NSMigrationPropertyMappingKey: $propertyMapping NSMigrationEntityPolicyKey: $entityPolicy Mapping Overview Mapping Model Objects 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 18Creating a Mapping Model in Xcode From the File menu, you select New File and in the New File pane select Design > Mapping Model. In the following pane, you select the source and destination models. When you click Finish, Xcode creates a new mapping model that contains as many default mappings as it can deduce from the source and destination. For example, given the model files shown in Figure 1-1 (page 7) and Figure 1-2 (page 7), Xcode creates a mapping model as shown in Figure 4-1. Figure 4-1 Mapping model for versions 1-2 of the Core Recipes models Reserved words in custom value expressions: If you use a custom value expression, you must escape reserved words such as SIZE, FIRST, and LAST using a # (for example, $source.#size). Mapping Overview Creating a Mapping Model in Xcode 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 19During migration, Core Data creates two stacks, one for the source store and one for the destination store. Core Data then fetches objects from the source stack and inserts the appropriate corresponding objects into the destination stack. Note that Core Data must re-create objects in the new stack. Overview Recall that stores are bound to their models. Migration is required when the model doesn't match the store. There are two areas where you get default functionality and hooks for customizing the default behavior: ● When detecting version skew and initializing the migration process. ● When performing the migration process. To perform the migration processrequirestwo Core Data stacks—which are automatically created for you—one for the source store, one for the destination store. The migration process is performed in 3 stages, copying objects from one stack to another. Requirements for the Migration Process Migration of a persistent store is performed by an instance of NSMigrationManager. To migrate a store, the migration manager requires several things: ● The managed object model for the destination store. This is the persistent store coordinator’s model. ● A managed object model that it can use to open the existing store. ● Typically, a mapping model that defines a transformation from the source (the store’s) model to the destination model. You don’t need a mapping model if you’re able to use lightweight migration—see “Lightweight Migration” (page 12). 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 20 The Migration ProcessYou can specify custom entity migration policy classes to customize the migration of individual entities. You specify custom migration policy classesin the mapping model (note the “Custom Entity Policy Name” text field in Figure 4-1 (page 19)). Custom Entity Migration Policies If your new model simply adds properties or entities to your existing model, there may be no need to write any custom code. If the transformation is more complex, however, you might need to create a subclass of NSEntityMigrationPolicy to perform the transformation; for example: ● If you have a Person entity that also includes address information that you want to split into a separate Address entity, but you want to ensure uniqueness of each Address. ● If you have an attribute that encodes data in a string format that you want to change to a binary representation. The methods you override in a custom migration policy correspond to the different phases of the migration process—these are called out in the description of the process given in “Three-Stage Migration.” Three-Stage Migration The migration process itself is in three stages. It uses a copy of the source and destination models in which the validation rules are disabled and the class of all entities is changed to NSManagedObject. To perform the migration, Core Data sets up two stacks, one for the source store and one for the destination store. Core Data then processes each entity mapping in the mapping model in turn. It fetches objects of the current entity into the source stack, creates the corresponding objects in the destination stack, then recreates relationships between destination objects in a second stage, before finally applying validation constraints in the final stage. Before a cycle starts, the entity migration policy responsible for the current entity is sent a beginEntityMapping:manager:error: message. You can override this method to perform any initialization the policy requires. The process then proceeds as follows: 1. Create destination instances based on source instances. At the beginning of this phase, the entity migration policy is sent a createDestinationInstancesForSourceInstance:entityMapping:manager:error:message; at the end it is sent a endInstanceCreationForEntityMapping:manager:error: message. In this stage, only attributes (not relationships) are set in the destination objects. The Migration Process Custom Entity Migration Policies 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 21Instances of the source entity are fetched. For each instance, appropriate instances of the destination entity are created (typically there is only one) and their attributes populated (for trivial cases, name = $source.name). A record is kept of the instances per entity mapping since this may be useful in the second stage. 2. Recreate relationships. At the beginning of this phase, the entity migration policy is sent a createRelationshipsForDestinationInstance:entityMapping:manager:error: message; at the end it is sent a endRelationshipCreationForEntityMapping:manager:error: message. For each entity mapping (in order), for each destination instance created in the first step any relationships are recreated. 3. Validate and save. In this phase, the entity migration policy is sent a performCustomValidationForEntityMapping:manager:error: message. Validation rules in the destination model are applied to ensure data integrity and consistency, and then the store is saved. At the end of the cycle, the entity migration policy issent an endEntityMapping:manager:error: message. You can override this method to perform any clean-up the policy needs to do. Note that Core Data cannot simply fetch objects into the source stack and insert them into the destination stack, the objects must be re-created in the new stack. Core Data maintains “association tables” which tell it which object in the destination store isthe migrated version of which object in the source store, and vice-versa. Moreover, because it doesn't have a means to flush the contexts it is working with, you may accumulate many objects in the migration manager as the migration progresses. If this presents a significant memory overhead and hence gives rise to performance problems, you can customize the process as described in “Multiple Passes—Dealing With Large Datasets” (page 29). The Migration Process Three-Stage Migration 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 22This chapter describes how to initiate the migration process and how the default migration process works. It does not describe customizing the migration process—this is described in “Customizing the Migration Process” (page 26). Initiating the Migration Process When you initialize a persistent store coordinator, you assign to it a managed object model (see initWithManagedObjectModel:); the coordinator uses that model to open persistent stores. You open a persistent store using addPersistentStoreWithType:configuration:URL:options:error:. How you use this method, however, depends on whether your application uses model versioning and on how you choose to support migration—whether you choose to use the default migration process or custom version skew detection and migration bootstrapping. The following list describes different scenarios and what you should do in each: ● Your application does not support versioning You use addPersistentStoreWithType:configuration:URL:options:error: directly. If for some reason the coordinator’s model is not compatible with the store schema (that is, the version hashes current model’s entities do not equal those in the store’s metadata), the coordinator detects this, generates an error, and addPersistentStoreWithType:configuration:URL:options:error: returns NO. You must deal with this error appropriately. ● Your application does support versioning and you choose to use either the lightweight or the default migration process You use addPersistentStoreWithType:configuration:URL:options:error: as described in “Lightweight Migration” (page 12) and “The Default Migration Process” (page 24) respectively. The fundamental difference from the non-versioned approach is that you instruct the coordinator to automatically migrate the store to the current model version by adding an entry to the options dictionary where the key is NSMigratePersistentStoresAutomaticallyOption and the value is an NSNumber object that represents YES. ● Your application does support versioning and you choose to use custom version skew detection and migration bootstrapping 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 23 Initiating the Migration ProcessBefore opening a store you use isConfiguration:compatibleWithStoreMetadata: to check whether its schema is compatible with the coordinator’s model: ● If it is, you use addPersistentStoreWithType:configuration:URL:options:error: to open the store directly; ● If it is not, you must migrate the store first then open it (again using addPersistentStoreWithType:configuration:URL:options:error:). You could simply use addPersistentStoreWithType:configuration:URL:options:error: to check whether migration is required, however this is a heavyweight operation and inefficient for this purpose. It is important to realize that there are two orthogonal concepts: 1. You can execute custom code during the migration. 2. You can have custom code for version skew detection and migration bootstrapping. The migration policy classes allow you to customize the migration of entities and properties in a number of ways, and these are typically all you need. You might, however, use custom skew detection and migration bootstrapping so that you can take control of the migration process. For example, if you have very large stores you could set up a migration manager with the two data models, and then use a series of mapping models to migrate your data into your destination store (if you use the same destination URL for each invocation, Core Data adds new objects to the existing store). This allows the framework (and you) to limit the amount of data in memory during the conversion process. The Default Migration Process To open a store and perform migration (if necessary), you use addPersistentStoreWithType:configuration:URL:options:error: and add to the options dictionary an entry where the key is NSMigratePersistentStoresAutomaticallyOption and the value is an NSNumber object that represents YES. Your code looks similar to the following example: Listing 6-1 Opening a store using automatic migration NSError *error; NSPersistentStoreCoordinator *psc = <#The coordinator#>; NSURL *storeURL = <#The URL of a persistent store#>; NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] Initiating the Migration Process The Default Migration Process 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 24forKey:NSMigratePersistentStoresAutomaticallyOption]; NSPersistentStore *store = [psc addPersistentStoreWithType:<#Store type#> configuration:<#Configuration or nil#> URL:storeURL options:optionsDictionary error:&error]; If the migration proceeds successfully, the existing store at storeURL is renamed with a “~” suffix before any file extension and the migrated store saved to storeURL. In its implementation of addPersistentStoreWithType:configuration:URL:options:error: Core Data does the following: 1. Tries to find a managed object model that it can use to open the store. Core Data searches through your application’s resources for models and tests each in turn. If it cannot find a suitable model, Core Data returns nil and a suitable error. 2. Tries to find a mapping model that maps from the managed object model for the existing store to that in use by the persistent store coordinator. Core Data searches through your application’s resources for available mapping models and tests each in turn. If it cannot find a suitable mapping, Core Data returns NO and a suitable error. Note that you must have created a suitable mapping model in order for this phase to succeed. 3. Creates instances of the migration policy objects required by the mapping model. Note that even if you use the default migration process you can customize the migration itself using custom migration policy classes. Initiating the Migration Process The Default Migration Process 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 25You only customize the migration process if you want to initiate migration yourself. You might do this to, for example, to search for models in locations other than the application’s main bundle, or to deal with large data sets by performing the migration in several passes using different mapping models (see “Multiple Passes—Dealing With Large Datasets” (page 29)). Is Migration Necessary Before you initiate a migration process, you should first determine whether it is necessary. You can check with NSManagedObjectModel’s isConfiguration:compatibleWithStoreMetadata: asillustrated in Listing 7-1 (page 26). Listing 7-1 Checking whether migration is necessary NSPersistentStoreCoordinator *psc = /* get a coordinator */ ; NSString *sourceStoreType = /* type for the source store, or nil if not known */ ; NSURL *sourceStoreURL = /* URL for the source store */ ; NSError *error = nil; NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:sourceStoreType URL:sourceStoreURL error:&error]; if (sourceMetadata == nil) { // deal with error } NSString *configuration = /* name of configuration, or nil */ ; NSManagedObjectModel *destinationModel = [psc managedObjectModel]; BOOL pscCompatibile = [destinationModel 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 26 Customizing the Migration ProcessisConfiguration:configuration compatibleWithStoreMetadata:sourceMetadata]; if (pscCompatibile) { // no need to migrate } Initializing a Migration Manager You initialize a migration manager using initWithSourceModel:destinationModel:; you therefore first need to find the appropriate model for the store. You get the model for the store using NSManagedObjectModel’s mergedModelFromBundles:forStoreMetadata:. If this returns a suitable model, you can create the migration manager as illustrated in Listing 7-2 (page 27) (this code fragment continues from Listing 7-1 (page 26)). Listing 7-2 Initializing a Migration Manager NSArray *bundlesForSourceModel = /* an array of bundles, or nil for the main bundle */ ; NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:bundlesForSourceModel forStoreMetadata:sourceMetadata]; if (sourceModel == nil) { // deal with error } MyMigrationManager *migrationManager = [[MyMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel]; Customizing the Migration Process Initializing a Migration Manager 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 27Performing a Migration You migrate a store using NSMigrationManager’s migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:. To use this method you need to marshal a number of parameters; most are straightforward, the only one that requires some work is the discovery of the appropriate mapping model (which you can retrieve using NSMappingModel’s mappingModelFromBundles:forSourceModel:destinationModel:method). This is illustrated in Listing 7-3 (page 28) (a continuation of the example shown in Listing 7-2 (page 27)). Listing 7-3 Performing a Migration NSArray *bundlesForMappingModel = /* an array of bundles, or nil for the main bundle */ ; NSError *error = nil; NSMappingModel *mappingModel = [NSMappingModel mappingModelFromBundles:bundlesForMappingModel forSourceModel:sourceModel destinationModel:destinationModel]; if (mappingModel == nil) { // deal with the error } NSDictionary *sourceStoreOptions = /* options for the source store */ ; NSURL *destinationStoreURL = /* URL for the destination store */ ; NSString *destinationStoreType = /* type for the destination store */ ; NSDictionary *destinationStoreOptions = /* options for the destination store */ ; BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL type:sourceStoreType options:sourceStoreOptions withMappingModel:mappingModel toDestinationURL:destinationStoreURL destinationType:destinationStoreType destinationOptions:destinationStoreOptions Customizing the Migration Process Performing a Migration 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 28error:&error]; Multiple Passes—Dealing With Large Datasets The basic approach shown above is to have the migration manager take two models, and then iterate over the steps (mappings) provided in a mapping model to move the data from one side to the next. Because Core Data performs a "three stage" migration—where it creates all of the data first, and then relates the data in a second stage—it must maintain “association tables" (which tell it which object in the destination store is the migrated version of which object in the source store, and vice-versa). Further, because it doesn't have a means to flush the contexts it is working with, it means you'll accumulate many objects in the migration manager as the migration progresses. In order to address this, the mapping model is given as a parameter of the migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error: call itself. What this means is that if you can segregate parts of your graph (as far as mappings are concerned) and create them in separate mapping models, you could do the following: 1. Get the source and destination data models 2. Create a migration manager with them 3. Find all of your mapping models, and put them into an array (in some defined order, if necessary) 4. Loop through the array, and call migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error: with each of the mappings This allows you to migrate "chunks" of data at a time, while not pulling in all of the data at once. From a "tracking/showing progress” point of view, that basically just creates another layer to work from, so you'd be able to determine percentage complete based on number of mapping models to iterate through (and then further on the number of entity mappings in a model you've already gone through). Customizing the Migration Process Multiple Passes—Dealing With Large Datasets 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 29If you are using iCloud, you can only migrate the contents of a store using automatic lightweight migration. To migrate a persistent store that is in iCloud, you add the store to a persistent store coordinator using addPersistentStoreWithType:configuration:URL:options:error: and pass at least the following options in the options dictionary: NSDictionary *optionsDictionary = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, <#Ubiquitous content name#>, NSPersistentStoreUbiquitousContentNameKey, nil]; Changes to a store are recorded and preserved independently for each model version that is associated with a given NSPersistentStoreUbiquitousContentNameKey. A persistent store configured with a given NSPersistentStoreUbiquitousContentNameKey only syncs data with a store on another device data if the model versions match. If you migrate a persistent store configured with a NSPersistentStoreUbiquitousContentNameKey option to a new model version, the store’s history of changes originating from the current device will also be migrated and then merged with any other devices configured with that new model version. Any changes from stores using the new version are also merged in. Existing changes can not, however, be migrated to a new model version if the migration is performed using a custom mapping model. 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 30 Migration and iCloudThis table describes the changes to Core Data Model Versioning and Data Migration Programming Guide . Date Notes 2012-01-09 Updated to describe use of migration with iCloud. 2010-02-24 Added further details to the section on Mapping Model Objects. 2009-06-04 Added an article to describe the lightweight migration feature. 2009-03-05 First version for iOS. 2008-02-08 Added a note about migrating stores from OS X v10.4 (Tiger). New document that describes managed object model versioning and Core Data migration. 2007-05-18 2012-01-09 | © 2012 Apple Inc. All Rights Reserved. 31 Document Revision HistoryApple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, Mac, OS X, Tiger, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. iCloud is a service mark of Apple Inc., registered in the U.S. and other countries. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. Kernel Programming GuideContents About This Document 9 Who Should Read This Document 9 Road Map 9 Other Apple Publications 11 Mach API Reference 11 Information on the Web 12 Keep Out 13 Why You Should Avoid Programming in the Kernel 13 Kernel Architecture Overview 14 Darwin 15 Architecture 16 Mach 17 BSD 18 I/O Kit 19 Kernel Extensions 19 The Early Boot Process 21 Boot ROM 21 The Boot Loader 21 Rooting 22 Security Considerations 24 Security Implications of Paging 25 Buffer Overflows and Invalid Input 26 User Credentials 27 Basic User Credentials 28 Access Control Lists 29 Remote Authentication 29 One-Time Pads 30 Time-based authentication 30 Temporary Files 31 /dev/mem and /dev/kmem 31 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 2Key-based Authentication and Encryption 32 Public Key Weaknesses 33 Using Public Keys for Message Exchange 35 Using Public Keys for Identity Verification 35 Using Public Keys for Data Integrity Checking 35 Encryption Summary 36 Console Debugging 36 Code Passing 37 Performance Considerations 39 Interrupt Latency 39 Locking Bottlenecks 40 Working With Highly Contended Locks 40 Reducing Contention by Decreasing Granularity 41 Code Profiling 42 Using Counters for Code Profiling 42 Lock Profiling 43 Kernel Programming Style 45 C++ Naming Conventions 45 Basic Conventions 45 Additional Guidelines 46 Standard C Naming Conventions 47 Commonly Used Functions 48 Performance and Stability Tips 50 Performance and Stability Tips 50 Stability Tips 52 Style Summary 52 Mach Overview 53 Mach Kernel Abstractions 53 Tasks and Threads 54 Ports, Port Rights, Port Sets, and Port Namespaces 55 Memory Management 57 Interprocess Communication (IPC) 58 IPC Transactions and Event Dispatching 59 Message Queues 59 Semaphores 59 Notifications 60 Locks 60 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 3 ContentsRemote Procedure Call (RPC) Objects 60 Time Management 60 Memory and Virtual Memory 61 OS X VM Overview 61 Memory Maps Explained 63 Named Entries 64 Universal Page Lists (UPLs) 65 Using Mach Memory Maps 66 Other VM and VM-Related Subsystems 68 Pagers 68 Working Set Detection Subsystem 69 VM Shared Memory Server Subsystem 69 Address Spaces 70 Background Info on PCI Address Translation 70 IOMemoryDescriptor Changes 71 VM System and pmap Changes: 72 Kernel Dependency Changes 72 Summary 72 Allocating Memory in the Kernel 73 Allocating Memory From a Non-I/O-Kit Kernel Extension 73 Allocating Memory From the I/O Kit 74 Allocating Memory In the Kernel Itself 75 Mach Scheduling and Thread Interfaces 77 Overview of Scheduling 77 Why Did My Thread Priority Change? 78 Using Mach Scheduling From User Applications 79 Using the pthreads API to Influence Scheduling 79 Using the Mach Thread API to Influence Scheduling 80 Using the Mach Task API to Influence Scheduling 83 Kernel Thread APIs 85 Creating and Destroying Kernel Threads 85 SPL and Friends 86 Wait Queues and Wait Primitives 87 Bootstrap Contexts 91 How Contexts Affect Users 92 How Contexts Affect Developers 93 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 4 ContentsI/O Kit Overview 94 Redesigning the I/O Model 94 I/O Kit Architecture 96 Families 96 Drivers 97 Nubs 97 Connection Example 98 For More Information 100 BSD Overview 101 BSD Facilities 102 Differences between OS X and BSD 103 For Further Reading 104 File Systems Overview 106 Working With the File System 106 VFS Transition 107 Network Architecture 108 Boundary Crossings 109 Security Considerations 110 Choosing a Boundary Crossing Method 110 Kernel Subsystems 111 Bandwidth and Latency 111 Mach Messaging and Mach Interprocess Communication (IPC) 112 Using Well-Defined Ports 113 Remote Procedure Calls (RPC) 113 Calling RPC From User Applications 116 BSD syscall API 116 BSD ioctl API 116 BSD sysctl API 117 General Information on Adding a sysctl 118 Adding a sysctl Procedure Call 118 Registering a New Top Level sysctl 121 Adding a Simple sysctl 122 Calling a sysctl From User Space 123 Memory Mapping and Block Copying 125 Summary 127 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 5 ContentsSynchronization Primitives 128 Semaphores 128 Condition Variables 130 Locks 132 Spinlocks 132 Mutexes 134 Read-Write Locks 136 Spin/Sleep Locks 138 Using Lock Functions 139 Miscellaneous Kernel Services 142 Using Kernel Time Abstractions 142 Obtaining Time Information 142 Event and Timer Waits 143 Handling Version Dependencies 145 Boot Option Handling 146 Queues 147 Installing Shutdown Hooks 148 Kernel Extension Overview 150 Implementation of a Kernel Extension (KEXT) 151 Kernel Extension Dependencies 151 Building and Testing Your Extension 152 Debugging Your KEXT 153 Installed KEXTs 154 Building and Debugging Kernels 155 Adding New Files or Modules 155 Modifying the Configuration Files 155 Modifying the Source Code Files 157 Building Your First Kernel 158 Building an Alternate Kernel Configuration 160 When Things Go Wrong: Debugging the Kernel 161 Setting Debug Flags in Open Firmware 161 Avoiding Watchdog Timer Problems 163 Choosing a Debugger 164 Using gdb for Kernel Debugging 164 Using ddb for Kernel Debugging 169 Bibliography 175 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 6 ContentsApple OS X Publications 175 General UNIX and Open Source Resources 175 BSD and UNIX Internals 176 Mach 177 Networking 178 Operating Systems 179 POSIX 179 Programming 179 Websites and Online Resources 180 Security and Cryptography 181 Document Revision History 182 Glossary 184 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 7 ContentsFigures, Tables, and Listings Kernel Architecture Overview 14 Figure 3-1 OS X architecture 14 Figure 3-2 Darwin and OS X 15 Figure 3-3 OS X kernel architecture 16 Kernel Programming Style 45 Table 7-1 Commonly used C functions 49 Mach Scheduling and Thread Interfaces 77 Table 10-1 Thread priority bands 77 Table 10-2 Thread policies 81 Table 10-3 Task roles 83 I/O Kit Overview 94 Figure 12-1 I/O Kit architecture 98 Synchronization Primitives 128 Listing 17-1 Allocating lock attributes and groups (lifted liberally from kern_time.c) 139 Building and Debugging Kernels 155 Table 20-1 Debugging flags 163 Table 20-2 Switch options in ddb 171 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 8The purpose of this document is to provide fundamental high-level information about the OS X core operating-system architecture. It also provides background for system programmers and developers of device drivers, file systems, and network extensions. In addition, it goes into detail about topics of interest to kernel programmers as a whole. This is not a document on drivers. It covers device drivers at a high level only. It does, however, cover some areas of interest to driver writers, such as crossing the user-kernel boundary. If you are writing device drivers, you should primarily read the document I/O Kit Fundamentals, but you may still find this document helpful as background reading. Who Should Read This Document This document has a wide and diverse audience—specifically, the set of potential system software developers for OS X, including the following sorts of developers: ● device-driver writers ● network-extension writers ● file-system writers ● developers of software that modifies file system data on-the-fly ● system programmers familiar with BSD, Linux, and similar operating systems ● developers who want to learn about kernel programming If you fall into one of these categories, you may find this document helpful. It is important to stress the care needed when writing code that resides in the kernel, however, as noted in “Keep Out” (page 13). Road Map The goal of this document is to describe the various major components of OS X at a conceptual level, then provide more detailed programming information for developers working in each major area. It is divided into several parts. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 9 About This DocumentThe first part is a kernel programming overview, which discusses programming guidelines that apply to all aspects of kernel programming. This includes issues such as security, SMP safety, style, performance, and the OS X kernel architecture as a whole. This part contains the chapters “Keep Out” (page 13), “Kernel Architecture Overview” (page 14), “The Early Boot Process” (page 21), “Security Considerations” (page 24), “Performance Considerations” (page 39), and “Kernel Programming Style” (page 45). The next part describes Mach and the bootstrap task, including information about IPC, bootstrap contexts, ports and port rights, and so on. This includes the chapters “Mach Overview” (page 53), “Memory and Virtual Memory” (page 61), “Mach Scheduling and Thread Interfaces” (page 77), and “Bootstrap Contexts” (page 91). The third part describes the I/O Kit and BSD. The I/O Kit is described at only a high level, since it is primarily of interest to driver developers. The BSD subsystem is covered in more detail, including descriptions of BSD networking and file systems. This includes the chapters “I/O Kit Overview” (page 94), “BSD Overview” (page 101), “File Systems Overview” (page 106), and “Network Architecture” (page 108). The fourth part describes kernelservices, including boundary crossings,synchronization, queues, clocks, timers, shutdown hooks, and boot option handling. This includes the chapters “Boundary Crossings” (page 109), “Synchronization Primitives” (page 128), and “Miscellaneous Kernel Services” (page 142). The fifth part explains how to build and debug the kernel and kernel extensions. This includes the chapters “Kernel Extension Overview” (page 150) and “Building and Debugging Kernels” (page 155). Each part begins with an overview chapter or chapters, followed by chapters that address particular areas of interest. The document ends with a glossary of terms used throughout the preceding chapters as well as a bibliography which provides numerous pointers to other reference materials. Glossary terms are highlighted in bold when first used. While most terms are defined when they first appear, the definitions are all in the glossary for convenience. If a term seems familiar, it probably means what you think it does. If it’s unfamiliar, check the glossary. In any case, all readers may want to skim through the glossary, in case there are subtle differences between OS X usage and that of other operating systems. The goal of this document is very broad, providing a firm grounding in the fundamentals of OS X kernel programming for developers from many backgrounds. Due to the complex nature of kernel programming and limitations on the length of this document, however, it is not always possible to provide introductory material for developers who do not have at least some background in their area of interest. It is also not possible to cover every detail of certain parts of the kernel. If you run into problems, you should join the appropriate Darwin discussion list and ask questions. You can find the lists at http://www.lists.apple.com/. For this reason, the bibliography contains high-level references that should help familiarize you with some of the basic concepts that you need to understand fully the material in this document. About This Document Road Map 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 10This document is, to a degree, a reference document. The introductory sections should be easily read, and we recommend that you do so in order to gain a general understanding of each topic. Likewise, the first part of each chapter, and in many cases, of sections within chapters, will be tailored to providing a general understanding of individual topics. However, you should not plan to read this document cover to cover, but rather, take note of topics of interest so that you can refer back to them when the need arises. Other Apple Publications This document, Kernel Programming , is part of the Apple Reference Library. Be sure to read the first document in the series, Mac Technology Overview, if you are not familiar with OS X. You can obtain other documents from the Apple Developer Documentation website at http://developer.apple.com/documentation. Mach API Reference If you plan to do extensive work inside the OS X kernel, you may find it convenient to have a complete Mach API reference, since this document only documents the most common and useful portions of the Mach API. In order to better understand certain interfaces, it may also be helpful to study the implementations that led up to those used in OS X, particularly to fill in gaps in understanding of the fundamental principles of the implementation. OS X is based on the Mach 3.0 microkernel, designed by Carnegie Mellon University, and later adapted to the Power Macintosh by Apple and the Open Software Foundation Research Institute (now part of Silicomp). This was known as osfmk, and was part of MkLinux (http://www.mklinux.org). Later, this and code from OSF’s commercial development efforts were incorporated into Darwin’s kernel. Throughout this evolutionary process, the Mach APIs used in OS X diverged in many ways from the original CMU Mach 3 APIs. You may find older versions of the Mach source code interesting, both to satisfy historical curiosity and to avoid remaking mistakes made in earlier implementations. MkLinux maintains an active CVS repository with their recent versions of Mach kernel source code. Older versions can be obtained through various Internet sites. You can also find CMU Mach white papers by searching for Mach on the CMU computer science department’s website (http://www.cs.cmu.edu), along with various source code samples. Up-to-date versions of the Mach 3 APIsthat OS X provides are described in the Mach API reference in the kernel sources. The kernel sources can be found in the xnu project on http://kernel.macosforge.org/. About This Document Other Apple Publications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 11Information on the Web Apple maintains several websites where developers can go for general and technical information on OS X. ● Apple Developer Connection: Developer Documentation (http://developer.apple.com/documentation). Features the same documentation that is installed on OS X, except that often the documentation is more up-to-date. Also includes legacy documentation. ● Apple Developer Connection: OS X (http://developer.apple.com/devcenter/mac/). Offers SDKs, release notes, product notes and news, and other resources and information related to OS X. ● AppleCare Tech Info Library (http://www.apple.com/support/). Contains technical articles, tutorials, FAQs, technical notes, and other information. About This Document Information on the Web 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 12This document assumes a broad general understanding of kernel programming concepts. There are many good introductory operating systems texts. This is not one of them. For more information on basic operating systems programming, you should consider the texts mentioned in the bibliography at the end of this document. Many developers are justifiably cautious about programming in the kernel. A decision to program in the kernel is not to be taken lightly. Kernel programmers have a responsibility to users that greatly surpasses that of programmers who write user programs. Why You Should Avoid Programming in the Kernel Kernel code must be nearly perfect. A bug in the kernel could cause random crashes, data corruption, or even render the operating system inoperable. It is even possible for certain errant operations to cause permanent and irreparable damage to hardware, for example, by disabling the cooling fan and running the CPU full tilt. Kernel programming is a black art that should be avoided if at all possible. Fortunately, kernel programming is usually unnecessary. You can write most software entirely in user space. Even most device drivers (FireWire and USB, for example) can be written as applications, rather than as kernel code. A few low-level drivers must be resident in the kernel's address space, however, and this document might be marginally useful if you are writing drivers that fall into this category. Despite parts of this document being useful in driver writing, this is not a document about writing drivers. In OS X, you write device drivers using the I/O Kit. While this document covers the I/O Kit at a conceptual level, the details of I/O Kit programming are beyond the scope of this document. Driver writers are encouraged to read I/O Kit Fundamentals for detailed information about the I/O Kit. This document covers most aspects of kernel programmingwith the exception of device drivers. Covered topics include scheduling, virtual memory pagers and policies, Mach IPC, file systems, networking protocol stacks, process and thread management, kernel security, synchronization, and a number of more esoteric topics. To summarize, kernel programming is an immense responsibility. You must be exceptionally careful to ensure that your code does not cause the system to crash, does not provide any unauthorized user accessto someone else’s files or memory, does not introduce remote or local root exploits, and does not cause inadvertent data loss or corruption. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 13 Keep OutOS X provides many benefits to the Macintosh user and developer communities. These benefits include improved reliability and performance, enhanced networking features, an object-based system programming interface, and increased support for industry standards. In creatingOS X, Apple has completely re-engineered the MacOS core operating system. Forming the foundation of OS X is the kernel. Figure 3-1 (page 14) illustrates the OS X architecture. Figure 3-1 OS X architecture Carbon Cocoa BSD Java (JDK) Classic BSD Core Services Kernel environment Application Services QuickTime Application environment The kernel provides many enhancements for OS X. These include preemption, memory protection, enhanced performance, improved networking facilities, support for both Macintosh (Extended and Standard) and non-Macintosh (UFS, ISO 9660, and so on) file systems, object-oriented APIs, and more. Two of these features, preemption and memory protection, lead to a more robust environment. In Mac OS 9, applications cooperate to share processor time. Similarly, all applications share the memory of the computer among them. Mac OS 9 is a cooperative multitasking environment. The responsiveness of all processes is compromised if even a single application doesn’t cooperate. On the other hand, real-time applications such as multimedia need to be assured of predictable, time-critical, behavior. In contrast, OS X is a preemptive multitasking environment. In OS X, the kernel provides enforcement of cooperation,scheduling processesto share time (preemption). Thissupportsreal-time behavior in applications that require it. In OS X, processes do not normally share memory. Instead, the kernel assigns each process its own address space, controlling access to these address spaces. This control ensures that no application can inadvertently access or modify another application’s memory (protection). Size is not an issue; with the virtual memory system included in OS X, each application has access to its own 4 GB address space. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 14 Kernel Architecture OverviewViewed together, all applications are said to run in user space, but this does not imply that they share memory. User space is simply a term for the combined address spaces of all user-level applications. The kernel itself has its own address space, called kernel space. In OS X, no application can directly modify the memory of the system software (the kernel). Although user processes do not share memory by default as in Mac OS 9, communication (and even memory sharing) between applications is still possible. For example, the kernel offers a rich set of primitives to permit some sharing of information among processes. These primitives include shared libraries, frameworks, and POSIX shared memory. Mach messaging provides another approach, handing memory from one process to another. Unlike Mac OS 9, however, memory sharing cannot occur without explicit action by the programmer. Darwin The OS X kernel is an Open Source project. The kernel, along with other core parts of OS X are collectively referred to as Darwin. Darwin is a complete operating system based on many of the same technologies that underlie OS X. However, Darwin does not include Apple’s proprietary graphics or applications layers, such as Quartz, QuickTime, Cocoa, Carbon, or OpenGL. Figure 3-2 (page 15) shows the relationship between Darwin and OS X. Both build upon the same kernel, but OS X adds Core Services, Application Services and QuickTime, as well as the Classic, Carbon, Cocoa, and Java (JDK) application environments. Both Darwin and OS X include the BSD command-line application environment; however, in OS X, use of environment is not required, and thus it is hidden from the user unless they choose to access it. Figure 3-2 Darwin and OS X Carbon Cocoa BSD Java (JDK) Classic BSD Core Services Kernel environment Application Services QuickTime Application environment Darwin technology is based on BSD, Mach 3.0, and Apple technologies. Best of all, Darwin technology is Open Source technology, which meansthat developers have full accessto the source code. In effect, OS X third-party developers can be part of the Darwin core system software development team. Developers can also see how Apple is doing thingsin the core operating system and adopt (or adapt) code to use within their own products. Refer to the Apple Public Source License (APSL) for details. Kernel Architecture Overview Darwin 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 15Because the same software forms the core of both OS X and Darwin, developers can create low-level software that runs on both OS X and Darwin with few, if any, changes. The only difference is likely to be in the way the software interacts with the application environment. Darwin is based on proven technology from many sources. A large portion of this technology is derived from FreeBSD, a version of 4.4BSD that offers advanced networking, performance,security, and compatibility features. Other parts of the system software, such as Mach, are based on technology previously used in Apple’s MkLinux project, in OS X Server, and in technology acquired from NeXT. Much of the code is platform-independent. All of the core operating-system code is available in source form. The core technologies have been chosen for several reasons. Mach provides a clean set of abstractions for dealing with memory management, interprocess(and interprocessor) communication (IPC), and other low-level operating-system functions. In today’s rapidly changing hardware environment, this provides a useful layer of insulation between the operating system and the underlying hardware. BSD is a carefully engineered, mature operating system with many capabilities. In fact, most of today’s commercial UNIX and UNIX-like operating systems contain a great deal of BSD code. BSD also provides a set of industry-standard APIs. New technologies,such asthe I/OKit and Network Kernel Extensions(NKEs), have been designed and engineered by Apple to take advantage of advanced capabilities,such asthose provided by an object-oriented programming model. OS X combines these new technologies with time-tested industry standards to create an operating system that is stable, reliable, flexible, and extensible. Architecture The foundation layer of Darwin and OS X is composed of several architectural components, as shown in Figure 3-3 (page 16). Taken together, these components form the kernel environment. Figure 3-3 OS X kernel architecture Common services Kernel environment Application environments Mach File system BSD Networking NKE Drivers I/O Kit Kernel Architecture Overview Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 16Important: Note that OS X uses the term kernel somewhat differently than you might expect. “A kernel, in traditional operating-system terminology, is a small nucleus of software that provides only the minimal facilities necessary for implementing additional operating-system services.” — from The Design and Implementation of the 4.4 BSD Operating System, McKusick, Bostic, Karels, and Quarterman, 1996. Similarly, in traditional Mach-based operating systems, the kernel refers to the Mach microkernel and ignores additional low-level code without which Mach does very little. In OS X, however, the kernel environment contains much more than the Mach kernel itself. The OS X kernel environment includes the Mach kernel, BSD, the I/O Kit, file systems, and networking components. These are often referred to collectively as the kernel. Each of these components is described briefly in the following sections. For further details, refer to the specific component chapters or to the reference material listed in the bibliography. Because OS X contains three basic components (Mach, BSD, and the I/O Kit), there are also frequently as many as three APIs for certain key operations. In general, the API chosen should match the part of the kernel where it is being used, which in turn is dictated by what your code is attempting to do. The remainder of this chapter describes Mach, BSD, and the I/O Kit and outlines the functionality that is provided by those components. Mach Mach manages processor resources such as CPU usage and memory, handles scheduling, provides memory protection, and provides a messaging-centered infrastructure to the rest of the operating-system layers. The Mach component provides ● untyped interprocess communication (IPC) ● remote procedure calls (RPC) ● scheduler support for symmetric multiprocessing (SMP) ● support for real-time services ● virtual memory support ● support for pagers ● modular architecture General information about Mach may be found in the chapter “Mach Overview” (page 53). Information about scheduling can be found in the chapter “Mach Scheduling and Thread Interfaces” (page 77). Information about the VM system can be found in “Memory and Virtual Memory” (page 61). Kernel Architecture Overview Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 17BSD Above the Mach layer, the BSD layer provides “OS personality” APIs and services. The BSD layer is based on the BSD kernel, primarily FreeBSD. The BSD component provides ● file systems ● networking (except for the hardware device level) ● UNIX security model ● syscall support ● the BSD process model, including process IDs and signals ● FreeBSD kernel APIs ● many of the POSIX APIs ● kernel support for pthreads (POSIX threads) The BSD component is described in more detail in the chapter “BSD Overview” (page 101). Networking OS X networking takes advantage of BSD’s advanced networking capabilities to provide support for modern features, such as Network Address Translation (NAT) and firewalls. The networking component provides ● 4.4BSD TCP/IP stack and socket APIs ● support for both IP and DDP (AppleTalk transport) ● multihoming ● routing ● multicast support ● server tuning ● packet filtering ● Mac OS Classic support (through filters) More information about networking may be found in the chapter “Network Architecture” (page 108). Kernel Architecture Overview Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 18File Systems OS X providessupport for numeroustypes of file systems, including HFS, HFS+, UFS, NFS, ISO 9660, and others. The default file-system type is HFS+; OS X boots (and “roots”) from HFS+, UFS, ISO, NFS, and UDF. Advanced features of OS X file systems include an enhanced Virtual File System (VFS) design. VFS provides for a layered architecture (file systems are stackable). The file system component provides ● UTF-8 (Unicode) support ● increased performance over previous versions of Mac OS. More information may be found in the chapter “File Systems Overview” (page 106). I/O Kit The I/O Kit provides a framework forsimplified driver development,supporting many categories of devices.The I/O Kit features an object-oriented I/O architecture implemented in a restricted subset of C++. The I/O Kit framework is both modular and extensible. The I/O Kit component provides ● true plug and play ● dynamic device management ● dynamic (“on-demand”) loading of drivers ● power management for desktop systems as well as portables ● multiprocessor capabilities The I/O Kit is described in greater detail in the chapter “I/O Kit Overview” (page 94). Kernel Extensions OS X provides a kernel extension mechanism as a means of allowing dynamic loading of pieces of code into kernel space, without the need to recompile. These pieces of code are known generically as plug-ins or, in the OS X kernel environment, as kernel extensions or KEXTs. Because KEXTs provide both modularity and dynamic loadability, they are a natural choice for any relatively self-contained service that requires access to interfaces that are not exported to user space. Many of the components of the kernel environment support this extension mechanism, though they do so in different ways. For example, some of the new networking features involve the use of network kernel extensions (NKEs). These are discussed in the chapter “Network Architecture” (page 108). Kernel Architecture Overview Kernel Extensions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 19The ability to dynamically add a new file-system implementation is based on VFS KEXTs. Device drivers and device familiesin the I/O Kit are implemented using KEXTs. KEXTs make development much easier for developers writing drivers or those writing code to support a new volume format or networking protocol. KEXTs are discussed in more detail in the chapter “Kernel Extension Overview” (page 150). Kernel Architecture Overview Kernel Extensions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 20Boot ROM When the power to a Macintosh computer is turned on, the BootROM firmware is activated. BootROM (which is part of the computer’s hardware) hastwo primary responsibilities: it initializessystem hardware and itselects an operating system to run. BootROM has two components to help it carry out these functions: ● POST (Power-On Self Test) initializes some hardware interfaces and verifies that sufficient memory is available and in a good state. ● EFI does basic hardware initialization and selects which operating system to use. If multiple installations of OS X are available, BootROM chooses the one that was last selected by the Startup Disk System Preference. The user can override this choice by holding down the Option key while the computer boots, which causes EFI to display a screen for choosing the boot volume. The Boot Loader Once BootROM is finished and an OS X partition has been selected, control passes to the boot.efi boot loader. The principal job of this boot loader is to load the kernel environment. As it does this, the boot loader draws the “booting” image on the screen. If full-disk encryption is enabled, the boot loader is responsible for drawing the login UI and prompting for the user’s password, which needed to accessthe encrypted disk to boot from it. (This UI is drawn by loginwindow otherwise.) In the simplest case, the boot loader can be found in the /System/Library/CoreServices directory on the root partition, in a file named boot.efi. Note: Booting from a UFS volume is deprecated as of OS X v10.5. In order to speed up boot time, the boot loader uses several caches. The contents and location of these caches varies between versions of OS X, but knowing some details about the caching may be helpful when debugging kernel extensions. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 21 The Early Boot ProcessAfter you install or modify a kernel extension, touch the /System/Library/Extensions directory; the system rebuilds the caches automatically. Important: You should not depend on the implementation details of the kernel caches in your software. In OS X v10.7, the boot loader looks for the unified prelinked kernel. This cache contains all kernel extensions that may be needed to boot a Mac with any hardware configuration, with the extensions already linked against the kernel. It islocated at /System/Library/Caches/com.apple.kext.caches/Startup/kernelcache. In OS X v10.6 and earlier, the boot loader first looks for the prelinked kernel (also called the kernel cache). This cache contains exactly the set of kernel extensions that were needed during the previous system startup, already linked against the kernel. If the prelinked kernel is missing or unusable (for example, because a hardware configuration has changed), the booter looks for the mkext cache, which contains all kernel extensions that may be needed to boot the system. Using the mkext cache is much slower because the linker must be run. On OS X v10.5 and v10.6, these caches are located in /System/Library/Caches/com.apple.kext.caches/Startup/; on previous versions of OS X, it was located at /System/Library/Caches/com.apple.kernelcaches/. Finally, if the caches cannot be used, the boot loader searches /System/Library/Extensions for drivers and other kernel extensions whose OSBundleRequired property is set to a value appropriate to the type of boot (for example, local or network boot). This process is very slow, because the Info.plist file of every kernel extension must be parsed, and then the linker must be run. For more information on how drivers are loaded, see I/O Kit Fundamentals, the manual page for kextcache, and Kernel Extension Programming Topics. Rooting Once the kernel and all drivers necessary for booting are loaded, the boot loaderstartsthe kernel’sinitialization procedure. At this point, enough drivers are loaded for the kernel to find the root device. The kernel initializes the Mach and BSD data structures and then initializes the I/O Kit. The I/O Kit links the loaded drivers into the kernel, using the device tree to determine which drivers to link. Once the kernel finds the root device, it roots(*) BSD off of it. The Early Boot Process Rooting 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 22Note: As a terminology aside, the term “boot” was historically reserved for loading a bootstrap loader and kernel off of a disk or partition. In more recent years, the usage has evolved to allow a second meaning: the entire process from initial bootstrap until the OS is generally usable by an end user. In this case, the term is used according to the former meaning. As used here, the term “root” refersto mounting a partition asthe root, or top-level, filesystem. Thus, while the OS boots off of the root partition, the kernel rootsthe OS off of the partition before executing startup scripts from it. Boot≠Root is a technology that allows the system to boot from a partition other than the root partition. This is used to boot systems where the root partition is encrypted using full-disk encryption, or where the root partition islocated on a device which requires additional drivers(such as a RAID array). Boot≠Root uses a helper partition to store the files needed to boot, such as the kernel cache. For more information on how to set up the property in a filter-scheme driver,see “Developing a Filter Scheme” in Mass StorageDeviceDriver Programming Guide . The Early Boot Process Rooting 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 23Kernel-level security can mean many things, depending on what kind of kernel code you are writing. This chapter points out some common security issues at the kernel or near-kernel level and where applicable, describes ways to avoid them. These issues are covered in the following sections: ● “Security Implications of Paging” (page 25) ● “Buffer Overflows and Invalid Input” (page 26) ● “User Credentials” (page 27) ● “Remote Authentication” (page 29) ● “Temporary Files” (page 31) ● “/dev/mem and /dev/kmem” (page 31) ● “Key-based Authentication and Encryption” (page 32) ● “Console Debugging” (page 36) ● “Code Passing” (page 37) Many of these issues are also relevant for application programming, but are crucial for programmers working in the kernel. Others are special considerations that application programers might not expect or anticipate. Note: The terms cleartext and plaintext both refer to unencrypted text. These terms can generally be used interchangeably, although in some circles, the term cleartext is restricted to unencrypted transmission across a network. However, in other circles, the term plaintext (orsometimes plain text) refers to plain ASCII text (as opposed to HTML or rich text. To avoid any potential confusion, this chapter will use the term cleartext to refer to unencrypted text. In order to understand security in OS X, it is important to understand that there are two security models at work. One of these is the kernel security model, which is based on users, groups, and very basic per-user and per-group rights, which are, in turn, coupled with access control lists for increased flexibility. The other is a user-level security model, which is based on keys, keychains, groups, users, password-based authentication, and a host of other details that are beyond the scope of this document. The user level of security contains two basic features that you should be aware of as a kernel programmer: Security Server and Keychain Manager. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 24 Security ConsiderationsThe Security Server consists of a daemon and various accesslibrariesfor caching permission to do certain tasks, based upon various means of authentication, including passwords and group membership. When a program requests permission to do something, the Security Server basically says “yes” or “no,” and caches that decision so that further requestsfrom that user (forsimilar actions within a single context) do not require reauthentication for a period of time. The Keychain Manager is a daemon that provides services related to the keychain, a central repository for a user’s encryption/authentication keys. For more high level information on keys,see “Key-based Authentication and Encryption” (page 32). The details of the user-level security model use are far beyond the scope of this document. However, if you are writing an application that requires services of this nature, you should consider taking advantage of the Security Server and Keychain Manager from the user-space portion of your application, rather than attempting equivalent services in the kernel. More information about these services can be found in Apple’s Developer Documentation website at http://developer.apple.com/documentation. Security Implications of Paging Paging has long been a major problem for security-conscious programmers. If you are writing a program that does encryption, the existence of even a small portion of the cleartext of a document in a backing store could be enough to reduce the complexity of breaking that encryption by orders of magnitude. Indeed, many types of data,such as hashes, unencrypted versions ofsensitive data, and authentication tokens, should generally not be written to disk due to the potential for abuse. This raises an interesting problem. There is no good way to deal with this in user space (unless a program is running as root). However, for kernel code, it is possible to prevent pages from being written out to a backing store. This process is referred to as “wiring down” memory, and is described further in “Memory Mapping and Block Copying” (page 125). The primary purpose of wired memory is to allow DMA-based I/O. Since hardware DMA controllers generally do not understand virtual addressing, information used in I/O must be physically in memory at a particular location and must not move until the I/O operation is complete. This mechanism can also be used to prevent sensitive data from being written to a backing store. Because wired memory can never be paged out (until it is unwired), wiring large amounts of memory has drastic performance repercussions, particularly on systems with small amounts of memory. For this reason, you should take care not to wire down memory indiscriminately and only wire down memory if you have a very good reason to do so. In OS X, you can wire down memory at allocation time or afterwards. To wire memory at allocation time: ● In I/O Kit, call IOMalloc and IOFree to allocate and free wired memory. Security Considerations Security Implications of Paging 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 25● In other kernel extensions, call OSMalloc and OSFree and pass a tag type whose flags are set to OSMT_DEFAULT. ● In user space code, allocate page-sized quantities with your choice of API, and then call mlock(2) to wire them. ● Inside the kernel itself (not in kernel extensions), you can also use kmem_alloc and related functions. For more information on wired memory, see “Memory Mapping and Block Copying” (page 125). Buffer Overflows and Invalid Input Buffer overflows are one of the more common bugs in both application and kernel programming. The most common cause is failing to allocate space for the NULL character that terminates a string in C or C++. However, user input can also cause buffer overflows if fixed-size input buffers are used and appropriate care is not taken to prevent overflowing these buffers. The most obvious protection, in this case, is the best one. Either don’t use fixed-length buffers or add code to reject or truncate input that overflows the buffer. The implementation details in either case depend on the type of code you are writing. For example, if you are working with strings and truncation is acceptable, instead of using strcpy, you should use strlcpy to limit the amount of data to copy. OS X provides length-limited versions of a number of string functions, including strlcpy, strlcat, strncmp, snprintf, and vsnprintf. If truncation of data is not acceptable, you must explicitly call strlen to determine the length of the input string and return an error if it exceeds the maximum length (one less than the buffer size). Other types of invalid input can be somewhat harder to handle, however. As a general rule, you should be certain that switch statements have a default case unless you have listed every legal value for the width of the type. A common mistake is assuming that listing every possible value of an enum type provides protection. An enum is generally implemented as either a char or an int internally. A careless or malicious programmer could easily pass any value to a kernel function, including those not explicitly listed in the type, simply by using a different prototype that defines the parameter as, for example, an int. Another common mistake is to assume that you can dereference a pointer passed to your function by another function. You should always check for null pointers before dereferencing them. Starting a function with int do_something(bufptr *bp, int flags) { Security Considerations Buffer Overflows and Invalid Input 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 26char *token = bp->b_data; isthe surest way to guarantee thatsomeone else will passin a null buffer pointer, either maliciously or because of programmer error. In a user program, this is annoying. In a file system, it is devastating. Security is particularly important for kernel code that draws input from a network. Assumptions about packet size are frequently the cause of security problems. Always watch for packets that are too big and handle them in a reasonable way. Likewise, always verify checksums on packets. This can help you determine if a packet was modified, damaged, or truncated in transit, though it is far from foolproof. If the validity of data from a network is of vital importance, you should use remote authentication, signing, and encryption mechanisms such as those described in “Remote Authentication” (page 29) and “Key-based Authentication and Encryption” (page 32). User Credentials As described in the introduction to this chapter, OS X has two different means of authenticating users. The user-levelsecurity model (including the Keychain Manager and the Security Server) is beyond the scope of this document. The kernel security model, however, is of greater interest to kernel developers, and is much more straightforward than the user-level model. The kernel security model is based on two mechanisms: basic user credentials and ACL permissions. The first, basic user credentials, are passed around within the kernel to identify the current user and group of the calling process. The second authentication mechanism, access control lists (ACLs), provides access control at a finer level of granularity. One of the most important things to remember when working with credentials is that they are per process, not per context. This is important because a process may not be running as the console user. Two examples of this are processes started from an ssh session (since ssh runs in the startup context) and setuid programs (which run as a different user in the same login context). It is crucial to be aware of these issues. If you are communicating with a setuid root GUI application in a user’s login context, and if you are executing another application or are reading sensitive data, you probably want to treat it as if it had the same authority as the console user, not the authority of the effective user ID caused by running setuid. This is particularly problematic when dealing with programs that run as setuid root if the console user is not in the admin group. Failure to perform reasonable checks can lead to major security holes down the road. However, this is not a hard and fast rule. Sometimes it is not obvious whether to use the credentials of the running process or those of the console user. In such cases, it is often reasonable to have a helper application show a dialog box on the console to require interaction from the console user. If this is not possible, a good Security Considerations User Credentials 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 27rule of thumb is to assume the lesser of the privileges of the current and console users, as it is almost always better to have kernel code occasionally fail to provide a needed service than to provide that service unintentionally to an unauthorized user or process. It is generally easier to determine the console user from a user space application than from kernel space code. Thus, you should generally do such checks from user space. If that is not possible, however, the variable console_user (maintained by the VFS subsystem) will give you the uid of the last owner of /dev/console (maintained by a bit of code in the chown system call). Thisis certainly not an idealsolution, but it does provide the most likely identity of the console user. Since this is only a “best guess,” however, you should use this only if you cannot do appropriate checking in user space. Basic User Credentials Basic user credentials used in the kernel are stored in a variable of type struct ucred. These are mostly used in specialized parts of the kernel—generally in places where the determining factor in permissions is whether or not the caller is running as the root user. This structure has four fields: ● cr_ref—reference count (used internally) ● cr_uid—user ID ● cr_ngroups—number of groups in cr_groups ● cr_groups[NGROUPS]—list of groups to which the user belongs Thisstructure has an internal reference counter to prevent unintentionally freeing the memory associated with it while it is still in use. For this reason, you should not indiscriminately copy this object but should instead either use crdup to duplicate it or use crcopy to duplicate it and (potentially) free the original. You should be sure to crfree any copies you might make. You can also create a new, empty ucred structure with crget. The prototypes for these functions follow: ● struct ucred *crdup(struct ucred *cr) ● struct ucred *crcopy(struct ucred *cr) ● struct ucred *crget(void) ● void crfree(struct ucred *cr) Security Considerations User Credentials 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 28Note: Functions for working with basic user credential are not exported outside of the kernel, and thus are not generally available to kernel extensions. Access Control Lists Access control lists are a new feature in OS X v10.4. Access control lists are primarily used in the file system portion of the OS X kernel, and are supported through the use of the kauth API. The kauth API is described in the header file /System/Library/Frameworks/Kernel.framework/Headers/sys/kauth.h. Because this API is still evolving, detailed documentation is not yet available. Remote Authentication This is one of the more difficult problems in computer security: the ability to identify someone connecting to a computer remotely. One of the mostsecure methodsisthe use of public key cryptography, which is described in more detail in “Key-based Authentication and Encryption” (page 32). However, many other means of authentication are possible, with varying degrees of security. Some other authentication schemes include: ● blind trust ● IP-only authentication ● password (shared secret) authentication ● combination of IP and password authentication ● one-time pads (challenge-response) ● time-based authentication Most of these are obvious, and require no further explanation. However, one-time pads and time-based authentication may be unfamiliar to many people outside security circles, and are thus worth mentioning in more detail. Security Considerations Remote Authentication 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 29One-Time Pads Based on the concept of “challenge-response” pairs, one-time pad (OTP) authentication requires that both parties have an identical list of pairs of numbers, words, symbols, or whatever, sorted by the first item. When trying to access a remote system, the remote system prompts the user with a challenge. The user finds the challenge in the first column, then sends back the matching response. Alternatively, this could be an automated exchange between two pieces of software. For maximum security, no challenge should ever be issued twice. For this reason, and because these systems were initially implemented with a paper pad containing challenge-response, or CR pairs, such systems are often called one-time pads. The one-time nature of OTP authentication makesit impossible forsomeone to guessthe appropriate response to any one particular challenge by a brute force attack (by responding to that challenge repeatedly with different answers). Basically, the only way to break such a system, short of a lucky guess, is to actually know some portion of the contents of the list of pairs. For this reason, one-time pads can be used over insecure communication channels. If someone snoops the communication, they can obtain that challenge-response pair. However, that information is of no use to them, since that particular challenge will never be issued again. (It does not even reduce the potential sample space for responses, since only the challenges must be unique.) Time-based authentication Thisis probably the least understood means of authentication, though it is commonly used by such technologies as SecurID. The concept isrelatively straightforward. You begin with a mathematical function that takes a small number of parameters (two, for example) and returns a new parameter. A good example of such a function is the function that generates the set of Fibonacci numbers (possibly truncated after a certain number of bits, with arbitrary initial seed values). Take this function, and add a third parameter, t, representing time in units of k seconds. Make the function be a generating function on t, with two seed values, a and b, where f(x,y) = (x + y) MOD (2 32 ) g(t) = a, 0 t k g(t) = b, k t 2k g(t) = f (g( log k t -2),g( log k t -1)) Security Considerations Remote Authentication 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 30In other words, every k seconds, you calculate a new value based on the previous two and some equation. Then discard the oldest value, replacing it with the second oldest value, and replace the second oldest value with the value that you just generated. As long as both ends have the same notion of the current time and the original two numbers, they can then calculate the most recently generated number and use this as a shared secret. Of course, if you are writing code that does this, you should use a closed form of this equation, since calculating Fibonacci numbers recursively without additional storage grows at O(2^(t/k)), which is not practical when t is measured in years and k is a small constant measured in seconds. The security ofsuch a scheme depends on various properties of the generator function, and the details ofsuch a function are beyond the scope of this document. For more information, you should obtain an introductory text on cryptography,. such as Bruce Schneier’s Applied Cryptography . Temporary Files Temporary files are a major source of security headaches. If a program does not set permissions correctly and in the right order, this can provide a means for an attacker to arbitrarily modify or read these files. The security impact of such modifications depends on the contents of the files. Temporary files are of much less concern to kernel programmers,since most kernel code does not use temporary files. Indeed, kernel code should generally not use files at all. However, many people programming in the kernel are doing so to facilitate the use of applicationsthat may use temporary files. Assuch, thisissue is worth noting. The most common problem with temporary files is that it is often possible for a malicious third party to delete the temporary file and substitute a different one with relaxed permissions in its place. Depending on the contents of the file, this could range from being a minor inconvenience to being a relatively large security hole, particularly if the file contains a shell script that is about to be executed with the permissions of the program’s user. /dev/mem and /dev/kmem One particularly painfulsurprise to people doing security programming in most UNIX or UNIX-like environments is the existence of /dev/mem and /dev/kmem. These device files allow the root user to arbitrarily access the contents of physical memory and kernel memory, respectively. There is absolutely nothing you can do to prevent this. From a kernel perspective, root is omnipresent and omniscient. If this is a security concern for your program, then you should consider whether your program should be used on a system controlled by someone else and take the necessary precautions. Security Considerations Temporary Files 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 31Note: Support for /dev/kmem is being phased out. It is not available on Intel-based Macintosh computers in OS X v10.4. In the future, it will be removed entirely. It is not possible to write device drivers that access PCI device memory through /dev/mem in OS X. If you need to support such a driver, you must write a kernel stub driver that matches against the device and mapsits memory space into the addressspace of the user process. For more information, read about user clients in I/O Kit Fundamentals. Key-based Authentication and Encryption Key-based authentication and encryption are ostensibly some of the more secure means of authentication and encryption, and can exist in many forms. The most common forms are based upon a shared secret. The DES, 3DES (triple-DES), IDEA, twofish, and blowfish ciphers are examples of encryption schemes based on a shared secret. Passwords are an example of an authentication scheme based on a shared secret. The idea behind most key-based encryption is that you have an encryption key of some arbitrary length that is used to encode the data, and that same key is used in the opposite manner (or in some cases, in the same manner) to decode the data. The problem with shared secret security is that the initial key exchange must occur in a secure fashion. If the integrity of the key is compromised during transmission, the data integrity is lost. This is not a concern if the key can be generated ahead of time and placed at both transport endpoints in a secure fashion. However, in many cases, this is not possible or practical because the two endpoints (be they physical devices or system tasks) are controlled by different people or entities. Fortunately, an alternative exists, known as zero-knowledge proofs. The concept of a zero-knowledge proof is that two seemingly arbitrary key values, x and y, are created, and that these values are related by some mathematical function ƒ in such a way that ƒ(ƒ(a,k1),k2) = a That is, applying a well-known function to the original cleartext using the first key results in ciphertext which, when that same function is applied to the ciphertext using the second key returns the original data. This is also reversible, meaning that ƒ(ƒ(a,k2),k1) = a Security Considerations Key-based Authentication and Encryption 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 32If the function f is chosen correctly, it is extremely difficult to derive x from y and vice-versa, which would mean that there is no function that can easily transform the ciphertext back into the cleartext based upon the key used to encode it. An example of this is to choose the mathematical function to be f(a,k)=((a*k) MOD 256) + ((a*k)/256) where a is a byte of cleartext, and k is some key 8 bits in length. This is an extraordinarily weak cipher, since the function f allows you to easily determine one key from the other, but it is illustrative of the basic concept. Pick k1 to be 8 and k2 to be 32. So for a=73, (a * 8)=584. This takes two bytes, so add the bits in the high byte to the bits of the low byte, and you get 74. Repeat this process with 32. This gives you 2368. Again, add the bits from the high byte to the bits of the low byte, and you have 73 again. This mathematical concept (with very different functions), when put to practical use, is known as public key (PK) cryptography, and forms the basis for RSA and DSA encryption. Public Key Weaknesses Public key encryption can be very powerful when used properly. However, it has a number of inherent weaknesses. A complete explanation of these weaknesses is beyond the scope of this document. However, it is important that you understand these weaknesses at a high level to avoid falling into some common traps. Some commonly mentioned weakness of public key cryptography include: ● Trust model for key exchange ● Pattern sensitivity ● Short data weakness Trust Models The most commonly discussed weakness of public key cryptography is the initial key exchange process itself. If someone manages to intercept a key during the initial exchange, he or she could instead give you his or her own public key and intercept messages going to the intended party. This is known as a man-in-the-middle attack. For such services as ssh, most people either manually copy the keys from one server to another or simply assume that the initial key exchange was successful. For most purposes, this is sufficient. In particularly sensitive situations, however, this is not good enough. For this reason, there is a procedure known as key signing. There are two basic models for key signing: the central authority model and the web of trust model. Security Considerations Key-based Authentication and Encryption 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 33The central authority model is straightforward. A central certifying agency signs a given key, and says that they believe the owner of the key is who he or she claims to be. If you trust that authority, then by association, you trust keys that the authority claims are valid. The web of trust model is somewhat different. Instead of a central authority, individuals sign keys belonging to other individuals. By signing someone’s key, you are saying that you trust that the person is really who he or she claims to be and that you believe that the key really belongs to him or her. The methods you use for determining that trust will ultimately impact whether others trust your signatures to be valid. There are many different ways of determining trust, and thus many groups have their own rulesfor who should and should not sign someone else’s key. Those rules are intended to make the trust level of a key depend on the trust level of the keys that have signed it. The line between central authorities and web of trust models is not quite as clear-cut as you might think, however. Many central authorities are hierarchies of authorities, and in some cases, they are actually webs of trust among multiple authorities. Likewise, many webs of trust may include centralized repositories for keys. While those repositories don’t provide any certification of the keys, they do provide centralized access. Finally, centralized authorities can easily sign keys as part of a web of trust. There are many websites that describe webs of trust and centralized certification schemes. A good general description of several such models can be found at http://world.std.com/~cme/html/web.html. Sensitivity to Patterns and Short Messages Existing public key encryption algorithms do a good job at encrypting semi-random data. They fallshort when encrypting data with certain patterns, as these patterns can inadvertently reveal information about the keys. The particular patterns depend on the encryption scheme. Inadvertently hitting such a pattern does not allow you to determine the private key. However, they can reduce the search space needed to decode a given message. Short data weakness is closely related to pattern sensitivity. If the information you are encrypting consists of a single number, for example the number 1, you basically get a value that is closely related mathematically to the public key. If the intent is to make sure that only someone with the private key can get the original value, you have a problem. In other words, public key encryption schemes generally do not encrypt all patterns equally well. For thisreason (and because public key cryptography tendsto be slower than single key cryptography), public keys are almost never used to encrypt end-user data. Instead, they are used to encrypt a session key. This session key is then used to encrypt the actual data using a shared secret mechanism such as 3DES, AES, blowfish, and so on. Security Considerations Key-based Authentication and Encryption 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 34Using Public Keys for Message Exchange Public key cryptography can be used in many ways. When both keys are private, it can be used to send data back and forth. However this use is no more useful than a shared secret mechanism. In fact, it is frequently weaker, for the reasons mentioned earlier in the chapter. Public key cryptography becomes powerful when one key is made public. Assume that Ernie and Bert want to send coded messages. Ernie gives Bert his public key. Assuming that the key was not intercepted and replaced with someone else’s key, Bert can now send data to Ernie securely, because data encrypted with the public key can only be decrypted with the private key (which only Ernie has). Bert uses this mechanism to send a shared secret. Bert and Ernie can now communicate with each other using a shared secret mechanism, confident in the knowledge that no third party has intercepted that secret. Alternately, Bert could give Ernie his public key, and they could both encrypt data using each other’s public keys, or more commonly by using those public keys to encrypt a session key and encrypting the data with that session key. Using Public Keys for Identity Verification Public key cryptography can also be used for verification of identity. Kyle wants to know if someone on the Internet who claims to be Stan is really Stan. A few months earlier, Stan handed Kyle his public key on a floppy disk. Thus, since Kyle already has Stan’s public key (and trusts the source of that key), he can now easily verify Stan’s identity. To achieve this, Kyle sends a cleartext message and asks Stan to encrypt it. Stan encrypts it with his private key. Kyle then uses Stan’s public key to decode the ciphertext. If the resulting cleartext matches, then the person on the other end must be Stan (unless someone else has Stan’s private key). Using Public Keys for Data Integrity Checking Finally, public key cryptography can be used for signing. Ahmed is in charge of meetings of a secret society called the Stupid Acronym Preventionists club. Abraham is a member of the club and gets a TIFF file containing a notice of their next meeting, passed on by way of a fellow member of the science club, Albert. Abraham is concerned, however, that the notice might have come from Bubba, who is trying to infiltrate the SAPs. Ahmed, however, was one step ahead, and took a checksum of the original message and encrypted the checksum with his private key, and sent the encrypted checksum as an attachment. Abraham used Ahmed’s public key to decrypt the checksum, and found that the checksum did not match that of the actual document. He wisely avoided the meeting. Isaac, however, was tricked into revealing himself as a SAP because he didn’t remember to check the signature on the message. Security Considerations Key-based Authentication and Encryption 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 35The moral of thisstory? One should always beware of geekssharing TIFFs—that is, if the security ofsome piece of data isimportant and if you do not have a direct,secure means of communication between two applications, computers, people, and so on, you must verify the authenticity of any communication using signatures, keys, or some other similar method. This may save your data and also save face. Encryption Summary Encryption is a powerful technique for keeping data secure if the initial key exchange occursin a secure fashion. One meansfor thisisto have a public key,stored in a well-known (and trusted) location. This allowsfor one-way encrypted communication through which a shared secret can be transferred for later two-way encrypted communication. You can use encryption not only for protecting data, but also for verifying the authenticity of data by encrypting a checksum. You can also use it to verify the identity of a client by requiring that the client encrypt some random piece of data as proof that the client holds the appropriate encryption key. Encryption, however, is not the final word in computer security. Because it depends on having some form of trusted key exchange, additional infrastructure is needed in order to achieve total security in environments where communication can be intercepted and modified. Console Debugging Warning: Failure to follow this advice can unintentionally expose security-critical information. In traditional UNIX and UNIX-like systems, the console is owned by root. Only root sees console messages. For this reason, print statements in the kernel are relatively secure. In OS X, any user can run the Console application. This represents a major departure from other UNIX-like systems. While it is never a good idea to include sensitive information in kernel debugging statements, it is particularly important not to do so in OS X. You must assume that any information displayed to the console could potentially be read by any user on the system (since the console is virtualized in the form of a user-viewable window). Printing any information involving sensitive data, including its location on disk or in memory, represents a security hole, however slight, and you should write your code accordingly. Obviously this is of less concern if that information is only printed when the user sets a debugging flag somewhere, but for normal use, printing potentially private information to the console is strongly discouraged. Security Considerations Console Debugging 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 36You must also be careful not to inadvertently print information that you use for generating password hashes or encryption keys, such as seed values passed to a random number generator. This is, by necessity, not a complete list of information to avoid printing to the console. You must use your own judgement when deciding whether a piece of information could be valuable if seen by a third party, and then decide if it is appropriate to print it to the console. Code Passing There are many ways of passing executable code into the kernel from user space. For the purposes of this section, executable code is not limited to compiled object code. It includes any instructions passed into the kernel that significantly affect control flow. Examples of passed-in executable code range from simple rules such as the filtering code uploaded in many firewall designs to bytecode uploads for a SCSI card. If it is possible to execute your code in user space, you should not even contemplate pushing code into the kernel. For the rare occasion where no other reasonable solution exists, however, you may need to pass some form of executable code into the kernel. This section explains some of the security ramifications of pushing code into the kernel and the level of verification needed to ensure consistent operation. Here are some guidelines to minimize the potential for security holes: 1. No raw object code. Direct execution of code passed in from user space is very dangerous. Interpreted languages are the only reasonable solution for this sort of problem, and even this is fraught with difficulty. Traditional machine code can’t be checked sufficiently to ensure security compliance. 2. Bounds checking. Since you are in the kernel, you are responsible for making sure that any uploaded code does not randomly access memory and does not attempt to do direct hardware access. You would normally make this a feature of the language itself, restricting access to the data element on which the bytecode is operating. 3. Termination checking. With very, very few exceptions, the language chosen should be limited to code that can be verified to terminate, and you should verify accordingly. If your driver is stuck in a tightly rolled loop, it is probably unable to do its job, and may impact overall system performance in the process. A language that does not allow (unbounded) loops (for example, allowing for but not while or goto could be one way to ensure termination. 4. Validity checking. Security Considerations Code Passing 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 37Your bytecode interpreter would be responsible for checking ahead for any potentially invalid operations and taking appropriate punitive actions against the uploaded code. For example, if uploaded code is allowed to do math, then proper protection must be in place to handle divide by zero errors. 5. Sanity checking. You should verify that the output is something remotely reasonable, if possible. It is not always possible to verify that the output is correct, but it is generally possible to create rules that prevent egregiously invalid output. For example, a network filter rule should output something resembling packets. If the checksums are bad, or if other information is missing or corrupt, clearly the uploaded code is faulty, and appropriate actions should be taken. It would be highly inappropriate for OS X to send out bad network traffic. In general, the more restrictive the language set, the lower the security risk. For example, interpreting simple network routing policies is less likely to be a security problem than interpreting packet rewriting rules, which is less likely to be an issue than running Java bytecode in the kernel. As with anything else, you must carefully weigh the potential benefits against the potential drawbacks and make the best decision given the information available. Security Considerations Code Passing 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 38Performance is a key aspect of any software system. Nowhere is this more true than in the kernel, where small performance problems tend to be magnified by repeated execution. For this reason, it is extremely important that your code be as efficient as possible. This chapter discusses the importance of low interrupt latency and fine-grained locking and tells you how to determine what portions of your code would benefit most from more efficient design. Interrupt Latency In OS X, you will probably never need to write code that runs in an interrupt context. In general, only motherboard hardware requires this. However, in the unlikely event that you do need to write code in an interrupt context, interrupt latency should be a primary concern. Interrupt latency refers to the delay between an interrupt being generated and an interrupt handler actually beginning to service that interrupt. In practice, the worst case interrupt latency is closely tied to the amount of time spent in supervisor mode (also called kernel mode) with interrupts off while handling some other interrupt. Low interrupt latency is necessary for reasonable overall performance, particularly when working with audio and video. In order to have reasonable soft real-time performance (for example, performance of multimedia applications), the interrupt latency caused by every device driver must be both small and bounded. OS X takes great care to bound and minimize interrupt latency for built-in drivers. It doesthis primarily through the use of interrupt service threads (also known as I/O service threads). When OS X takes an interrupt, the low-level trap handlers call up to a generic interrupt handling routine that clears the pending interrupt bit in the interrupt controller and calls a device-specific interrupt handler. That device-specific handler, in turn, sends a message to an interrupt service thread to notify it that an interrupt has occurred, and then the handler returns. When no further interrupts are pending, control returns to the currently executing thread. The next time the interrupt service thread is scheduled, it checks to see if an interrupt has occurred, then services the interrupt. As the name suggests, this actually is happening in a thread context, not an interrupt context. This design causes two major differences from traditional operating system design: ● Interrupt latency is near zero, since the code executing in an interrupt context is very small. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 39 Performance Considerations● It is possible for an interrupt to occur while a device driver is executing. This means that traditional (threaded) device drivers can be preempted and must use locking or other similar methods to protect any shared data (although they need to do so anyway to work on computers with multiple processors). This model is crucial to the performance of OS X. You should not attempt to circumvent this design by doing large amounts of work in an interrupt context. Doing so will be detrimental to the overall performance of the system. Locking Bottlenecks It is difficult to communicate data between multiple threads or between thread and interrupt contexts without using locking or other synchronization. This locking protects your data from getting clobbered by another thread. However, it also has the unfortunate side effect of being a potential bottleneck. In some types of communication (particularly n-way), locking can dramatically hinder performance by allowing only one thing to happen at a time. Read-write locks, discussed in “Synchronization Primitives” (page 128), can help alleviate this problem in the most common situation where multiple clients need to be able to read information but only rarely need to modify that data. However, there are many cases where read-write locks are not helpful. This section discusses some possible problems and ways of improving performance within those constraints. Working With Highly Contended Locks When many threads need to obtain a lock (or a small number of threads need to obtain a lock frequently), this lock is considered highly contended. Highly contended locks frequently represent faulty code design, but they are sometimes unavoidable. In those cases, the lock tends to become a major performance bottleneck. Take, for example, the issue of many-to-many communication that must be synchronized through a common buffer. While some improvement can be gained by using read-write locks instead of an ordinary mutex, the issue of multiple writers means that read-write locks still perform badly. One possible solution for this many-to-many communication problem is to break the lock up into multiple locks. Instead of sharing a single buffer for the communication itself, make a shared buffer that contains accounting information for the communication (for example, a list of buffers available for reading). Then assign each individual buffer its own lock. The readers might then need to check several locations to find the right data, but this still frequently yields better performance, since writers must only contend for a write lock while modifying the accounting information. Performance Considerations Locking Bottlenecks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 40Anothersolution for many-to-many communicationsisto eliminate the buffer entirely and communicate using message passing, sockets, IPC, RPC, or other methods. Yet another solution is to restructure your code in a way that the locking is unnecessary. This is often much more difficult. One method that is often helpful isto take advantage of flags and atomic increments, as outlined in the next paragraph. For simplicity, a single-writer, single-reader example is presented, but it is possible to extend this idea to more complicated designs. Take a buffer with some number of slots. Keep a read index and a write index into that buffer. When the write index and read index are the same, there is no data in the buffer. When writing, clear the next location. Then do an atomic increment on the pointer. Write the data. End by setting a flag at that new location that says that the data is valid. Note that this solution becomes much more difficult when dealing with multiple readers and multiple writers, and as such, is beyond the scope of this section. Reducing Contention by Decreasing Granularity One of the fundamental properties of locksis granularity. The granularity of a lock refersto the amount of code or data that it protects. A lock that protects a large block of code or a large amount of data is referred to as a coarse-grained lock, while a lock that protects only a small amount of code or data isreferred to as a fine-grained lock. A coarse-grained lock is much more likely to be contended (needed by one thread while being held by another) than a more finely grained lock. There are two basic ways of decreasing granularity. The first is to minimize the amount of code executed while a lock is held. For example, if you have code that calculates a value and stores it into a table, don’t take the lock before calling the function and release it after the function returns. Instead, take the lock in that piece of code right before you write the data, and release it as soon as you no longer need it. Of course, reducing the amount of protected code is not always possible or practical if the code needs to guarantee consistency where the value it is writing depends on other values in the table, since those values could change before you obtain the lock, requiring you to go back and redo the work. It is also possible to reduce granularity by locking the data in smaller units. In the above example, you could have a lock on each cell of the table. When updating cells in the table, you would start by determining the cells on which the destination cell depends, then lock those cells and the destination cell in some fixed order. (To avoid deadlock, you must always either lock cells in the same order or use an appropriate try function and release all locks on failure.) Once you have locked all the cells involved, you can then perform your calculation and release the locks, confident that no other thread has corrupted your calculations. However, by locking on a smaller unit of data, you have also reduced the likelihood of two threads needing to access the same cell. Performance Considerations Locking Bottlenecks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 41A slightly more radical version of this is to use read-write locks on a per-cell basis and always upgrade in a particular order. This is, however, rather extreme, and difficult to do correctly. Code Profiling Code profiling means determining how often certain pieces of code are executed. By knowing how frequently a piece of code is used, you can more accurately gauge the importance of optimizing that piece of code. There are a number of good tools for profiling user space applications. However, code profiling in the kernel is a very different beast, since it isn’t reasonable to attach to it like you would a running process. (It is possible by using a second computer, but even then, it is not a trivial task.) This section describes two useful ways of profiling your kernel code: counters and lock profiling. Any changes you make to allow code profiling should be done only during development. These are not the sort of changes that you want to release to end users. Using Counters for Code Profiling The first method of code profiling is with counters. To profile a section of code with a counter, you must first create a global variable whose name describesthat piece of code and initialize it to zero. You then add something like #ifdef PROFILING foo_counter++; #endif in the appropriate piece of code. If you then define PROFILING, that counter is created and initialized to zero, then incremented each time the code in question is executed. One small snag with this sort of profiling is the problem of obtaining the data. This can be done in several ways. The simplest is probably to install a sysctl, using the address of foo_counter as an argument. Then, you could simply issue the sysctl command from the command line and read or clear the variable. Adding a sysctl is described in more detail in “BSD sysctl API ” (page 117). In addition to using sysctl, you could also obtain the data by printing its value when unloading the module (in the case of a KEXT) or by using a remote debugger to attach to the kernel and directly inspecting the variable. However, a sysctl provides the most flexibility. With a sysctl, you can sample the value at any time, not just when the module is unloaded. The ability to arbitrarily sample the value makes it easier to determine the importance of a piece of code to one particular action. Performance Considerations Code Profiling 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 42If you are developing code for use in the I/O Kit, you should probably use your driver’s setProperties call instead of a sysctl. Lock Profiling Lock profiling is another useful way to find the cause of code inefficiency. Lock profiling can give you the following information: ● how many times a lock was taken ● how long the lock was held on average ● how often the lock was unavailable Put another way, this allows you to determine the contention of a lock, and in so doing, can help you to minimize contention by code restructuring. There are many different ways to do lock profiling. The most common way is to create your own lock calls that increment a counter and then call the real locking functions. When you move from debugging into a testing cycle before release, you can then replace the functions with defines to cause the actual functions to be called directly. For example, you might write something like this: extern struct timeval time; boolean_t mymutex_try(mymutex_t *lock) { int ret; ret=mutex_try(lock->mutex); if (ret) { lock->tryfailcount++; } return ret; } void mymutex_lock(mymutex_t *lock) { if (!(mymutex_try(lock))) { mutex_lock(lock->mutex); } lock->starttime = time.tv_sec; } void mymutex_unlock(mymutex_t *lock) { Performance Considerations Code Profiling 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 43lock->lockheldtime += (time.tv_sec - lock->starttime); lock->heldcount++; mutex_unlock(lock->mutex); } This routine has accuracy only to the nearest second, which is not particularly accurate. Ideally, you want to keep track of both time.tv_sec and time.tv_usec and roll the microseconds into seconds as the number gets large. From this information, you can obtain the average time the lock was held by dividing the total time held by the number of times it was held. It also tells you the number of times a lock was taken immediately instead of waiting, which is a valuable piece of data when analyzing contention. As with counter-based profiling, after you have written code to record lock use and contention, you must find a way to obtain that information. A sysctl is a good way of doing this, since it is relatively easy to implement and can provide a “snapshot” view of the data structure at any point in time. For more information on adding a sysctl, see “BSD sysctl API ” (page 117). Another way to do lock profiling isto use the built-in ETAP (Event Trace Analysis Package). This package consists of additional code designed for lock profiling. However, since this requires a kernel recompile, it is generally not recommended. Performance Considerations Code Profiling 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 44As described in “Keep Out” (page 13), programming in the kernel is fraught with hazards that can cause instability, crashes, or security holes. In addition to these issues, programming in the kernel has the potential for compatibility problems. If you program only to the interfaces discussed in this document or other Apple documents, you will avoid the majority of these. However, even limiting yourself to documented interfaces does not protect you from a handful of pitfalls. The biggest potential problem that you face is namespace collision, which occurs when your function, variable, or class name is the same as someone else’s. Since this makes one kernel extension or the other fail to load correctly (in a non-deterministic fashion), Apple has established function naming conventions for C and C++ code within the kernel. These are described in “Standard C Naming Conventions” (page 47) and “C++ Naming Conventions” (page 45), respectively. In addition to compatibility problems, kernel extensions that misbehave can also dramatically decrease the system’s overall performance or cause crashes. Some of these issues are described in “Performance and Stability Tips” (page 50). For more thorough coverage of performance and stability, you should also read the chapters “Security Considerations” (page 24) and “Performance Considerations” (page 39). C++ Naming Conventions Basic I/O Kit C++ naming conventions are defined in the document I/O Kit Device Driver Design Guidelines. This section refines those conventions in ways that should make them more useful to you as a programmer. Basic Conventions The primary conventions are as follows: ● Use the Java-style reverse DNS naming convention, substituting underscores for periods. For example, com_apple_foo. ● Avoid the following reserved prefixes: ● OS ● os ● IO ● io 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 45 Kernel Programming Style● Apple ● apple ● AAPL ● aapl This ensures that you will not collide with classes created by other companies or with future classes added to the operating system by Apple. It does not protect you from other projects created within your company, however, and for this reason, some additional guidelines are suggested. Additional Guidelines These additional guidelines are intended to minimize the chance of accidentally breaking your own software and to improve readability of code by developers. ● To avoid namespace collisions, you should prefix the names of classes and families with project names or other reasonably unique prefix codes. For example, if you are working on a video capture driver, and one of its classes is called capture, you will probably encounter a name collision eventually. Instead, you should name the class something like com_mycompany_driver_myproduct_capture. Similarly, names like To maximize readability, you should use macros to rename classes and families at compile time. For example: #define captureClass com_mycompany_driver_myproduct_capture #define captureFamily com_mycompany_iokit_myproduct_capture ● Use prefixes in function and method names to make it easier to see relationships between them. For example, Apple uses NS, CF, IO, and other prefixesto indicate that functions belong to specific frameworks. This might be as simple as prefixing a function with the name of the enclosing or related class, or it might be some other scheme that makes sense for your project. These are only suggested guidelines. Your company or organization should adopt its own set of guidelines within the constraints of the basic conventions described in the previous section. These guidelines should provide a good starting point. Kernel Programming Style C++ Naming Conventions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 46Standard C Naming Conventions The naming conventionsfor C++ have been defined forsome time in the document I/O Kit Device Driver Design Guidelines. However, no conventions have been given for standard C code. Because standard C has an even greater chance of namespace collision than C++, it is essential that you follow these guidelines when writing C code for use in the kernel. Because C does not have the benefit of classes, it is much easier to run into a naming conflict between two functions. For this reason, the following conventions are suggested: ● Declare all functions and (global) variables static where possible to prevent them from being seen in the global namespace. If you need to share these across files within your KEXT, you can achieve a similar effect by declaring them __private_extern__. ● Each function name should use Java-style reverse DNS naming. For example, if your company is apple.com, you should begin each function with com_apple_. ● Follow the reverse DNS name with the name of your project. For example, if you work at Apple and were working on project Schlassen, you would start each function name (in drivers) with com_apple_driver_schlassen_. Note: The term driver is reserved for actual device drivers. For families, you should instead use iokit. For example, if project Schlassen is an I/O Kit family, function namesshould all begin with com_apple_iokit_schlassen_. ● Use hierarchical names if you anticipate multiple projects with similar names coming from different parts of your company or organization. ● Use macro expansion to save typing, for example PROJECT_eat could expand to com_apple_driver_schlassen_pickle_eat. ● If you anticipate that the last part of a function name may be the same as the last part of another function name (for example, PROJECT1_eat and PROJECT2_eat), you should change the namesto avoid confusion (for example, PROJECT1_eatpickle and PROJECT2_eatburger). ● Avoid the following reserved prefixes: ● OS ● os ● IO ● io ● Apple ● apple Kernel Programming Style Standard C Naming Conventions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 47● AAPL ● aapl ● Avoid conflicting with any names already in the kernel, and do not use prefixes similar to those of existing kernel functions that you may be working with. ● Never begin a function name with an underscore (_). ● Under no circumstances should you use common names for your functions without prefixing them with the name of your project in some form. These are some examples of unacceptable names: ● getuseridentity ● get_user_info ● print ● find ● search ● sort ● quicksort ● merge ● console_log In short, picking any name that you would normally pick for a function is generally a bad idea, because every other developer writing code is likely to pick the same name for his or her function. Occasional conflicts are a fact of life. However, by following these few simple rules, you should be able to avoid the majority of common namespace pitfalls. Commonly Used Functions One of the most common problems faced when programming in the kernel is use of “standard” functions—things like printf or bcopy. Many commonly used standard C library functions are implemented in the kernel. In order to use them, however, you need to include the appropriate prototypes, which may be different from the user space prototypes for those functions, and which generally have different names when included from kernel code. In general, any non–I/O Kit header that you can safely include in the kernel is located in xnu/bsd/sys or xnu/osfmk/mach, although there are a few specialized headers in other places like libkern and libsa. Normal headers (those in /usr/include) cannot be used in the kernel. Kernel Programming Style Commonly Used Functions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 48Important: If you are writing an I/O Kit KEXT, most of these functions are not what you are looking for. The I/O Kit providesits own APIsfor these features, including IOLog, IOMemoryDescriptor, and IOLock. While using the lower-level functionality is not expressly forbidden, it is generally discouraged (though printf is always fine). For more information about APIs available to I/O Kit KEXTs, see Kernel Framework Reference . Table 7-1 (page 49) lists some commonly used C functions, variables, and types, and gives the location of their prototypes. Table 7-1 Commonly used C functions Function name Header path printf Buffer cache functions (bread, bwrite, and brelse) Directory entries Error numbers Kernel special variables Spinlocks malloc Queues Random number generator bzero, bcopy, copyin, and copyout timeout and untimeout Various time functions Standard type declarations User credentials OS and system information If the standard C function you are trying to use is not in one of these files, chances are the function is not supported for use within the kernel, and you need to implement your code in another way. Kernel Programming Style Commonly Used Functions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 49The symbols in these header files are divided among multiple symbol sets, depending on the technology area where they were designed to be used. To use these, you may have to declare dependencies on any of the following: ● com.apple.kernel—You should generally avoid this. ● com.apple.kernel.bsd—BSD portions of the kernel. ● com.apple.kernel.iokit—The I/O Kit. ● com.apple.kernel.libkern—General-purpose functions. ● com.apple.kernel.mach—Mach-specific APIs. ● com.apple.kpi.bsd—BSD portions of the kernel (v10.4 and later). ● com.apple.kernel.iokit—The I/O Kit (v10.4 and later). ● com.apple.kernel.libkern—General-purpose functions (v10.4 and later). ● com.apple.kernel.mach—Mach-specific APIs (v10.4 and later). ● com.apple.kpi.unsupported—Unsupported legacy functionality (v10.4 and later). Where possible, you should specify a dependency on the KPI version of these symbols. However, these symbols are only available in v10.4 and later. For the I/O Kit and libkern, this should make little difference. For other areas, such as network kernel extensions or file system KEXTs, you must use the KPI versions if you want your extension to load in OS X v10.4 and later. For a complete list of symbols in any of these dependencies, run nm on the binaries in /System/Library/Extensions/System.kext/PlugIns. Performance and Stability Tips This section includes some basic tips on performance and stability. You should read the sections on security and performance for additional information. These tips cover only style issues, not general performance or stability issues. Performance and Stability Tips Programming in the kernel is subject to a number of restrictions that do not exist in application programming. The first and most important is the stack size. The kernel has a limited amount of space allocated for thread stacks, which can cause problems if you aren’t aware of the limitation. This means the following: ● Recursion must be bounded (to no more than a few levels). ● Recursion should be rewritten as iterative routines where possible. Kernel Programming Style Performance and Stability Tips 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 50● Large stack variables(function local) are dangerous. Do not use them. This also appliesto large local arrays. ● Dynamically allocated variables are preferred (using malloc or equivalent) over local variables for objects more than a few bytes in size. ● Functions should have as few arguments as possible. ● Pass pointers to structures, not the broken out elements. ● Don’t use arguments to avoid using global or class variables. ● Do name global variables in a way that protects you from collision. ● C++ functions should be declared static. ● Functions not obeying these rules can cause a kernel panic, or in extreme cases, do not even compile. In addition to issues of stack size, you should also avoid doing anything that would generate unnecessary load such as polling a device or address. A good example is the use of mutexes rather than spinlocks. You should also structure your locks in such a way to minimize contention and to minimize hold times on the most highly contended locks. Also, since unused memory (and particularly wired memory) can cause performance degradation, you should be careful to deallocate memory when it is no longer in use, and you should never allocate large regions of wired memory. This may be unavoidable in some applications, but should be avoided whenever possible and disposed of at the earliest possible opportunity. Allocating large contiguous blocks of memory at boot time is almost never acceptable, because it cannot be released. There are a number of issues that you should consider when deciding whether to use floating point math or AltiVec vector math in the kernel. First, the kernel takes a speed penalty whenever floating-point math or AltiVec instructions are used in a system call context (or other similar mechanisms where a user thread executes in a kernel context), as floating-point and AltiVec registers are only maintained when they are in use. Note: In cases where altivec or floating point has already been used in user space in the calling thread, there is no additional penalty for using them in the kernel. Thus, for things like audio drivers, the above does not apply. In general, you should avoid doing using floating-point math or AltiVec instructions in the kernel unless doing so will result in a significant speedup. It is not forbidden, but is strongly discouraged. Second, AltiVec was not supported in the kernel prior to OS X v10.3. It was not possible to detect this support from within the kernel until a later 10.3 software update. If you must deploy your KEXT on earlier versions of OS X, you must either provide a non-AltiVec version of your code or perform the AltiVec instructions in user space. Kernel Programming Style Performance and Stability Tips 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 51Finally, AltiVec data stream instructions (dst, dstt, dstst, dss, and dssall) are not supported in the kernel, even for processors that support them in user space. Do not attempt to use them. If you decide to use AltiVec in the kernel, your code can determine whether the CPU supports AltiVec using the sysctlbyname call to get the hw.optional.altivec property. For more information, see “The sysctlbyname System Call” (page 123). Stability Tips ● Don’tsleep while holding resources(locks, for example). While thisis not forbidden, it isstrongly discouraged to avoid deadlock. ● Be careful to allocate and free memory with matching calls. For example, do not use allocation routines from the I/O Kit and deallocation routines from BSD. Likewise, do not use IOMallocContiguous with IOFreePageable. ● Use reference counts to avoid freeing memory that is still in use elsewhere. Be sure to deallocate memory when its reference count reaches zero, but not before. ● Lock objects before operating on them, even to change reference counts. ● Never dereference pointers without verifying that they are not NULL. In particular, never do this: int foo = *argptr; unless you have already verified that argptr cannot possibly be NULL. ● Test code in sections and try to think up likely edge cases for calculations. ● Never assume that your code will be run only on big endian processors. ● Never assume that the size of an instance of a type will never change. Always use sizeof if you need this information. ● Never assume that a pointer will always be the same size as an int or long. Style Summary Kernel programming style is very much a matter of personal preference, and it is not practical to programmatically enforce the guidelines in this chapter. However, we strongly encourage you to follow these guidelines to the maximum extent possible. These guidelines were created based on frequent problems reported by developers writing code in the kernel. No one can force you to use good style in your programming, but if you do not, you do so at your own peril. Kernel Programming Style Style Summary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 52The fundamental services and primitives of the OS X kernel are based on Mach 3.0. Apple has modified and extended Mach to better meet OS X functional and performance goals. Mach 3.0 was originally conceived as a simple, extensible, communications microkernel. It is capable of running as a stand–alone kernel, with other traditional operating-system servicessuch asI/O, file systems, and networking stacks running as user-mode servers. However, in OS X, Mach is linked with other kernel components into a single kernel address space. This is primarily for performance; it is much faster to make a direct call between linked components than it is to send messages or do remote procedure calls (RPC) between separate tasks. This modular structure results in a more robust and extensible system than a monolithic kernel would allow, without the performance penalty of a pure microkernel. Thusin OS X, Mach is not primarily a communication hub between clients and servers. Instead, its value consists of its abstractions, its extensibility, and its flexibility. In particular, Mach provides ● object-based APIs with communication channels (for example, ports) as object references ● highly parallel execution, including preemptively scheduled threads and support for SMP ● a flexible scheduling framework, with support for real-time usage ● a complete set of IPC primitives, including messaging, RPC, synchronization, and notification ● support for large virtual addressspaces,shared memory regions, and memory objects backed by persistent store ● proven extensibility and portability, for example across instruction set architectures and in distributed environments ● security and resource management as a fundamental principle of design; all resources are virtualized Mach Kernel Abstractions Mach provides a small set of abstractions that have been designed to be both simple and powerful. These are the main kernel abstractions: ● Tasks. The units of resource ownership; each task consists of a virtual addressspace, a portright namespace, and one or more threads. (Similar to a process.) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 53 Mach Overview● Threads. The units of CPU execution within a task. ● Address space. In conjunction with memory managers, Mach implements the notion of a sparse virtual address space and shared memory. ● Memory objects. The internal units of memory management. Memory objectsinclude named entries and regions; they are representations of potentially persistent data that may be mapped into address spaces. ● Ports. Secure, simplex communication channels, accessible only via send and receive capabilities (known as port rights). ● IPC. Message queues, remote procedure calls, notifications, semaphores, and lock sets. ● Time. Clocks, timers, and waiting. At the trap level, the interface to most Mach abstractions consists of messages sent to and from kernel ports representing those objects. The trap-level interfaces (such as mach_msg_overwrite_trap) and message formats are themselves abstracted in normal usage by the Mach Interface Generator (MIG). MIG is used to compile procedural interfaces to the message-based APIs, based on descriptions of those APIs. Tasks and Threads OS X processes and POSIX threads (pthreads) are implemented on top of Mach tasks and threads, respectively. A thread is a point of control flow in a task. A task exists to provide resources for the threads it contains. This split is made to provide for parallelism and resource sharing. A thread ● is a point of control flow in a task. ● has access to all of the elements of the containing task. ● executes (potentially) in parallel with other threads, even threads within the same task. ● has minimal state information for low overhead. A task ● is a collection ofsystem resources. These resources, with the exception of the addressspace, are referenced by ports. These resources may be shared with other tasks if rights to the ports are so distributed. ● provides a large, potentially sparse address space, referenced by virtual address. Portions of this space may be shared through inheritance or external memory management. ● contains some number of threads. Mach Overview Tasks and Threads 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 54Note that a task has no life of its own—only threads execute instructions. When it is said that “task Y does X,” what is really meant is that “a thread contained within task Y does X.” A task is a fairly expensive entity. It exists to be a collection of resources. All of the threads in a task share everything. Two tasks share nothing without an explicit action (although the action is often simple) and some resources (such as port receive rights) cannot be shared between two tasks at all. A thread is a fairly lightweight entity. It is fairly cheap to create and has low overhead to operate. This is true because a thread has little state information (mostly its register state). Its owning task bears the burden of resource management. On a multiprocessor computer, it is possible for multiple threads in a task to execute in parallel. Even when parallelism is not the goal, multiple threads have an advantage in that each thread can use a synchronous programming style, instead of attempting asynchronous programming with a single thread attempting to provide multiple services. A thread is the basic computational entity. A thread belongs to one and only one task that defines its virtual address space. To affect the structure of the address space or to reference any resource other than the address space, the thread must execute a special trap instruction that causesthe kernel to perform operations on behalf of the thread or to send a message to some agent on behalf of the thread. In general, these traps manipulate resources associated with the task containing the thread. Requests can be made of the kernel to manipulate these entities: to create them, delete them, and affect their state. Mach provides a flexible framework for thread–scheduling policies. Early versions of OS X support both time-sharing and fixed-priority policies. A time-sharing thread’s priority is raised and lowered to balance its resource consumption against other time-sharing threads. Fixed-priority threads execute for a certain quantum of time, and then are put at the end of the queue of threads of equal priority. Setting a fixed priority thread’s quantum level to infinity allows the thread to run until it blocks, or until it is preempted by a thread of higher priority. High priority real-time threads are usually fixed priority. OS X also provides time constraint scheduling for real-time performance. This scheduling allows you to specify that your thread must get a certain time quantum within a certain period of time. Mach scheduling is described further in “Mach Scheduling and Thread Interfaces” (page 77). Ports, Port Rights, Port Sets, and Port Namespaces With the exception of the task’s virtual address space, all other Mach resources are accessed through a level of indirection known as a port. A port is an endpoint of a unidirectional communication channel between a client who requests a service and a server who providesthe service. If a reply isto be provided to such a service request, a second port must be used. This is comparable to a (unidirectional) pipe in UNIX parlance. Mach Overview Ports, Port Rights, Port Sets, and Port Namespaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 55In most cases, the resource that is accessed by the port (that is, named by it) is referred to as an object. Most objects named by a port have a single receiver and (potentially) multiple senders. That is, there is exactly one receive port, and at least one sending port, for a typical object such as a message queue. The service to be provided by an object is determined by the manager that receives the request sent to the object. It follows that the kernel is the receiver for ports associated with kernel-provided objects and that the receiver for ports associated with task-provided objects is the task providing those objects. For ports that name task-provided objects, it is possible to change the receiver of requests for that port to a different task, for example by passing the port to that task in a message. A single task may have multiple ports that refer to resources it supports. For that matter, any given entity can have multiple ports that represent it, each implying different sets of permissible operations. For example, many objects have a name port and a control port (sometimes called the privileged port). Access to the control port allows the object to be manipulated; access to the name port simply names the object so that you can obtain information about it or perform other non-privileged operations against it. Tasks have permissions to access ports in certain ways (send, receive, send-once); these are called port rights. A port can be accessed only via a right. Ports are often used to grant clients access to objects within Mach. Having the right to send to the object’sIPC port denotesthe right to manipulate the object in prescribed ways. As such, port right ownership is the fundamental security mechanism within Mach. Having a right to an object is to have a capability to access or manipulate that object. Port rights can be copied and moved between tasks via IPC. Doing so, in effect, passes capabilities to some object or server. One type of object referred to by a port is a port set. As the name suggests, a port set is a set of port rights that can be treated as a single unit when receiving a message or event from any of the members of the set. Port sets permit one thread to wait on a number of message and event sources, for example in work loops. Traditionally in Mach, the communication channel denoted by a port was always a queue of messages. However, OS X supports additional types of communication channels, and these new types of IPC object are also represented by ports and port rights. See the section “Interprocess Communication (IPC)” (page 58), for more details about messages and other IPC types. Ports and port rights do not have systemwide names that allow arbitrary ports or rights to be manipulated directly. Ports can be manipulated by a task only if the task has a port right in its port namespace. A port right is specified by a port name, an integer index into a 32-bit port namespace. Each task has associated with it a single port namespace. Tasks acquire port rights when another task explicitly insertsthem into its namespace, when they receive rights in messages, by creating objects that return a right to the object, and via Mach calls for certain special ports (mach_thread_self, mach_task_self, and mach_reply_port.) Mach Overview Ports, Port Rights, Port Sets, and Port Namespaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 56Memory Management As with most modern operating systems, Mach provides addressing to large, sparse, virtual address spaces. Runtime access is made via virtual addresses that may not correspond to locations in physical memory at the initial time of the attempted access. Mach is responsible for taking a requested virtual address and assigning it a corresponding location in physical memory. It does so through demand paging. A range of a virtual address space is populated with data when a memory object is mapped into that range. All data in an addressspace is ultimately provided through memory objects. Mach asksthe owner of a memory object (a pager) for the contents of a page when establishing it in physical memory and returns the possibly modified data to the pager before reclaiming the page. OS X includes two built-in pagers—the default pager and the vnode pager. The default pager handles nonpersistent memory, known as anonymous memory. Anonymous memory is zero-initialized, and it exists only during the life of a task. The vnode pager maps files into memory objects. Mach exports an interface to memory objects to allow their contents to be contributed by user-mode tasks. This interface is known as the External Memory Management Interface, or EMMI. The memory management subsystem exports virtual memory handles known as named entries or named memory entries. Like most kernel resources, these are denoted by ports. Having a named memory entry handle allows the owner to map the underlying virtual memory object or to pass the right to map the underlying object to others. Mapping a named entry in two different tasks results in a shared memory window between the two tasks, thus providing a flexible method for establishing shared memory. Beginning in OS X v10.1, the EMMI system was enhanced to support “portless” EMMI. In traditional EMMI, two Mach ports were created for each memory region, and likewise two ports for each cached vnode. Portless EMMI, in its initial implementation, replaces this with direct memory references (basically pointers). In a future release, ports will be used for communication with pagers outside the kernel, while using direct references for communication with pagers that reside in kernel space. The net result of these changes is that early versions of portless EMMI do not support pagers running outside of kernel space. This support is expected to be reinstated in a future release. Addressranges of virtual memory space may also be populated through direct allocation (using vm_allocate). The underlying virtual memory object is anonymous and backed by the default pager. Shared ranges of an address space may also be set up via inheritance. When new tasks are created, they are cloned from a parent. This cloning pertains to the underlying memory address space as well. Mapped portions of objects may be inherited as a copy, or asshared, or not at all, based on attributes associated with the mappings. Mach practices a form of delayed copy known as copy-on-write to optimize the performance of inherited copies on task creation. Mach Overview Memory Management 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 57Rather than directly copying the range, a copy-on-write optimization is accomplished by protected sharing. The two tasks share the memory to be copied, but with read-only access. When either task attempts to modify a portion of the range, that portion is copied at that time. Thislazy evaluation of memory copiesis an important optimization that permits simplifications in several areas, notably the messaging APIs. One other form of sharing is provided by Mach, through the export of named regions. A named region is a form of a named entry, but instead of being backed by a virtual memory object, it is backed by a virtual map fragment. This fragment may hold mappings to numerous virtual memory objects. It is mappable into other virtual maps, providing a way of inheriting not only a group of virtual memory objects but also their existing mapping relationships. This feature offers significant optimization in task setup, for example when sharing a complex region of the address space used for shared libraries. Interprocess Communication (IPC) Communication between tasksis an important element of the Mach philosophy. Mach supports a client/server system structure in which tasks(clients) accessservices by making requests of other tasks(servers) via messages sent over a communication channel. The endpoints of these communication channels in Mach are called ports, while port rights denote permission to use the channel. The forms of IPC provided by Mach include ● message queues ● semaphores ● notifications ● lock sets ● remote procedure calls (RPCs) The type of IPC object denoted by the port determines the operations permissible on that port, and how (and whether) data transfer occurs. Important: The IPC facilities in OS X are in a state of transition. In early versions of the system, not all of these IPC types may be implemented. There are two fundamentally different Mach APIs for raw manipulation of ports—the mach_ipc family and the mach_msg family. Within reason, both families may be used with any IPC object; however, the mach_ipc calls are preferred in new code. The mach_ipc calls maintain state information where appropriate in order to support the notion of a transaction. The mach_msg calls are supported for legacy code but deprecated; they are stateless. Mach Overview Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 58IPC Transactions and Event Dispatching When a thread calls mach_ipc_dispatch, it repeatedly processes events coming in on the registered port set. These events could be an argument block from an RPC object (as the results of a client’s call), a lock object being taken (as a result of some other thread’s releasing the lock), a notification or semaphore being posted, or a message coming in from a traditional message queue. These events are handled via callouts from mach_msg_dispatch. Some events imply a transaction during the lifetime of the callout. In the case of a lock, the state is the ownership of the lock. When the callout returns, the lock is released. In the case of remote procedure calls, the state is the client’s identity, the argument block, and the reply port. When the callout returns, the reply is sent. When the callout returns, the transaction (if any) is completed, and the thread waits for the next event. The mach_ipc_dispatch facility is intended to support work loops. Message Queues Originally, the sole style of interprocess communication in Mach was the message queue. Only one task can hold the receive right for a port denoting a message queue. This one task is allowed to receive (read) messages from the port queue. Multiple tasks can hold rights to the port that allow them to send (write) messages into the queue. A task communicates with another task by building a data structure that contains a set of data elements and then performing a message-send operation on a port for which it holds send rights. At some later time, the task with receive rights to that port will perform a message-receive operation. A message may consist of some or all of the following: ● pure data ● copies of memory ranges ● port rights ● kernel implicit attributes, such as the sender’s security token The message transfer is an asynchronous operation. The message is logically copied into the receiving task, possibly with copy-on-write optimizations. Multiple threads within the receiving task can be attempting to receive messages from a given port, but only one thread can receive any given message. Semaphores Semaphore IPC objects support wait, post, and post all operations. These are counting semaphores, in that posts are saved (counted) if there are no threads currently waiting in that semaphore’s wait queue. A post all operation wakes up all currently waiting threads. Mach Overview Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 59Notifications Like semaphores, notification objects also support post and wait operations, but with the addition of a state field. The state is a fixed-size, fixed-format field that is defined when the notification object is created. Each post updates the state field; there is a single state that is overwritten by each post. Locks A lock is an object that provides mutually exclusive access to a critical section. The primary interfaces to locks are transaction oriented (see “IPC Transactions and Event Dispatching” (page 59)). During the transaction, the thread holds the lock. When it returns from the transaction, the lock is released. Remote Procedure Call (RPC) Objects As the name implies, an RPC object is designed to facilitate and optimize remote procedure calls. The primary interfaces to RPC objects are transaction oriented (see “IPC Transactions and Event Dispatching” (page 59)) When an RPC object is created, a set of argument block formats is defined. When an RPC (a send on the object) is made by a client, it causes a message in one of the predefined formats to be created and queued on the object, then eventually passed to the server (the receiver). When the server returns from the transaction, the reply isreturned to the sender. Mach triesto optimize the transaction by executing the server using the client’s resources; this is called thread migration. Time Management The traditional abstraction of time in Mach is the clock, which provides a set of asynchronous alarm services based on mach_timespec_t. There are one or more clock objects, each defining a monotonically increasing time value expressed in nanoseconds. The real-time clock is built in, and is the most important, but there may be other clocksfor other notions of time in the system. Clockssupport operationsto get the current time,sleep for a given period, set an alarm (a notification that is sent at a given time), and so forth. The mach_timespec_t API is deprecated in OS X. The newer and preferred API is based on timer objects that in turn use AbsoluteTime as the basic data type. AbsoluteTime is a machine-dependent type, typically based on the platform-native time base. Routines are provided to convert AbsoluteTime values to and from other data types,such as nanoseconds. Timer objectssupport asynchronous, drift-free notification, cancellation, and premature alarms. They are more efficient and permit higher resolution than clocks. Mach Overview Time Management 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 60This chapter describes allocating memory and the low-level routinesfor modifying memory mapsin the kernel. It also describes a number of commonly used interfaces to the virtual memory system. It does not describe how to make changes in paging policy or add additional pagers. OS X does not support external pagers, although much of the functionality can be achieved in other ways, some of which are covered at a high level in this chapter. The implementation details of these interfaces are subject to change, however, and are thus left undocumented. With the exception of the section “Allocating Memory in the Kernel” (page 73), this chapter is of interest only if you are writing file systems or are modifying the virtual memory system itself. OS X VM Overview The VM system used in OS X is a descendent of Mach VM, which was created at Carnegie Mellon University in the 1980s. To a large extent, the fundamental design is the same, although some of the details are different, particularly when enhancing the VM system. It does, however, support the ability to request certain paging behavior through the use of universal page lists (UPLs). See “Universal Page Lists (UPLs)” (page 65) for more information. The design of Mach VM centers around the concept of physical memory being a cache for virtual memory. At its highest level, Mach VM consists of address spaces and ways to manipulate the contents of those address spaces from outside the space. These address spaces are sparse and have a notion of protections to limit what tasks can access their contents. At a lower level, the object level, virtual memory is seen as a collection of VM objects and memory objects, each with a particular owner and protections. These objects can be modified with object callsthat are available both to the task and (via the back end of the VM) to the pagers. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 61 Memory and Virtual MemoryNote: While memory objects and VM objects are closely related, the terms are not equivalent and should not be confused. .A VM object can be backed by one or more memory objects, which are, in turn, managed by a pager. A VM object may also be partially backed by other VM objects, as occurs in the case of shadow chains (described later in this section). The VM object is internal to the virtual memory system, and includes basic information about accessing the memory. The memory object, by contrast, is provided by the pager. The contents of the memory associated with that memory object can be retrieved from disk or some other backing store by exchanging messages with the memory object. Implicitly, each VM object is associated with a given pager through its memory object. VM objects are cached with system pages (RAM), which can be any power of two multiple of the hardware page size. In the OS X kernel,system pages are the same size as hardware pages. Each system page isrepresented in a given address space by a map entry. Each map entry has its own protection and inheritance. A given map entry can have an inheritance of shared, copy, or none. If a page is marked shared in a given map, child tasks share this page for reading and writing. If a page is marked copy, child tasks get a copy of this page (using copy-on-write). If a page is marked none, the child’s page is left unallocated. VM objects are managed by the machine-independent VM system, with the underlying virtual to physical mappings handled by the machine-dependent pmap system. The pmap system actually handles page tables, translation lookaside buffers, segments, and so on, depending on the design of the underlying hardware. When a VM object is duplicated (for example, the data pages from a process that has just called fork), a shadow object is created. A shadow object isinitially empty, and contains a reference to another object. When the contents of a page are modified, the page is copied from the parent object into the shadow object and then modified. When reading data from a page, if that page exists in the shadow object, the page listed in the shadow object is used. If the shadow object has no copy of that page, the original object is consulted. A series of shadow objects pointing to shadow objects or original objects is known as a shadow chain. Shadow chains can become arbitrarily long if an object is heavily reused in a copy-on-write fashion. However, since fork is frequently followed by exec, which replaces all of the material being shadowed, long chains are rare. Further, Mach automatically garbage collectsshadow objects, removing any intermediate shadow objects whose pages are no longer referenced by any (nondefunct) shadow object. It is even possible for the original object to be released if it no longer contains pages that are relevant to the chain. The VM calls available to an application include vm_map and vm_allocate, which can be used to map file data or anonymous memory into the address space. This is possible only because the address space is initially sparse. In general, an application can either map a file into its address space (through file mapping primitives, abstracted by BSD) or it can map an object (after being passed a handle to that object). In addition, a task can change the protections of the objects in its address space and can share those objects with other tasks. Memory and Virtual Memory OS X VM Overview 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 62In addition to the mapping and allocation aspects of virtual memory, the VM system contains a number of other subsystems. These include the back end (pagers) and the shared memory subsystem. There are also other subsystems closely tied to VM, including the VM shared memory server. These are described in “Other VM and VM-Related Subsystems” (page 68). Memory Maps Explained Each Mach task has its own memory map. In Mach, this memory map takes the form of an ordered doubly linked list. As described in “OS X VM Overview” (page 61), each of these objects contains a list of pages and shadow references to other objects. In general, you should never need to access a memory map directly unless you are modifying something deep within the VM system. The vm_map_entry structure contains task-specific information about an individual mapping along with a reference to the backing object. In essence, it is the glue between an VM object and a VM map. While the details of this data structure are beyond the scope of this document, a few fields are of particular importance. The field is_submap is a Boolean value that tells whether this map entry is a normal VM object or a submap. A submap is a collection of mappings that is part of a larger map. Submaps are often used to group mappings together for the purpose ofsharing them among multiple Mach tasks, but they may be used for many purposes. What makes a submap particularly powerful is that when several tasks have mapped a submap into their address space, they can see each other’s changes, not only to the contents of the objects in the map, but to the objects themselves. This means that as additional objects are added to or deleted from the submap, they appear in or disappear from the address spaces of all tasks that share that submap. The field behavior controls the paging reference behavior of a specified range in a given map. This value changes how pageins are clustered. Possible values are VM_BEHAVIOR_DEFAULT, VM_BEHAVIOR_RANDOM, VM_BEHAVIOR_SEQUENTIAL, and VM_BEHAVIOR_RSEQNTL, for default,random,sequential, orreverse-sequential pagein ordering. The protection and max_protection fields control the permissions on the object. The protection field indicates what rights the task currently has for the object, while the max_protection field contains the maximum access that the current task can obtain for the object. You might use the protection field when debugging shared memory. By setting the protection to be read-only, any inadvertent writes to the shared memory would cause an exception. However, when the task actually needsto write to thatshared region, it could increase its permissionsin the protection field to allow writes. Memory and Virtual Memory Memory Maps Explained 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 63It would be a security hole if a task could increase its own permissions on a memory object arbitrarily, however. In order to preserve a reasonable security model, the task that owns a memory object must be able to limit the rights granted to a subordinate task. For this reason, a task is not allowed to increase its protection beyond the permissions granted in max_protection. Possible valuesfor protection and max_protection are described in detail in xnu/osfmk/mach/vm_prot.h. Finally, the use_pmap field indicates whether a submap’s low-level mappings should be shared among all tasksinto which the submap is mapped. If the mappings are notshared, then the structure of the map isshared among all tasks, but the actual contents of the pages are not. For example,shared libraries are handled with two submaps. The read-only shared code section has use_pmap set to true. The read-write (nonshared) section has use_pmap set to false, forcing a clean copy of the library’s DATA segment to be mapped in from disk for each new task. Named Entries The OS X VM system provides an abstraction known as a named entry. A named entry is nothing more than a handle to a shared object or a submap. Shared memory support in OS X is achieved by sharing objects between the memory maps of various tasks. Shared memory objects must be created from existing VM objects by calling vm_allocate to allocate memory in your address space and then calling mach_make_memory_entry_64 to get a handle to the underlying VM object. The handle returned by mach_make_memory_entry_64 can be passed to vm_map to map that object into a given task’s address space. The handle can also be passed via IPC or other means to other tasks so that they can map it into their address spaces. This provides the ability to share objects with tasks that are not in your direct lineage, and also allows you to share additional memory with tasks in your direct lineage after those tasks are created. The other form of named entry, the submap, is used to group a set of mappings. The most common use of a submap is to share mappings among multiple Mach tasks. A submap can be created with vm_region_object_create. What makes a submap particularly powerful is that when several tasks have mapped a submap into their address space, they can see each other’s changes to both the data and the structure of the map. This means that one task can map or unmap a VM object in another task’s addressspace simply by mapping or unmapping that object in the submap. Memory and Virtual Memory Named Entries 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 64Universal Page Lists (UPLs) A universal page list, or UPL, is a data structure used when communicating with the virtual memory system. UPLs can be used to change the behavior of pages with respect to caching, permissions, mapping, and so on. UPLs can also be used to push data into and pull data from VM objects. The term is also often used to refer to the family of routines that operate on UPLs. The flags used when dealing with UPLs are described in osfmk/mach/memory_object_types.h. The life cycle of a UPL looks like this: 1. A UPL is created based on the contents of a VM object. This UPL includes information about the pages within that object. 2. That UPL is modified in some way. 3. The changes to the UPL are either committed (pushed back to the VM system) or aborted, with ubc_upl_commit or ubc_upl_abort, respectively. If you have a control handle for a given VM object (which generally means that you are inside a pager), you can use vm_object_upl_request to get a UPL for that object. Otherwise, you must use the vm_map_get_upl call. In either case, you are left with a handle to the UPL. When a pagein is requested, the pager receives a list of pages that are locked against the object, with certain pages set to not valid. The pager must either write data into those pages or must abort the transaction to prevent invalid data in the kernel. Similarly in pageout, the kernel must write the data to a backing store or abort the transaction to prevent data loss. The pager may also elect to bring additional pages into memory or throw additional pages out of memory at its discretion. Because pagers can be used both for virtual memory and for memory mapping of file data, when a pageout is requested, the data may need to be freed from memory, or it may be desirable to keep it there and simply flush the changes to disk. For this reason, the flag UPL_CLEAN_IN_PLACE exists to allow a page to be flushed to disk but not removed from memory. When a pager decides to page in or out additional pages, it must determine which pages to move. A pager can request all of the dirty pages by setting the RETURN_ONLY_DIRTY flag. It can also request all pages that are not in memory using the RETURN_ONLY_ABSENT flag. There is a slight problem, however. If a given page is marked as BUSY in the UPL, a request for information on that page would normally block. If the pager is doing prefetching or preflushing, this is not desirable, since it might be blocking on itself or on some other pager that is blocked waiting for the current transaction to complete. To avoid such deadlock, the UPL mechanism provides the UPL_NOBLOCK flag. This is frequently used in the anonymous pager for requesting free memory. Memory and Virtual Memory Universal Page Lists (UPLs) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 65The flag QUERY_OBJECT_TYPE can be used to determine if an object is physically contiguous and to get other properties of the underlying object. The flag UPL_PRECIOUS means that there should be only one copy of the data. This prevents having a copy both in memory and in the backing store. However, this breaks the adjacency of adjacent pages in the backing store, and is thus generally not used to avoid a performance hit. The flag SET_INTERNAL is used by the BSD subsystem to cause all information about a UPL to be contained in a single memory object so that it can be passed around more easily. It can only be used if your code is running in the kernel’s address space. Since this handle can be used for multiple small transactions (for example, when mapping a file into memory block-by-block), the UPL API includes functions for committing and aborting changes to only a portion of the UPL. These functions are upl_commit_range and upl_abort_range, respectively. To aid in the use of UPLsfor handling multi-part transactions, the upl_commit_range and upl_abort_range calls have a flag that causes the UPL to be freed when there are no unmodified pages in the UPL. If you use this flag, you must be very careful not to use the UPL after all ranges have been committed or aborted. Finally, the function vm_map_get_upl is frequently used in file systems. It gets the underlying VM object associated with a given range within an address space. Since this returns only the first object in that range, it is your responsibility to determine whether the entire range is covered by the resulting UPL and, if not, to make additional calls to get UPLs for other objects. Note that while the vm_map_get_upl call is against an address space range, most UPL calls are against a vm_object. Using Mach Memory Maps Warning: Thissection describesthe low-level API for dealing with Mach VM maps. These maps cannot be modified in this way from a kernel extension. These functions are not available for use in a KEXT. They are presented strictly for use within the VM system and other parts of Mach. If you are not doing in-kernel development, you should be using the methods described in the chapter “Boundary Crossings” (page 109). From the context of the kernel (not from a KEXT), there are two maps that you will probably need to deal with. The first is the kernel map. Since your code is executing in the kernel’s address space, no additional effort is needed to use memory referenced in the kernel map. However, you may need to add additional mappings into the kernel map and remove them when they are no longer needed. Memory and Virtual Memory Using Mach Memory Maps 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 66The second map of interest is the memory map for a given task. This is of most interest for code that accepts input from user programs, for example a sysctl or a Mach RPC handler. In nearly all cases, convenient wrappers provide the needed functionality, however. Most of these functions are based around the vm_offset_t type, which is a pointer-sized integer. In effect, you can think of them as pointers, with the caveat that they are not necessarily pointers to data in the kernel’s address space, depending on usage. The low-level VM map API includes the following functions: kern_return_t vm_map_copyin(vm_map_t src_map, vm_offset_t src_addr, vm_size_t len, boolean_t src_destroy, vm_map_copy_t *copy_result); kern_return_t vm_map_copyout(vm_map_t map, vm_offset_t *addr, /* Out */ register vm_map_copy_t copy); kern_return_t vm_map_copy_overwrite(vm_map_t dst_map, vm_offset_t dst_address,vm_map_copy_t copy, boolean_t interruptible, pmap_t pmap); void vm_map_copy_discard(vm_map_copy_t copy); void vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, vm_prot_t access_type, boolean_t user_wire); void vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, boolean_t user_wire); The function vm_map_copyin copies data from an arbitrary (potentially non–kernel) memory map into a copy list and returns the copy list pointer in copy_result. If something goes wrong and you need to throw away this intermediate object, it should be freed with vm_map_copy_discard. In order to actually get the data from the copy list, you need to overwrite a memory object in the kernel’s address space with vm_map_copy_overwrite. This overwrites an object with the contents of a copy list. For most purposes, the value passed for interruptible should be FALSE, and pmap should be NULL. Memory and Virtual Memory Using Mach Memory Maps 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 67Copying data from the kernel to user space is exactly the same as copying data from user space, except that you pass kernel_map to vm_map_copyin and pass the user map to vm_map_copy_overwrite. In general, however, you should avoid doing this, since you could end up with a task’s memory being fragmented into lots of tiny objects, which is undesirable. Do not use vm_map_copyout when copying data into an existing user task’s address map. The function vm_map_copyout is used for filling an unused region in an address map. If the region is allocated, then vm_map_copyout does nothing. Because it requires knowledge of the current state of the map, it is primarily used when creating a new address map (for example, if you are manually creating a new process). For most purposes, you do not need to use vm_map_copyout. The functions vm_map_wire and vm_map_unwire can be used to wire and unwire portions of an address map. If you set the argument user_wire to TRUE, then the page can be unwired from user space. This should be set to FALSE if you are about to use the memory for I/O or for some other operation that cannot tolerate paging. In vm_map_wire, the argument access_type indicates the types of accesses that should not be allowed to generate a page fault. In general, however, you should be using vm_wire to wire memory. As mentioned earlier, this information is presented strictly for use in the heart of the kernel. You cannot use anything in this section from a kernel extension. Other VM and VM-Related Subsystems There are two additional VM subsystems: pagers and the working set detection subsystem. In addition, the VM shared memory server subsystem is closely tied to (but is not part of) the VM subsystem. This section describes these three VM and VM-related subsystems. Pagers OS X has three basic pagers: the vnode pager, the default pager (or anonymous pager), and the device pager. These are used by the VM system to actually get data into the VM objects that underlie named entries. Pagers are linked into the VM system through a combination of a subset of the old Mach pager interface and UPLs. The default pager is what most people think of when they think of a VM system. It is responsible for moving normal data into and out of the backing store. In addition, there is a facility known as the dynamic pager that sits on top of the default pager and handles the creation and deletion of backing store files. These pager files are filled with data in clusters (groups of pages). When the total fullness of the paging file pool reaches a high–water mark, the default pager asks the dynamic pager to allocate a new store file. When the pool drops below its low water mark, the VM system selects a pager file, moves its contents into other pager files, and deletes it from disk. Memory and Virtual Memory Other VM and VM-Related Subsystems 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 68The vnode pager has a 1:1 (onto) mapping between objects in VM space and open files (vnodes). It is used for memory mapped file I/O. The vnode pager is generally hidden behind calls to BSD file APIs. The device pager allows you to map non–general-purpose memory with the cache characteristics required for that memory (WIMG). Non–general–purpose memory includes physical addresses that are mapped onto hardware other than main memory—for example, PCI memory, frame buffer memory, and so on. The device pager is generally hidden behind calls to various I/O Kit functions. Working Set Detection Subsystem To improve performance, OS X has a subsystem known asthe working set detection subsystem. Thissubsystem is called on a VM fault; it keeps a profile of the fault behavior of each task from the time of its inception. In addition, just before a page request, the fault code asksthissubsystem which adjacent pagesshould be brought in, and then makes a single large request to the pager. Since files on disk tend to have fairly good locality, and since address space locality is largely preserved in the backing store, this provides a substantial performance boost. Also, since it is based upon the application’s previous behavior, it tends to pull in pages that would probably have otherwise been needed later. This occurs for all pagers. The working set code works well once it is established. However, without help, its performance would be the baseline performance until a profile for a given application has been developed. To overcome this, the first time that an application is launched in a given user context, the initial working set required to start the application is captured and stored in a file. From then on, when the application is started, that file is used to seed the working set. These working set files are established on a per-user basis. They are stored in /var/vm/app_profile and are only accessible by the super-user (and the kernel). VM Shared Memory Server Subsystem The VM shared memory server subsystem is a BSD service that is closely tied to VM, but is not part of VM. This server provides two submaps that are used for shared library support in OS X. Because shared libraries contain both read-only portions (text segment) and read-write portions (data segment), the two portions are treated separately to maximize efficiency. The read-only portions are completely shared between tasks, including the underlying pmap entries. The read-write portions share a common submap, but have different underlying data objects (achieved through copy-on-write). The three functions exported by the VM shared memory server subsystem should only be called by dyld. Do not use them in your programs. Memory and Virtual Memory Other VM and VM-Related Subsystems 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 69The function load_shared_file is used to load a new shared library into the system. Once such a file is loaded, other tasks can then depend on it, so a shared library cannot be unshared. However, a new set of shared regions can be created with new_system_shared_regions so that no new tasks will use old libraries. The function reset_shared_file can be used to reset any changes that your task may have made to its private copy of the data section for a file. Finally, the function new_system_shared_regions can be used to create a new set of shared regions for future tasks. New regions can be used when updating prebinding with new shared libraries to cause new tasks to see the latest libraries at their new locations in memory. (Users of old shared libraries will still work, but they will fall off the pre-bound path and will perform less efficiently.) It can also be used when dealing with private libraries that you want to share only with your task’s descendents. Address Spaces This section explains issues that some developers may see when using their drivers in Panther or later. These changes were necessitated by a combination of hardware and underlying OS changes; however, you may see problems resulting from the changes even on existing hardware. There are three basic areas of change in OS X v10.3. These are: ● IOMemoryDescriptor changes ● VM system (pmap) changes ● Kernel dependency changes These are described in detail in the sections that follow. Background Info on PCI Address Translation To allow existing device drivers to work with upcoming 64-bit system architectures, a number of changes were required. To explain these, a brief introduction to PCI bus bridges is needed. When a PCI device needs to perform a data transaction to or from main memory, the device driver calls a series of functions intended to prepare this memory for I/O. In an architecture where both the device drivers and the memory subsystem use 32-bit addressing, everything just works, so long as the memory doesn't get paged out during the I/O operation. As kernel memory is generally not pageable, the preparation islargely superfluous. On a system whose memory subsystem uses 64-bit addressing, however, this becomes a bit of a problem. Because the hardware devices on the PCI bus can only handle 32-bit addresses, the device can only “see” a 4 gigabyte aperture into the (potentially much larger) main memory at any given time. Memory and Virtual Memory Address Spaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 70There are two possible solutionsfor this problem. The easy (butslow)solution would be to use “bounce buffers”. In such a design, device drivers would copy data into memory specifically allocated within the bottom 4 gigs of memory. However, this incurs a performance penalty and also puts additional constraints on the lower 4 gigs of memory, causing numerous problems for the VM system. The other solution, the one chosen in Apple's 64-bit implementation, is to use address translation to “map” blocks of memory into the 32-bit address space of the PCI devices. While the PCI device can still only see a 4 gig aperture, that aperture can then be non-contiguous, and thus bounce buffers and other restrictions are unnecessary. This address translation is done using a part of the memory controller known as DART, which stands for Device Address Resolution Table. This introduces a number of potential problems, however. First, physical addresses as seen by the processor no longer map 1:1 onto the addresses as seen by PCI devices. Thus, a new term, I/O addresses, is introduced to describe this new view. Because I/O addresses and physical addresses are no longer the same, the DART must keep a table of translations to use when mapping between them. Fortunately, if your driver is written according to Apple guidelines (using only documented APIs), this process is handled transparently. Note: This additional addressing mode has an impact when debugging I/O Kit device drivers. For more information, see “When Things Go Wrong: Debugging the Kernel” (page 161). IOMemoryDescriptor Changes When your driver calls IOMemoryDescriptor::prepare, a mapping is automatically injected into the DART. When it calls IOMemoryDescriptor::release , the mapping is removed. If you fail to do this, your driver could experience random data corruption or panics. Because the DART requires different caching for reads and writes, the DMA direction is important on hardware that includes a DART. While you may receive random failuresif the direction is wrong in general (on any system), if you attempt to call WriteBytes on a memory region whose DMA direction is set up for reading, you will cause a kernel panic on 64-bit hardware. If you attempt to perform a DMA transaction to unwired (user) memory, on previous systems, you would only get random crashes, panics, and data corruption. On machines with a DART, you will likely get no data whatsoever. As a side-effect of changes in the memory subsystem, OS X is much more likely to return physically contiguous page ranges in memory regions. Historically, OS X returned multi-page memory regions in reverse order, starting with the last page and moving towards the first page. The result of this was that multi-page memory regions essentially never had a contiguous range of physical pages. Memory and Virtual Memory Address Spaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 71Because of the increased probability of seeing physically contiguous blocks of memory in a memory region, this change may expose latent bugs in some drivers that only show up when handling contiguous ranges of physical pages, which could result in incorrect behavior or panics. Note that the problems mentioned above are caused by bugs in the drivers, and could result in problems on older hardware prior to Panther. These issues are more likely to occur in Panther and later versions of OS X, however, because of the new hardware designs and the OS changes that were made to support those designs. VM System and pmap Changes: In Panther, as a result of the changes described in detail in the section on PCI address translation, physical addresses obtained directly from the pmap layer have no useful purpose outside the VM system itself. To prevent their inadvertent use in device drivers, the pmap calls are no longer available from kernel extensions. A few drivers written prior to the addition of the IOMemoryDescriptor class still use pmap calls to get the physical pages associated with a virtual address. Also, a few developers have looked at the IOMemoryDescriptor implementation and chosen to obtain addresses directly from the pmap layer to remove what was perceived as an unnecessary abstraction layer. Even without removing access to the pmap calls, these drivers would not function on systems with a DART (see the PCI section above for info on DARTs). To better emphasize this upcoming failure, Panther will cause these drivers to fail to load with an undefined symbol error (generally for pmap_extract ) even on systems without a DART. Kernel Dependency Changes Beginning in Panther, device drivers that declare a dependency on version 7 (the Panther version) of the I/O Kit will no longer automatically get symbols from Mach and BSD. This change was made to discourage I/O Kit developers from relying on symbols that are not explicitly approved for use in the I/O Kit. Existing drivers are unaffected by this change. This change only affects you if you explicitly modify your device driver to declare a dependency on version 7 of the I/O Kit to take advantage of new I/O Kit features. Summary As described above, some device drivers may require minor modifications to support Panther and higher. Apple has made every effort to ensure compatibility with existing device driversto the greatest extent possible, but a few drivers may break. If your driver breaks, you should first check to see if your driver includes any of the bugs described in the previous sections. If it does not, contact Apple Developer Technical Support for additional debugging suggestions. Memory and Virtual Memory Address Spaces 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 72Allocating Memory in the Kernel As with most things in the OS X kernel, there are a number of ways to allocate memory. The choice of routines depends both on the location of the calling routine and on the reason for allocating memory. In general, you should use Mach routines for allocating memory unless you are writing code for use in the I/O Kit, in which case you should use I/O Kit routines. Allocating Memory From a Non-I/O-Kit Kernel Extension The header defines the following routines for kernel memory allocation: ● OSMalloc—allocates a block of memory. ● OSMalloc_noblock—allocates a block of memory, but immediately returns NULL if the request would block. ● OSMalloc_nowait—same as OSMalloc_noblock. ● OSFree—releases memory allocated with any of the OSMalloc variants. ● OSMalloc_Tagalloc—allows you to create a unique tag for your memory allocations. You must create at least one tag before you can use any of the OSMalloc functions. ● OSMalloc_Tagfree—releases a tag allocated with OSMalloc_Tagalloc. (You must release all allocations associated with that tag before you call this function.) For example, to allocate and free a page of wired memory, you might write code like this: #include #define MYTAGNAME "com.apple.mytag" ... OSMallocTag mytag = OSMalloc_Tagalloc(MYTAGNAME, OSMT_DEFAULT); void *datablock = OSMalloc(PAGE_SIZE_64, mytag); ... OSFree(datablock, PAGE_SIZE_64, mytag); To allocate a page of pageable memory, pass OSMT_PAGEABLE instead of OSMT_DEFAULT in your call to OSMalloc_Tagalloc. Memory and Virtual Memory Allocating Memory in the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 73Allocating Memory From the I/O Kit Although the I/O Kit is generally beyond the scope of this document, the I/O Kit memory management routines are presented here for completeness. In general, I/O Kit routinesshould not be used outside the I/O Kit. Similarly, Mach allocation routines should not be directly used from the I/O Kit because the I/O Kit has abstractions for those routines that fit the I/O Kit development model more closely. The I/O Kit includes the following routines for kernel memory allocation: void *IOMalloc(vm_size_t size); void *IOMallocAligned(vm_size_t size, vm_size_t alignment); void *IOMallocContiguous(vm_size_t size, vm_size_t alignment, IOPhysicalAddress *physicalAddress); void *IOMallocPageable(vm_size_t size, vm_size_t alignment); void IOFree(void *address, vm_size_t size); void IOFreeAligned(void *address, vm_size_t size); void IOFreeContiguous(void *address, vm_size_t size); void IOFreePageable(void *address, vm_size_t size); Most of these routines are relatively transparent wrappers around the Mach allocation functions. There are two major differences, however. First, the caller does not need to know which memory map is being modified. Second, they have a separate free call for each allocation call for internal bookkeeping reasons. The functions IOMallocContiguous and IOMallocAligned differsomewhat fromtheir Mach underpinnings. IOMallocAligned uses calls directly to Mach VM to add support for arbitrary (power of 2) data alignment, rather than aligning based on the size of the object. IOMallocContiguous adds an additional parameter, PhysicalAddress. If this pointer is not NULL, the physical address is returned through this pointer. Using Mach functions, obtaining the physical address requires a separate function call. Memory and Virtual Memory Allocating Memory in the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 74Important: If your KEXT allocates memory that will be shared, you should create a buffer of type IOMemoryDescriptor or IOBufferMemoryDescriptor and specify that the buffer should be sharable. If you are allocating memory in a user application that will be shared with the kernel, you should use valloc or vm_allocate instead of malloc and then call mach_make_memory_entry_64. Allocating Memory In the Kernel Itself In addition to the routines available to kernel extensions, there are a number of other functions you can call to allocate memory when you are modifying the Mach kernel itself. Mach routines provide a relatively straightforward interface for allocating and releasing memory. They are the preferred mechanism for allocating memory outside of the I/O Kit. BSD also offers _MALLOC and _FREE, which may be used in BSD parts of the kernel. These routines do not provide for forced mapping of a given physical address to a virtual address. However, if you need such a mapping, you are probably writing a device driver, in which case you should be using I/O Kit routines instead of Mach routines. Most of these functions are based around the vm_offset_t type, which is a pointer-sized integer. In effect, you can think of them as pointers, with the caveat that they are not necessarily pointers to data in the kernel’s address space, depending on usage. These are some of the commonly used Mach routines for allocating memory: kern_return_t kmem_alloc(vm_map_t map, vm_offset_t *addrp, vm_size_t size); void kmem_free(vm_map_t map, vm_offset_t addr, vm_size_t size); kern_return_t mem_alloc_aligned(vm_map_t map, vm_offset_t *addrp, vm_size_t size); kern_return_t kmem_alloc_wired(vm_map_t map, vm_offset_t *addrp, vm_size_t size); kern_return_t kmem_alloc_pageable(vm_map_t map, vm_offset_t *addrp, vm_size_t size); kern_return_t kmem_alloc_contig(vm_map_t map, vm_offset_t *addrp, vm_size_t size, vm_offset_t mask, int flags); These functions all take a map as the first argument. Unless you need to allocate memory in a different map, you should pass kernel_map for this argument. Memory and Virtual Memory Allocating Memory in the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 75All of the kmem_alloc functions except kmem_alloc_pageable allocate wired memory. The function kmem_alloc_pageable creates the appropriate VM structures but does not back the region with physical memory. This function could be combined with vm_map_copyout when creating a new address map, for example. In practice, it is rarely used. The function kmem_alloc_aligned allocates memory aligned according to the value of the size argument, which must be a power of 2. The function kmem_alloc_wired is synonymous with kmem_alloc and is appropriate for data structures that cannot be paged out. It is not strictly necessary; however, if you explicitly need certain pieces of data to be wired, using kmem_alloc_wired makes it easier to find those portions of your code. The function kmem_alloc_contig attempts to allocate a block of physically contiguous memory. This is not always possible, and requires a full sort of the system free list even for short allocations. After startup, this sort can cause long delays, particularly on systems with lots of RAM. You should generally not use this function. The function kmem_free is used to free an object allocated with one of the kmem_alloc functions. Unlike the standard C free function, kmem_free requires the length of the object. If you are not allocating fixed-size objects (for example, sizeof struct foo), you may have to do some additional bookkeeping, since you must free an entire object, not just a portion of one. Memory and Virtual Memory Allocating Memory in the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 76OS X is based on Mach and BSD. Like Mach and most BSD UNIX systems, it contains an advanced scheduler based on the CMU Mach 3 scheduler. This chapter describes the scheduler from the perspective of both a kernel programmer and an application developer attempting to set scheduling parameters. This chapter begins with the “Overview of Scheduling” (page 77), which describes the basic concepts behind Mach scheduling at a high level, including real-time priority support. The second section, “Using Mach Scheduling From User Applications” (page 79), describes how to access certain key Mach scheduler routines from user applications and from other parts of the kernel outside the scheduler. The third section, “Kernel Thread APIs” (page 85), explains scheduler-related topics including how to create and terminate kernel threads and describes the BSD spl macros and their limited usefulness in OS X. Overview of Scheduling The OS X scheduler is derived from the scheduler used in OSFMK 7.3. In general, much documentation about prior implementations applies to the scheduler in OS X, although you will find numerous differences. The details of those differences are beyond the scope of this overview. Mach scheduling is based on a system of run queues at various priorities that are handled in different ways. The priority levels are divided into four bands according to their characteristics, as described in Table 10-1 (page 77). Table 10-1 Thread priority bands Priority Band Characteristics Normal normal application thread priorities System high priority threads whose priority has been raised above normal threads reserved for threads created inside the kernel that need to run at a higher priority than all user space threads (I/O Kit workloops, for example) Kernel mode only threads whose priority is based on getting a well-defined fraction of total clock cycles, regardless of other activity (in an audio player application, for example). Real-time threads 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 77 Mach Scheduling and Thread InterfacesThreads can migrate between priority levels for a number of reasons, largely as an artifact of the time sharing algorithm used. However, this migration is within a given band. Threads marked as being real-time priority are also special in the eyes of the scheduler. A real-time thread tells the scheduler that it needs to run for A cycles out of the next B cycles. For example, it might need to run for 3000 out of the next 7000 clock cyclesin order to keep up. It also tellsthe scheduler whether those cycles must be contiguous. Using long contiguous quanta is generally frowned upon but is occasionally necessary for specialized real-time applications. The kernel will make every effort to honor the request, but since this is soft real-time, it cannot be guaranteed. In particular, if the real-time thread requests something relatively reasonable, its priority will remain in the real-time band, but if it lies blatantly about its requirements and behaves in a compute-bound fashion, it may be demoted to the priority of a normal thread. Changing a thread’s priority to turn it into a real-time priority thread using Mach calls is described in more detail in “Using Mach Scheduling From User Applications” (page 79). In addition to the raw Mach RPC interfaces, some aspects of a thread’s priority can be controlled from user space using the POSIX thread priority API. The POSIX thread API is able to set thread priority only within the lowest priority band (0–63). For more information on the POSIX thread priority API, see “Using the pthreads API to Influence Scheduling” (page 79). Why Did My Thread Priority Change? There are many reasons that a thread’s priority can change. This section attempts to explain the root cause of these thread priority changes. A real-time thread, as mentioned previously, is penalized (and may even be knocked down to normal thread priority) if it exceeds its time quantum without blocking repeatedly. For this reason, it is very important to make a reasonable guess about your thread’s workload if it needs to run in the real-time band. Threadsthat are heavily compute-bound are given lower priority to help minimize response time for interactive tasksso that high–priority compute–bound threads cannot monopolize the system and prevent lower–priority I/O-bound threads from running. Even at a lower priority, the compute–bound threads still run frequently, since the higher–priority I/O-bound threads do only a short amount of processing, block on I/O again, then allow the compute-bound threads to execute. All of these mechanisms are operating continually in the Mach scheduler. This meansthat threads are frequently moving up or down in priority based upon their behavior and the behavior of other threads in the system. Mach Scheduling and Thread Interfaces Why Did My Thread Priority Change? 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 78Using Mach Scheduling From User Applications There are three basic ways to change how a user thread is scheduled. You can use the BSD pthreads API to change basic policy and importance. You can also use Mach RPC calls to change a task’s importance. Finally, you can use RPC calls to change the scheduling policy to move a thread into a different scheduling band. This is commonly used when interacting with CoreAudio. The pthreads API is a user space API, and has limited relevance for kernel programmers. The Mach thread and task APIs are more general and can be used from anywhere in the kernel. The Mach thread and task calls can also be called from user applications. Using the pthreads API to Influence Scheduling OS X supports a number of policies at the POSIX threads API level. If you need real-time behavior, you must use the Mach thread_policy_set call. This is described in “Using the Mach Thread API to Influence Scheduling” (page 80). The pthreads API adjuststhe priority of threads within a given task. It does not necessarily impact performance relative to threads in other tasks. To increase the priority of a task, you can use nice or renice from the command line or call getpriority and setpriority from your application. The API providestwo functions: pthread_getschedparam and pthread_setschedparam. Their prototypes look like this: pthread_setschedparam(pthread_t thread, int policy, struct sched_param *param); pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) The arguments for pthread_getschedparam are straightforward. The first argument is a thread ID, and the others are pointers to memory where the results will be stored. The argumentsto pthread_setschedparam are not as obvious, however. As with pthread_getschedparam, the first argument is a thread ID. The second argument to pthread_setschedparam is the desired policy, which can currently be one of SCHED_FIFO (first in, first out), SCHED_RR (round-robin), or SCHED_OTHER. The SCHED_OTHER policy is generally used for extra policies that are specific to a given operating system, and should thus be avoided when writing portable code. The third argument is a structure that contains various scheduling parameters. Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 79Here is a basic example of using pthreads functions to set a thread’s scheduling policy and priority. int set_my_thread_priority(int priority) { struct sched_param sp; memset(&sp, 0, sizeof(struct sched_param)); sp.sched_priority=priority; if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == -1) { printf("Failed to change priority.\n"); return -1; } return 0; } This code snippet sets the scheduling policy for the current thread to round-robin scheduling, and sets the thread’s relative importance within the task to the value passed in through the priority argument. For more information, see the manual page for pthread. Using the Mach Thread API to Influence Scheduling This API is frequently used in multimedia applications to obtain real-time priority. It is also useful in other situations when the pthread scheduling API cannot be used or does not provide the needed functionality. The API consists of two functions, thread_policy_set and thread_policy_get. kern_return_t thread_policy_set( thread_act_t thread, thread_policy_flavor_t flavor, thread_policy_t policy_info, mach_msg_type_number_t count); kern_return_t thread_policy_get( thread_act_t thread, thread_policy_flavor_t flavor, thread_policy_t policy_info, mach_msg_type_number_t *count, Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 80boolean_t *get_default); The parameters of these functions are roughly the same, except that the thread_policy_get function takes pointers for the count and the get_default arguments. The count is an inout parameter, meaning that it is interpreted as the maximum amount of storage (in units of int32_t) that the calling task has allocated for the return, but it is also overwritten by the scheduler to indicate the amount of data that was actually returned. These functions get and set several parameters, according to the thread policy chosen. The possible thread policies are listed in Table 10-2 (page 81). Table 10-2 Thread policies Policy Meaning THREAD_STANDARD_POLICY Default value THREAD_TIME_CONSTRAINT_POLICY Used to specify real-time behavior. Used to indicate the importance of computation relative to other threads in a given task. THREAD_PRECEDENCE_POLICY The following code snippet shows how to set the priority of a task to tell the scheduler that it needs real-time performance. The example values provided in comments are based on the estimated needs of esd (the Esound daemon). #include #include #include #include int set_realtime(int period, int computation, int constraint) { struct thread_time_constraint_policy ttcpolicy; int ret; thread_port_t threadport = pthread_mach_thread_np(pthread_self()); ttcpolicy.period=period; // HZ/160 ttcpolicy.computation=computation; // HZ/3300; ttcpolicy.constraint=constraint; // HZ/2200; ttcpolicy.preemptible=1; Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 81if ((ret=thread_policy_set(threadport, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&ttcpolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT)) != KERN_SUCCESS) { fprintf(stderr, "set_realtime() failed.\n"); return 0; } return 1; } The time values are in terms of Mach absolute time units. Since these values differ on different CPUs, you should generally use numbers relative to HZ (a global variable in the kernel that contains the current number of ticks per second). You can either handle this conversion yourself by dividing this value by an appropriate quantity or use the conversion routines described in “Using Kernel Time Abstractions ” (page 142). Say your computer reports 133 million for the value of HZ. If you pass the example values given as arguments to this function, your thread tells the scheduler that it needs approximately 40,000 (HZ/3300) out of the next 833,333 (HZ/160) bus cycles. The preemptible value (1) indicates that those 40,000 bus cycles need not be contiguous. However, the constraint value (HZ/2200) tells the scheduler that there can be no more than 60,000 bus cycles between the start of computation and the end of computation. Note: Because the constraint sets a maximum bound for computation, it must be larger than the value for computation. A straightforward example using this API is code that displays video directly to the framebuffer hardware. It needs to run for a certain number of cycles every frame to get the new data into the frame buffer. It can be interrupted without worry, but if it isinterrupted for too long, the video hardware starts displaying an outdated frame before the software writes the updated data, resulting in a nasty glitch. Audio has similar behavior, but since it is usually buffered along the way (in hardware and in software), there is greater tolerance for variations in timing, to a point. Another policy call is THREAD_PRECEDENCE_POLICY. This is used for setting the relative importance of non-real-time threads. Its calling convention issimilar, except that itsstructure is thread_precedence_policy, and contains only one field, an integer_t called importance. While thisis a signed 32-bit value, the minimum legal value is zero (IDLE_PRI). threads set to IDLE_PRI will only execute when no other thread is scheduled to execute. Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 82In general, larger values indicate higher priority. The maximum limit is subject to change, as are the priority bands, some of which have special purposes (such as real-time threads). Thus, in general, you should use pthreads APIs to achieve this functionality rather than using this policy directly unless you are setting up an idle thread. Using the Mach Task API to Influence Scheduling This relatively simple API is not particularly useful for most developers. However, it may be beneficial if you are developing a graphical user interface for Darwin. It also provides some insight into the prioritization of tasks in OS X. It is presented here for completeness. The API consists of two functions, task_policy_set and task_policy_get. kern_return_t task_policy_set( task_t task, task_policy_flavor_t flavor, task_policy_t policy_info, mach_msg_type_number_t count); kern_return_t task_policy_get( task_t task, task_policy_flavor_t flavor, task_policy_t policy_info, mach_msg_type_number_t *count, boolean_t *get_default); As with thread_policy_set and thread_policy_get, the parameters are similar, except that the task_policy_get function takes pointers for the count and the get_default arguments. The count argument is an inout parameter. It is interpreted as the maximum amount of storage that the calling task has allocated for the return, but it is also overwritten by the scheduler to indicate the amount of data that was actually returned. These functions get and set a single parameter, that of the role of a given task, which changes the way the task’s priority gets altered over time. The possible roles of a task are listed in Table 10-3 (page 83). Table 10-3 Task roles Role Meaning TASK_UNSPECIFIED Default value Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 83Role Meaning This is set when a process is executed with nice or is modified by renice. TASK_RENICED GUI application in the foreground. There can be more than one foreground application. TASK_FOREGROUND_APPLICATION TASK_BACKGROUND_APPLICATION GUI application in the background. TASK_CONTROL_APPLICATION Reserved for the dock or equivalent (assigned FCFS). TASK_GRAPHICS_SERVER Reserved for WindowServer or equivalent (assigned FCFS). The following code snippet shows how to set the priority of a task to tell the scheduler that it is a foreground application (regardless of whether it really is). #include #include #include int set_my_task_policy(void) { int ret; struct task_category_policy tcatpolicy; tcatpolicy.role = TASK_FOREGROUND_APPLICATION; if ((ret=task_policy_set(mach_task_self(), TASK_CATEGORY_POLICY, (thread_policy_t)&tcatpolicy, TASK_CATEGORY_POLICY_COUNT)) != KERN_SUCCESS) { fprintf(stderr, "set_my_task_policy() failed.\n"); return 0; } return 1; } Mach Scheduling and Thread Interfaces Using Mach Scheduling From User Applications 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 84Kernel Thread APIs The OS X scheduler provides a number of public APIs. While many of these APIs should not be used, the APIs to create, destroy, and alter kernel threads are of particular importance. While not technically part of the scheduler itself, they are inextricably tied to it. The scheduler directly provides certain services that are commonly associated with the use of kernel threads, without which kernel threads would be of limited utility. For example, the scheduler provides support for wait queues, which are used in various synchronization primitives such as mutex locks and semaphores. Creating and Destroying Kernel Threads The recommended interface for creating threads within the kernel is through the I/O Kit. It provides IOCreateThread, IOThreadSelf, and IOExitThread functions that make it relatively painless to create threads in the kernel. The basic functions for creating and terminating kernel threads are: IOThread IOCreateThread(IOThreadFunc function, void *argument); IOThread IOThreadSelf(void); void IOExitThread(void); With the exception of IOCreateThread (which is a bit more complex), the I/O Kit functions are fairly thin wrappers around Mach thread functions. The types involved are also very thin abstractions. IOThread is really the same as thread_t. The IOCreateThread function creates a new thread that immediately begins executing the function that you specify. It passes a single argument to that function. If you need to pass more than one argument, you should dynamically allocate a data structure and pass a pointer to that structure. For example, the following code creates a kernel thread and executes the function myfunc in that thread: #include #include #include struct mydata { int three; char *string; }; Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 85static void myfunc(void *myarg) { struct mydata *md = (struct mydata *)myarg; IOLog("Passed %d = %s\n", md->three, md->string); IOExitThread(); } void start_threads() { IOThread mythread; struct mydata *md = (struct mydata *)malloc(sizeof(*md)); md->three = 3; md->string = (char *)malloc(2 * sizeof(char)); md->string[0] = '3'; md->string[1] = '\0'; // Start a thread using IOCreateThread mythread = IOCreateThread(&myfunc, (void *)md); } One other useful function is thread_terminate. This can be used to destroy an arbitrary thread (except, of course, the currently running thread). This can be extremely dangerous if not done correctly. Before tearing down a thread with thread_terminate, you should lock the thread and disable any outstanding timers against it. If you fail to deactivate a timer, a kernel panic will occur when the timer expires. With that in mind, you may be able to terminate a thread as follows: thread_terminate(getact_thread(thread)); There thread is of type thread_t. In general, you can only be assured that you can kill yourself, not other threads in the system. The function thread_terminate takes a single parameter of type thread_act_t (a thread activation). The function getact_thread takes a thread shuttle (thread_shuttle_t) or thread_t and returns the thread activation associated with it. SPL and Friends BSD–based and Mach–based operating systems contain legacy functions designed for basic single-processor synchronization. These include functions such as splhigh, splbio, splx, and other similar functions. Since these functions are not particularly useful for synchronization in an SMP situation, they are not particularly useful as synchronization tools in OS X. Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 86If you are porting legacy code from earlier Mach–based or BSD–based operating systems, you must find an alternate means of providing synchronization. In many cases, this is as simple as taking the kernel or network funnel. In parts of the kernel, the use of spl functions does nothing, but causes no harm if you are holding a funnel (and results in a panic if you are not). In other parts of the kernel, spl macros are actually used. Because spl cannot necessarily be used for itsintended purpose, itshould not be used in general unless you are writing code it a part of the kernel that already uses it. You should instead use alternate synchronization primitives such as those described in “Synchronization Primitives” (page 128). Wait Queues and Wait Primitives The wait queue API is used extensively by the scheduler and is closely tied to the scheduler in itsimplementation. It is also used extensively in locks, semaphores, and other synchronization primitives. The wait queue API is both powerful and flexible, and as a result issomewhat large. Not all of the API is exported outside the scheduler, and parts are not useful outside the context of the wait queue functions themselves. This section documents only the public API. The wait queue API includes the following functions: void wait_queue_init(wait_queue_t wq, int policy); extern wait_queue_t wait_queue_t wait_queue_alloc(int policy); void wait_queue_free(wait_queue_t wq); void wait_queue_lock(wait_queue_t wq); void wait_queue_lock_try(wait_queue_t wq); void wait_queue_unlock(wait_queue_t wq); boolean_t wait_queue_member(wait_queue_t wq, wait_queue_sub_t wq_sub); boolean_t wait_queue_member_locked(wait_queue_t wq, wait_queue_sub_t wq_sub); kern_return_t wait_queue_link(wait_queue_t wq, wait_queue_sub_t wq_sub); kern_return_t wait_queue_unlink(wait_queue_t wq, wait_queue_sub_t wq_sub); kern_return_t wait_queue_unlink_one(wait_queue_t wq, wait_queue_sub_t *wq_subp); void wait_queue_assert_wait(wait_queue_t wq, event_t event, int interruptible); void wait_queue_assert_wait_locked(wait_queue_t wq, event_t event, int interruptible, boolean_t unlocked); kern_return_t wait_queue_wakeup_all(wait_queue_t wq, event_t event, int result); kern_return_t wait_queue_peek_locked(wait_queue_t wq, event_t event, thread_t *tp, wait_queue_t *wqp); Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 87void wait_queue_pull_thread_locked(wait_queue_t wq, thread_t thread, boolean_t unlock); thread_t wait_queue_wakeup_identity_locked(wait_queue_t wq, event_t event, int result, boolean_t unlock); kern_return_t wait_queue_wakeup_one(wait_queue_t wq, event_t event, int result); kern_return_t wait_queue_wakeup_one_locked(wait_queue_t wq, event_t event, int result, boolean_t unlock); kern_return_t wait_queue_wakeup_thread(wait_queue_t wq, event_t event, thread_t thread, int result); kern_return_t wait_queue_wakeup_thread_locked(wait_queue_t wq, event_t event, thread_t thread, int result, boolean_t unlock); kern_return_t wait_queue_remove(thread_t thread); Most of the functions and their arguments are straightforward and are not presented in detail. However, a few require special attention. Most of the functions take an event_t as an argument. These can be arbitrary 32-bit values, which leads to the potential for conflicting events on certain wait queues. The traditional way to avoid this problem is to use the address of a data object that is somehow related to the code in question as that 32-bit integer value. For example, if you are waiting for an event that indicates that a new block of data has been added to a ring buffer, and if that ring buffer’s head pointer was called rb_head, you might pass the value &rb_head as the event ID. Because wait queue usage does not generally cross address space boundaries, this is generally sufficient to avoid any event ID conflicts. Notice the functions ending in _locked. These functions require that your thread be holding a lock on the wait queue before they are called. Functions ending in _locked are equivalent to their nonlocked counterparts (where applicable) except that they do not lock the queue on entry and may not unlock the queue on exit (depending on the value of unlock). The remainder of this section does not differentiate between locked and unlocked functions. The wait_queue_alloc and wait_queue_init functions take a policy parameter, which can be one of the following: ● SYNC_POLICY_FIFO—first-in, first-out ● SYNC_POLICY_FIXED_PRIORITY—policy based on thread priority Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 88● SYNC_POLICY_PREPOST—keep track of number of wakeups where no thread was waiting and allow threadsto immediately continue executing without waiting until that count reaches zero. Thisisfrequently used when implementing semaphores. You should not use the wait_queue_init function outside the scheduler. Because a wait queue is an opaque object outside that context, you cannot determine the appropriate size for allocation. Thus, because the size could change in the future, you should always use wait_queue_alloc and wait_queue_free unless you are writing code within the scheduler itself. Similarly, the functions wait_queue_member, wait_queue_member_locked, wait_queue_link, wait_queue_unlink, and wait_queue_unlink_one are operations on subordinate queues, which are not exported outside the scheduler. The function wait_queue_member determines whether a subordinate queue is a member of a queue. The functions wait_queue_link and wait_queue_unlink link and unlink a given subordinate queue from its parent queue, respectively. The function wait_queue_unlink_one unlinks the first subordinate queue in a given parent and returns it. The function wait_queue_assert_wait causes the calling thread to wait on the wait queue until it is either interrupted (by a thread timer, for example) or explicitly awakened by another thread. The interruptible flag indicates whether this function should allow an asynchronous event to interrupt waiting. The function wait_queue_wakeup_all wakes up all threads waiting on a given queue for a particular event. The function wait_queue_peek_locked returns the first thread from a given wait queue that is waiting on a given event. It does not remove the thread from the queue, nor does it wake the thread. It also returns the wait queue where the thread was found. If the thread is found in a subordinate queue, other subordinate queues are unlocked, as is the parent queue. Only the queue where the thread was found remains locked. The function wait_queue_pull_thread_locked pulls a thread from the wait queue and optionally unlocks the queue. This is generally used with the result of a previous call to wait_queue_peek_locked. The function wait_queue_wakeup_identity_locked wakes up the first thread that is waiting for a given event on a given wait queue and starts it running but leaves the thread locked. It then returns a pointer to the thread. This can be used to wake the first thread in a queue and then modify unrelated structures based on which thread was actually awakened before allowing the thread to execute. The function wait_queue_wakeup_one wakes up the first thread that is waiting for a given event on a given wait queue. The function wait_queue_wakeup_thread wakes up a given thread if and only if it is waiting on the specified event and wait queue (or one of its subordinates). Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 89The function wait_queue_remove wakes a given thread without regard to the wait queue or event on which it is waiting. Mach Scheduling and Thread Interfaces Kernel Thread APIs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 90In OS X kernel programming, the term context has several meanings that appear similar on the surface, but differ subtly. First, the term context can refer to a BSD process or Mach task. Switching from one process to another is often referred to as a context switch. Second, context can refer to the part of the operating system in which your code resides. Examples of this include thread contexts, the interrupt context, the kernel context, an application’s context, a Carbon File Manager context, and so on. Even for this use of the term, the exact meaning depends, ironically, on the context in which the term is used. Finally, context can refer to a bootstrap context. In Mach, the bootstrap task is assigned responsibility for looking up requests for Mach ports. As part of this effort, each Mach task is registered in one of two groups—either in the startup context or a user’s login context. (In theory, Mach can support any number of independent contexts, however the use of additional contexts is beyond the scope of this document.) For the purposes of this chapter, the term context refers to a bootstrap context. When OS X first boots, there is only the top-level context, which is generally referred to as the startup context. All other contexts are subsets of this context. Basic system services that rely on Mach ports must be started in this context in order to work properly. When a user logs in, the bootstrap task creates a new context called the login context. Programs run by the user are started in the login context. This allows the user to run a program that provides an alternate port lookup mechanism if desired, causing that user’s tasks to get a different port when the tasks look up a basic service. This has the effect of replacing that service with a user-defined version in a way that changes what the user’s tasks see, but does not affect any of the rest of the system. To avoid wasting memory, currently the login context is destroyed when the user logs out (orshortly thereafter). This behavior may change in the future, however. In the current implementation, programs started by the user will no longer be able to look up Mach ports after logout. If a program does not need to do any port lookup, it will not be affected. Other programs will terminate, hang, or behave erratically. For example, in Mac OS 10.1 and earlier, sshd continuesto function when started from a user context. However, since it is unable to communicate with lookupd or netinfo, it stops accepting passwords. This is not a particularly useful behavior. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 91 Bootstrap ContextsOther programs such as esound, however, continue to work correctly after logout when started from a user context. Other programs behave correctly in their default configuration but fail in other configurations—for example, when authentication support is enabled. There are no hard and fast rules for which programs will continue to operate after their bootstrap context is destroyed. Only thorough testing can tell you whether any given program will misbehave if started from a user context, since even programs that do not appear to directly use Mach communication may still do so indirectly. In OS X v10.2, a great deal of effort has gone into making sure that programs that use only standard BSD services and functions do not use Mach lookups in a way that would fail if started from a user context. If you find an application that breaks when started from a Terminal.app window, please file a bug report. How Contexts Affect Users From the perspective of a user, contexts are generally unimportant as long as they do not want a program to survive past the end of their login session. Contexts do become a problem for the administrator, however. For example, if the administrator upgrades sshd by killing the old version, starting the new one, and logging out, strange things could happen since the context in which sshd was running no longer exists. Contexts also pose an issue for usersrunning background jobs with nohup or users detaching terminalsessions using screen. There are times when it is perfectly reasonable for a program to survive past logout, but by default, this does not occur. There are three basic ways that a user can get around this. In the case of daemons, they can modify the startup scripts to start the application. On restart, the application will be started in the startup context. This is not very practical if the computer in question isin heavy use, however. Fortunately, there are other waysto startservices in a startup context. The second way to run a service in the startup context is to use ssh to connect to the computer. Since sshd is running in the startup context, programs started from an ssh session also register themselves in the startup context. (Note that a user can safely kill the main sshd process without being logged out. The user just needs to be careful to kill the right one.) The third way isto log in asthe console user (>console), which causes LoginWindow to exit and causes init to spawn a getty process on the console. Since init spawns getty, which spawns login, which spawns the user’s shell, any programs started from the text console will be in the startup context. Bootstrap Contexts How Contexts Affect Users 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 92More generally, any process that is the child of a process in the startup context (other than those inherited by init because their parent process exited) is automatically in the startup context. Any process that is the child of a process in the login context is, itself, in the login context. This means that daemons can safely fork children at any time and those children will be in the startup context, as will programs started from the console (not the Console application). This also meansthat any program started by a user in a terminal window, from Finder, from the Dock, and so on, will be in the currently logged in user’s login context, even if that user runs the application using su or sudo. How Contexts Affect Developers If you are writing only kernel code, contexts are largely irrelevant (unless you are creating a new context, of course). However, kernel developers frequently need to write a program that registers itself in the startup context in order to provide some level of driver communication. For example, you could write a user-space daemon that brokers configuration information for a sound driver based on which user is logged in at the time. In the most general case, the problem ofstarting an application in the startup context can be solved by creating a startup script for your daemon, which causesit to be run in the startup context after the next reboot. However, users generally do not appreciate having to reboot their computers to install a new driver. Asking the user to connect to his or her own computer with ssh to execute a script is probably not reasonable, either. The biggest problem with forcing a reboot, of course, is that users often install several programs at once. Rebooting between each install inconveniences the end user, and has no other benefit. For that reason, you should not force the user to restart. Instead, you should offer the user the option, noting that the software may not work correctly until the user restarts. While this does not solve the fundamental problem, it does at least minimize the most common source of complaints. There are a number of ways to force a program to start in the startup context without rebooting or using ssh. However, these are not robust solutions, and are not recommended. A standard API for starting daemons is under consideration. When an official API becomes available, this chapter will be updated to discuss it. Bootstrap Contexts How Contexts Affect Developers 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 93Those of you who are already familiar with writing device drivers for Mac OS 9 or for BSD will discover that writing driversfor OS X requiressome new ways of thinking. In creating OS X, Apple has completely redesigned the Macintosh I/O architecture, providing a framework for simplified driver development that supports many categories of devices. This framework is called the I/O Kit. From a programming perspective, the I/O Kit provides an abstract view of the system hardware to the upper layers of OS X. The I/O Kit uses an object-oriented programming model, implemented in a restricted subset of C++ to promote increased code reuse. By starting with properly designed base classes, you gain a head start in writing a new driver; with much of the driver code already written, you need only to fill in the specific code that makes your driver different. For example, all SCSI controllers deliver a fairly standard set of commands to a device, but do so via different low-level mechanisms. By properly using object-oriented programming methodology, a SCSI driver can implement those low-level transport portions without reimplementing the higher level SCSI protocol code. Similar opportunities for code reuse can be found in most types of drivers. Part of the philosophy of the I/O Kit is to make the design completely open. Rather than hiding parts of the API in an attempt to protect developers from themselves, all of the I/O Kit source is available as part of Darwin. You can use the source code as an aid to designing (and debugging) new drivers. Instead of hiding the interfaces, Apple’s designers have chosen to lead by example. Sample code and classes show the recommended (easy) way to write a driver. However, you are not prevented from doing things the hard way (or the wrong way). Instead, attention has been concentrated on making the “best” ways easy to follow. Redesigning the I/O Model You might ask why Apple chose to redesign the I/O model. At first glance, it mightseem that reusing the model from Mac OS 9 or FreeBSD would have been an easier choice. There are several reasons for the decision, however. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 94 I/O Kit OverviewNeither the Mac OS 9 driver model nor the FreeBSD model offered a feature set rich enough to meet the needs of OS X. The underlying operating-system technology of OS X is very different from that of Mac OS 9. The OS X kernel is significantly more advanced than the previous Mac OS system architecture; OS X needs to handle memory protection, preemption, multiprocessing, and other features not present (orsubstantially less pervasive) in previous versions of the Mac OS. Although FreeBSD supports these features, the BSD driver model did not offer the automatic configuration, stacking, power management, or dynamic device-loading features required in a modern, consumer-oriented operating system. By redesigning the I/O architecture, Apple’s engineers can take best advantage of the operating-system features in OS X. For example, virtual memory (VM) is not a fundamental part of the operating system in Mac OS 9. Thus, every driver writer must know about (and write for) VM. This has presented certain complications for developers. In contrast, OS X has simplified driver interaction with VM. VM capability is inherent in the OS X operating system and cannot be turned off by the user. Thus, VM capabilities can be abstracted into the I/O Kit, and the code for handling VM need not be written for every driver. OS X offers an unprecedented opportunity to reuse code. In Mac OS 9, for example, all software development kits (SDKs) were independent of each other, duplicating functionality between them. In OS X, the I/O Kit is delivered as part of the basic developer tools, and code is shared among its various parts. In contrast with traditional I/O models, the reusable code model provided by the I/O Kit can decrease your development work substantially. In porting drivers from Mac OS 9, for example, the OS X counterparts have been up to 75% smaller. In general, all hardware support is provided directly by I/O Kit entities. One exception to this rule is imaging devicessuch as printers,scanners, and digital cameras(although these do make some use of I/O Kit functionality). Specifically, although communication with these devices is handled by the I/O Kit (for instance, under the FireWire or USB families), support for particular device characteristics is handled by user-space code (see “For More Information” (page 100) for further discussion). If you need to support imaging devices, you should employ the appropriate imaging software development kit (SDK). The I/O Kit attempts to represent, in software, the same hierarchy that exists in hardware. Some things are difficult to abstract, however. When the hardware hierarchy is difficult to represent (for example, if layering violations occur), then the I/O Kit abstractions provide less help for writing drivers. In addition, all drivers exist to drive hardware; all hardware is different. Even with the reusable model provided by the I/O Kit, you still need to be aware of any hardware quirks that may impact a higher-level view of the device. The code to support those quirks still needs to be unique from driver to driver. I/O Kit Overview Redesigning the I/O Model 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 95Although most developers should be able to take full advantage of I/O Kit device families (see “Families” (page 96)), there will occasionally be some who cannot. Even those developers should be able to make use of parts of the I/O Kit, however. In any case, the source code is always available. You can replace functionality and modify the classes yourself if you need to do so. In designing the I/O Kit, one goal has been to make developers’ lives easier. Unfortunately, it is not possible to make all developers’ lives uniformly easy. Therefore, a second goal of the I/O Kit design is to meet the needs of the majority of developers, without getting in the way of the minority who need lower level access to the hardware. I/O Kit Architecture The I/O Kit provides a model of system hardware in an object-oriented framework. Each type of service or device is represented by a C++ class; each discrete service or device is represented by an instance (object) of that class. There are three major conceptual elements of the I/O Kit architecture: ● “Families” (page 96) ● “Drivers” (page 97) ● “Nubs” (page 97) Families A family defines a collection of high-level abstractions common to all devices of a particular category that takes the form of C code and C++ classes. Families may include headers, libraries, sample code, test harnesses, and documentation. They provide the API, generic support code, and at least one example driver (in the documentation). Families provide services for many different categories of devices. For example, there are protocol families (such as SCSI, USB, and FireWire), storage families (disk), network families, and families to describe human interface devices (mouse and keyboard). When devices have features in common, the software that supports those features is most likely found in a family. Common abstractions are defined and implemented by the family, allowing all drivers in a family to share similar features easily. For example, all SCSI controllers have certain things they must do, such as scanning the SCSI bus. The SCSI family defines and implementsthe functionality that is common to SCSI controllers. Because thisfunctionality has been included in the SCSI family, you do not need to include scanning code (for example) in your new SCSI controller driver. I/O Kit Overview I/O Kit Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 96Instead, you can concentrate on device-specific details that make your driver different from other SCSI drivers. The use of families means there is less code for you to write. Families are dynamically loadable; they are loaded when needed and unloaded when no longer needed. Although some common families may be preloaded at system startup, all families should be considered to be dynamically loadable (and, therefore, potentially unloaded). See the “Connection Example” (page 98) for an illustration. Drivers A driver is an I/O Kit object that manages a specific device or bus, presenting a more abstract view of that device to other parts of the system. When a driver is loaded, its required families are also loaded to provide necessary, common functionality. The request to load a driver causes all of its dependent requirements (and their requirements) to be loaded first. After all requirements are met, the requested driver is loaded as well. See “Connection Example” (page 98) for an illustration. Note that families are loaded upon demand of the driver, not the other way around. Occasionally, a family may already be loaded when a driver demands it; however, you should never assume this. To ensure that all requirements are met, each device driver should list all of its requirements in its property list. Most drivers are in a client-provider relationship, wherein the driver must know about both the family from which it inherits and the family to which it connects. A SCSI controller driver, for example, must be able to communicate with both the SCSI family and the PCI family (as a client of PCI and provider of SCSI). A SCSI disk driver communicates with both the SCSI and storage families. Nubs A nub is an I/O Kit object that represents a point of connection for a driver. It represents a controllable entity such as a disk or a bus. A nub is loaded as part of the family that instantiates it. Each nub provides access to the device or service that it represents and provides services such as matching, arbitration, and power management. The concept of nubs can be more easily visualized by imagining a TV set. There is a wire attached to your wall that provides TV service from somewhere. For all practical purposes, it is permanently associated with that provider, the instantiating class (the cable company who installed the line). It can be attached to the TV to provide a service (cable TV). That wire is a nub. Each nub provides a bridge between two drivers (and, by extension, between two families). It is most common that a driver publishes one nub for each individual device or service it controls. (In this example, imagine one wire for every home serviced by the cable company.) I/O Kit Overview I/O Kit Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 97It is also possible for a driver that controls only a single device or service to act as its own nub. (Imagine the antenna on the back of your TV that has a built-in wire.) See the “Connection Example” (page 98) for an illustration of the relationship between nubs and drivers. Connection Example Figure 12-1 (page 98) illustrates the I/O Kit architecture, using several example drivers and their corresponding nubs. Note that many different driver combinations are possible; this diagram shows only one possibility. In this case, a SCSI stack is shown, with a PCI controller, a disk, and a SCSI scanner. The SCSI disk is controlled by a kernel-resident driver. The SCSI scanner is controlled by a driver that is part of a user application. Figure 12-1 I/O Kit architecture IOPCIBridge family PCI bus driver IOSCSIParallelController family SCSI card driver IOBlockStorageDriver family SCSI disk driver IOPCIDevice nubs IOSCSIParallelDevice nubs IOMedia nub Disk User application User space Kernel space Device interface User client This example illustrates how a SCSI disk driver (Storage family) is connected to the PCI bus. The connection is made in several steps. I/O Kit Overview I/O Kit Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 981. The PCI bus driver discovers a PCI device and announces its presence by creating a nub (IOPCIDevice). The nub’s class is defined by the PCI family. IOPCIBridge family PCI bus driver IOPCIDevice nubs Video card Main logic board ATA SCSI card 2. The bus driver identifies (matches) the correct device driver and requests that the driver be loaded. At the end of this matching process, a SCSI controller driver has been found and loaded. Loading the controller driver causes all required families to be loaded as well. In this case, the SCSI family is loaded; the PCI family (also required) is already present. The SCSI controller driver is given a reference to the IOPCIDevice nub. 3. The SCSI controller driver scans the SCSI bus for devices. Upon finding a device, it announces the presence of the device by creating a nub (IOSCSIDevice). The class of this nub is defined by the SCSI family. IOPCIBridge family PCI bus driver IOSCSIParallelController family SCSI card driver IOPCIDevice nubs IOSCSIParallelDevice nubs SCSI disk Unknown device SCSI scanner 1 5 6 I/O Kit Overview I/O Kit Architecture 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 994. The controller driver identifies (matches) the correct device driver and requests that the driver be loaded. At the end of this matching process, a disk driver has been found and loaded. Loading the disk driver causes all required families to be loaded as well. In this case, the Storage family is loaded; the SCSI family (also required) is already present. The disk driver is given a reference to the IOSCSIDevice nub. IOPCIBridge family PCI bus driver IOSCSIParallelController family SCSI card driver IOBlockStorageDriver family SCSI disk driver IOPCIDevice nubs IOSCSIParallelDevice nubs IOMedia nub Disk For More Information For more information on the I/O Kit, you should read the document I/O Kit Fundamentals, available from Apple’s developer documentation website, http://developer.apple.com/documentation. It provides a good general overview of the I/O Kit. In addition to I/O Kit Fundamentals, the website contains a number of HOWTO documents and topic-specific documents that describe issues specific to particular technology areas such as FireWire and USB. I/O Kit Overview For More Information 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 100The BSD portion of the OS X kernel is derived primarily from FreeBSD, a version of 4.4BSD that offers advanced networking, performance, security, and compatibility features. BSD variants in general are derived (sometimes indirectly) from 4.4BSD-Lite Release 2 from the Computer Systems Research Group (CSRG) at the University of California at Berkeley. BSD provides many advanced features, including the following: ● Preemptive multitasking with dynamic priority adjustment. Smooth and fair sharing of the computer between applications and users is ensured, even under the heaviest of loads. ● Multiuser access. Many people can use an OS X system simultaneously for a variety of things. This means, for example, thatsystem peripheralssuch as printers and disk drives are properly shared between all users on the system or the network and that individual resource limits can be placed on users or groups of users, protecting critical system resources from overuse. ● Strong TCP/IP networking with support for industry standards such as SLIP, PPP, and NFS. OS X can interoperate easily with other systems as well as act as an enterprise server, providing vital functions such as NFS (remote file access) and email services, or Internet services such as HTTP, FTP, routing, and firewall (security) services. ● Memory protection. Applications cannot interfere with each other. One application crashing does not affect others in any way. ● Virtual memory and dynamic memory allocation. Applications with large appetitesfor memory are satisfied while still maintaining interactive response to users. With the virtual memory system in OS X, each application has access to its own 4 GB memory address space; this should satisfy even the most memory-hungry applications. ● Support for kernel threads based on Mach threads. User-level threading packages are implemented on top of kernel threads. Each kernel thread is an independently scheduled entity. When a thread from a user process blocks in a system call, other threads from the same process can continue to execute on that or other processors. By default, a process in the conventional sense has one thread, the main thread. A user process can use the POSIX thread API to create other user threads. ● SMP support. Support is included for computers with multiple CPUs. ● Source code. Developers gain the greatest degree of control over the BSD programming environment because source is included. ● Many of the POSIX APIs. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 101 BSD OverviewBSD Facilities The facilities that are available to a user process are logically divided into two parts: kernel facilities and system facilities implemented by or in cooperation with a server process. The facilities implemented in the kernel define the virtual machine in which each process runs. Like many real machines, this virtual machine has memory management, an interrupt facility, timers, and counters. The virtual machine also allows access to files and other objects through a set of descriptors. Each descriptor resembles a device controller and supports a set of operations. Like devices on real machines, some of which are internal to the machine and some of which are external, parts of the descriptor machinery are built into the operating system, while other parts are often implemented in server processes. The BSD component provides the following kernel facilities: ● processes and protection ● host and process identifiers ● process creation and termination ● user and group IDs ● process groups ● memory management ● text, data, stack, and dynamic shared libraries ● mapping pages ● page protection control ● POSIX synchronization primitives ● POSIX shared memory ● signals ● signal types ● signal handlers ● sending signals ● timing and statistics ● real time ● interval time ● descriptors ● files ● pipes BSD Overview BSD Facilities 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 102● sockets ● resource controls ● process priorities ● resource utilization and resource limits ● quotas ● system operation support ● bootstrap operations ● shut-down operations ● accounting BSD system facilities (facilities that may interact with user space) include ● generic input/output operations such as read and write, nonblocking, and asynchronous operations ● file-system operations ● interprocess communication ● handling of terminals and other devices ● process control ● networking operations Differences between OS X and BSD Although the BSD portion of OS X is primarily derived from FreeBSD, some changes have been made: ● The sbrk() system call for memory management is deprecated. Its use is not recommended in OS X. ● The OS X runtime model uses a different object file format for executables and shared objects, and a different mechanism for executing some of those executables. The primary native format is Mach-O. This format is supported by the dynamic link editor (dyld). The PEF binary file format is supported by the Code Fragment Manager (CFM). The kernel supports execve() with Mach-O binaries. Mapping and management of Mach-O dynamic shared libraries, as well as launching of PEF-based applications, are performed by user-space code. ● OS X does not support memory-mapped devices through the mmap() function. (Graphic device support and other subsystems provide similar functionality, but using different APIs.) In OS X, this interface should be done through user clients. See the Apple I/O Kit documents for additional information. ● The swapon() call is not supported; macx_swapon() is the equivalent call from the Mach pager. BSD Overview Differences between OS X and BSD 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 103● The Unified Buffer Cache implementation in OS X differs from that found in FreeBSD. ● Mach provides a number of IPC primitives that are not traditionally found in UNIX. See “Boundary Crossings” (page 109) for more information on Mach IPC. Some System V primitives are supported, but their use is discouraged in favor of POSIX equivalents. ● Several changes have been made to the BSD security model to support single-user and multiple-administrator configurations, including the ability to disable ownership and permissions on a volume-by-volume basis. ● The locking mechanism used throughout the kernel differs substantially from the mechanism used in FreeBSD. ● The kernel extension mechanism used by OS X is completely different. The OS X driver layer, the I/O Kit, is an object-oriented driver stack written in C++. The general kernel programming interfaces, or KPIs, are used to write non-driver kernel extensions. These mechanisms are described more in “I/O Kit Overview” (page 94) and KPI Reference , respectively. In addition, several new features have been added that are specific to the OS X (Darwin) implementation of BSD. These features are not found in FreeBSD. ● enhancements to file-system buffer cache and file I/O clustering ● adaptive and speculative read ahead ● user-process controlled read ahead ● time aging of the file-system buffer cache ● enhancements to file-system support ● implementation of Apple extensions for ISO-9660 file systems ● multithreaded asynchronous I/O for NFS ● addition of system calls to support semantics of Mac OS Extended (HFS+) file systems ● additions to naming conventions for pathnames, as required for accessing multiple forks in Mac OS Extended file systems For Further Reading The BSD component of the OS X kernel is complex. A complete description is beyond the scope of this document. However, many excellent references exist for this component. If you are interested in BSD, be sure to refer to the bibliography for further information. BSD Overview For Further Reading 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 104Although the BSD layer of OS X is derived from 4.4BSD, keep in mind that it is not identical to 4.4BSD. Some functionality of 4.4 BSD has not been included in OS X. Some new functionality has been added. The cited reference materials are recommended for additional reading. However, they should not be presumed as forming a definitive description of OS X. BSD Overview For Further Reading 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 105OS X provides“out-of-the-box”support forseveral different file systems. These include Mac OS Extended format (HFS+), the BSD standard file system format (UFS), NFS (an industry standard for networked file systems), ISO 9660 (used for CD-ROM), MS-DOS, SMB (Windows file sharing standard), AFP (Mac OS file sharing), and UDF. Support is also included for reading the older, Mac OS Standard format (HFS) file-system type; however, you should not plan to format new volumes using Mac OS Standard format. OS X cannot boot from these file systems, nor does the Mac OS Standard format provide some of the information required by OS X. The Mac OS Extended format provides many of the same characteristics as Mac OS Standard format but adds additional support for modern features such as file permissions, longer filenames, Unicode, both hard and symbolic links, and larger disk sizes. UFS provides case sensitivity and other characteristics that may be expected by BSD commands. In contrast, Mac OS Extended Format is not case-sensitive (but is case-preserving). OS X currently can boot and “root” from an HFS+, UFS, ISO, NFS, or UDF volume. That is, OS X can boot from and mount a volume of any of these types and use it as the primary, or root, file system. Other file systems can also be mounted, allowing usersto gain accessto additional volume formats and features. NFS provides access to network servers as if they were locally mounted file systems. The Carbon application environment mimics many expected behaviors of Mac OS Extended format on top of both UFS and NFS. These include such characteristics as Finder Info, file ID access, and aliases. By using the OS X Virtual File System (VFS) capability and writing kernel extensions, you can add support for other file systems. Examples of file systems that are not currently supported in OS X but that you may wish to add to the system include the Andrew file system (AFS) and the Reiser file system (ReiserFS). If you want to support a new volume format or networking protocol, you’ll need to write a file-system kernel extension. Working With the File System In OS X, the vnode structure providesthe internal representation of a file or directory (folder). There is a unique vnode allocated for each active file or folder, including the root. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 106 File Systems OverviewWithin a file system, operations on specific files and directories are implemented via vnodes and VOP (vnode operation) calls. VOP calls are used for operations on individual files or directories (such as open, close, read, or write). Examples include VOP_OPEN to open a file and VOP_READ to read file contents. In contrast, file-system–wide operations are implemented using VFS calls. VFS calls are primarily used for operations on entire file systems; examples include VFS_MOUNT and VFS_UNMOUNT to mount or unmount a file system, respectively. File-system writers need to provide stubs for each of these sets of calls. VFS Transition The details of the VFS subsystem in OS X are in the process of changing in order to make the VFS interface sustainable. If you are writing a leaf file system, these changes will still affect you in many ways. please contact Apple Developer Support for more information. File Systems Overview VFS Transition 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 107OS X kernel extensions (KEXTs) provide mechanisms to extend and modify the networking infrastructure of OS X dynamically, without recompiling or relinking the kernel. The effect is immediate and does not require rebooting the system. Networking KEXTs can be used to ● monitor network traffic ● modify network traffic ● receive notification of asynchronous events from the driver layer In the last case, such events are received by the data link and network layers. Examples of these events include power management events and interface status changes. Specifically, KEXTs allow you to ● create protocol stacks that can be loaded and unloaded dynamically and configured automatically ● create modulesthat can be loaded and unloaded dynamically atspecific positionsin the network hierarchy. The Kernel Extension Manager dynamically adds KEXTs to the running OS X kernel inside the kernel’s address space. An installed and enabled network-related KEXT is invoked automatically, depending on its position in the sequence of protocol components, to process an incoming or outgoing packet. All KEXTs provide initialization and termination routines that the Kernel Extension Manager invokes when it loads or unloads the KEXT. The initialization routine handles any operations that are needed to complete the incorporation of the KEXT into the kernel, such as updating protosw and domain structures (through programmatic interfaces). Similarly, the termination routine must remove references to the NKE from these structures to unload itself successfully. NKEs must provide a mechanism, such as a reference count, to ensure that the NKE can terminate without leaving dangling pointers. For additional information on the networking portions of the OS X kernel, you should read the document Network Kernel Extensions Programming Guide . 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 108 Network ArchitectureTwo applications can communicate in a number of ways—for example, by using pipes or sockets. The applicationsthemselves are unaware of the underlying mechanismsthat provide this communication. However this communication occurs by sending data from one program into the kernel, which then sends the data to the second program. As a kernel programmer, it is your job to create the underlying mechanisms responsible for communication between your kernel code and applications. This communication is known as crossing the user-kernel boundary. This chapter explains various ways of crossing that boundary. In a protected memory environment, each process is given its own address space. This means that no program can modify another program’s data unless that data also resides in its own memory space (shared memory). The same applies to the kernel. It resides in its own address space. When a program communicates with the kernel, data cannot simply be passed from one address space to the other as you might between threads (or between programs in environments like Mac OS 9 and most real-time operating systems, which do not have protected memory). We refer to the kernel’s address space as kernel space, and collectively refer to applications’ address spaces as user space. For this reason, applications are also commonly referred to as user-space programs, or user programs for short. When the kernel needs a small amount of data from an application, the kernel cannot just dereference a pointer passed in from that application, since that pointer is relative to the application’s address space. Instead, the kernel generally copies that information into storage within its own address space. When a large region of data needs to be moved, it may map entire pages into kernel space for efficiency. The same behavior can be seen in reverse when moving data from the kernel to an application. Because it is difficult to move data back and forth between the kernel and an application, this separation is called a boundary. It isinherently time consuming to copy data, even if that data isjust the user-space address of a shared region. Thus, there is a performance penalty whenever a data exchange occurs. If this penalty is a serious problem, it may affect which method you choose for crossing the user-kernel boundary. Also, by trying to minimize the number of boundary crossings, you may find ways to improve the overall design of your code. This is particularly significant if your code is involved in communication between two applications, since the user-kernel boundary must be crossed twice in that case. There are a number of ways to cross the user-kernel boundary. Some of them are covered in this chapter in the following sections: 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 109 Boundary Crossings● “Mach Messaging and Mach Interprocess Communication (IPC)” (page 112) ● “BSD syscall API ” (page 116) ● “BSD ioctl API” (page 116) ● “BSD sysctl API ” (page 117) ● “Memory Mapping and Block Copying” (page 125) In addition, the I/O Kit uses the user-client/device-interface API for most communication. Because that API is specific to the I/O Kit, it is not covered in this chapter. The user client API is covered in I/O Kit Fundamentals, Accessing Hardware From Applications, and I/O Kit Device Driver Design Guidelines. The ioctl API is also specific to the construction of device drivers, and is largely beyond the scope of this document. However, since ioctl is a BSD API, it is covered at a glance for your convenience. This chapter covers one subset of Mach IPC—the Mach remote procedure call (RPC) API. It also covers the syscall, sysctl, memory mapping, and block copying APIs. Security Considerations Crossing the user-kernel boundary represents a security risk if the kernel code operates on the data in any substantial way (beyond writing it to disk or passing it to another application). You must carefully perform bounds checking on any data passed in, and you must also make sure your code does not dereference memory that no longer belongs to the client application. Also, under no circumstances should you run unverified program code passed in from user space within the kernel. See “Security Considerations” (page 24) for further information. Choosing a Boundary Crossing Method The first step in setting up user-kernel data exchange is choosing a means to do that exchange. First, you must consider the purpose for the communication. Some crucial factors are latency, bandwidth, and the kernel subsystem involved. Before choosing a method of communication, however, you should first understand at a high-level each of these forms of communication. Mach messaging and Mach interprocess communication (IPC) are relatively low-level ways of communicating between two Mach tasks (processes), as well as between a Mach task and the kernel. These form the basis for most communication outside of BSD and the I/O Kit. The Mach remote procedure call (RPC) API is a high level procedural abstraction built on top of Mach IPC. Mach RPC is the most common use of IPC. Boundary Crossings Security Considerations 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 110The BSD syscall API is an API for calling kernel functions from user space. It is used extensively when writing file systems and networking protocols, in ways that are very subsystem-dependent. Developers are strongly discouraged from using the syscall API outside of file-system and network extensions, as no plug-in API exists for registering a new system call with the syscall mechanism. The BSD sysctl API (in its revised form) supersedes the syscall API and also provides a relatively painless way to change individual kernel variablesfrom userspace. It has a straightforward plug-in architecture, making it a good choice where possible. Memory mapping and block copying are used in conjunction with one of the other APIs mentioned, and provide ways of moving large amounts of data (more than a few bytes) or variably sized data to and from kernel space. Kernel Subsystems The choice of boundary crossing methods depends largely on the part of the kernel into which you are adding code. In particular, the boundary crossing method preferred for the I/O Kit is different from that preferred for BSD, which is different from that preferred for Mach. If you are writing a device driver or other related code, you are probably dealing with the I/O Kit. In that case, you should instead read appropriate sections in I/O Kit Fundamentals, Accessing Hardware From Applications, and I/O Kit Device Driver Design Guidelines. If you are writing code that resides in the BSD subsystem (for example, a file system), you should generally use BSD APIs such as syscall or sysctl unless you require high bandwidth or exceptionally low latency. If you are writing code that resides anywhere else, you will probably have to use Mach messaging. Bandwidth and Latency The guidelines in the previous section apply to most communication between applications and kernel code. The methods mentioned, however, are somewhat lacking where high bandwidth or low latency are concerns. If you require high bandwidth, but latency is not an issue, you should probably consider doing memory-mapped communication. For large messagesthisis handled somewhat transparently by Mach RPC, making it a reasonable choice. For BSD portions of the kernel, however, you must explicitly pass pointers and use copyin and copyout to move large quantities of data. Thisis discussed in more detail in “Memory Mapping and Block Copying” (page 125). Boundary Crossings Choosing a Boundary Crossing Method 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 111If you require low latency but bandwidth is not an issue, sysctl and syscall are not good choices. Mach RPC, however, may be an acceptable solution. Another possibility is to actually wire a page of memory (see “Memory Mapping and Block Copying” (page 125) for details),start an asynchronous Mach RPC simpleroutine (to process the data), and use either locks or high/low water marks (buffer fullness) to determine when to read and write data. This can work for high-bandwidth communication as well. If you require both high bandwidth and low latency, you should also look at the user client/device interface model used in the I/O Kit, since that model has similar requirements. Mach Messaging and Mach Interprocess Communication (IPC) Mach IPC and Mach messaging are the basis for much of the communication in OS X. In many cases, however, these facilities are used indirectly by services implemented on top of one of them. Mach messaging and IPC are fundamentally similar except that Mach messaging is stateless, which prevents certain types of error recovery, as explained later. Except where explicitly stated, this section treats the two as equivalent. The fundamental unit of Mach IPC isthe port. The concept of Mach ports can be difficult to explain in isolation, so instead this section assumes a passing knowledge of a similar concept, that of ports in TCP/IP. In TCP/IP, a server listens for incoming connections over a network on a particular port. Multiple clients can connect to the port and send and receive data in word-sized or multiple-word–sized blocks. However, only one server process can be bound to the port at a time. In Mach IPC, the concept is the same, but the players are different. Instead of multiple hosts connecting to a TCP/IP port, you have multiple Mach tasks on the same computer connecting to a Mach port. Instead of firewall rules on a port, you have port rights that specify what tasks can send data to a particular Mach port. Also, TCP/IP ports are bidirectional, while Mach ports are unidirectional, much like UNIX pipes. This means that when a Mach task connects to a port, it generally allocates a reply port and sends a message containing send rights to that reply port so that the receiving task can send messages back to the sending task. As with TCP/IP, multiple client tasks can open connections to a Mach port, but only one task can be listening on that port at a time. Unlike TCP/IP, however, the IPC mechanism itself provides an easy means for one task to hand off the right to listen to an arbitrary task. The term receive rights refers to a task’s ability to listen on a given port. Receive rights can be sent from task to task in a Mach message. In the case of Mach IPC (but not Mach messaging), receive rights can even be configured to automatically return to the original task if the new task crashes or becomes unreachable (for example, if the new task isrunning on another computer and a router crashes). Boundary Crossings Mach Messaging and Mach Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 112In addition to specifying receive rights, Mach ports can specify which tasks have the right to send data. A task with send rights may be able to send once, or may be able to arbitrarily send data to a given port, depending on the nature of the rights. Using Well-Defined Ports Before you can use Mach IPC for task communication, the sending task must be able to obtain send rights on the receiving task’s task port. Historically, there are several ways of doing this, not all of which are supported by OS X. For example, in OS X, unlike most other Mach derivatives, there is no service server or name server. Instead, the bootstrap task and mach_init subsume this functionality. When a task is created, it is given send rights to a bootstrap port for sending messages to the bootstrap task. Normally a task would use this port to send a message that gives the bootstrap task send rights on another port so that the bootstrap task can then return data to the calling task. Various routines exist in bootstrap.h that abstract this process. Indeed, most users of Mach IPC or Mach messaging actually use Mach remote procedure calls (RPC), which are implemented on top of Mach IPC. Since direct use of IPC is rarely desirable (because it is not easy to do correctly), and because the underlying IPC implementation has historically changed on a regular basis, the details are not covered here. You can find more information on using Mach IPC directly in the Mach 3 Server Writer’s Guide from Silicomp (formerly the Open Group, formerly the Open Software Foundation Research Institute), which can be obtained from the developer section of Apple’s website. While much of the information contained in that book is not fully up-to-date with respect to OS X, it should still be a relatively good resource on using Mach IPC. Remote Procedure Calls (RPC) Mach RPC is the most common use for Mach IPC. It is frequently used for user-kernel communication, but can also be used for task to task or even computer-to-computer communication. Programmers frequently use Mach RPC for setting certain kernel parameters such as a given thread’s scheduling policy. RPC is convenient because it is relatively transparent to the programmer. Instead of writing long, complex functionsthat handle ports directly, you have only to write the function to be called and a small RPC definition to describe how to export the function as an RPC interface. After that, any application with appropriate permissions can call those functions as if they were local functions, and the compiler will convert them to RPC calls. In the directory osfmk/mach (relative to your checkout of the xnu module from CVS), there are a number of files ending in .defs; these files contain the RPC definitions. When the kernel (or a kernel module) is compiled, the Mach Interface Generator(MIG) usesthese definitionsto create IPC code to support the functions exported via RPC. Normally, if you want to add a new remote procedure call, you should do so by adding a definition to one of these existing files. (See “Building and Debugging Kernels” (page 155) for more information on obtaining kernel sources.) Boundary Crossings Mach Messaging and Mach Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 113What follows is an example of the definition for a routine, one of the more common uses of RPC. routine thread_policy_get( thread : thread_act_t; flavor : thread_policy_flavor_t; out policy_info : thread_policy_t, CountInOut; inout get_default : boolean_t); Notice the C-like syntax of the definition. Each parameter in the routine roughly maps onto a parameter in the C function. The C prototype for this function follows. kern_return_t thread_policy_get( thread_act_t act, thread_policy_flavor_t flavor, thread_policy_t policy_info, mach_msg_type_number_t *count, boolean_t get_default); The first two parameters are integers, and are passed as call-by-value. The third is a struct containing integers. It is an outgoing parameter, which means that the values stored in that variable will not be received by the function, but will be overwritten on return. Note: The parameters are all word-sized or multiples of the word size. Smaller data are impossible because of limitations inherent to the underlying Mach IPC mechanisms. From there it becomes more interesting. The fourth parameter in the C prototype is a representation of the size of the third. In the definition file, this is represented by an added option, CountInOut. The MIG option CountInOut specifies that there is to be an inout parameter called count. An inout parameter is one in which the original value can be read by the function being called, and its value is replaced on return from that function. Unlike a separate inout parameter, however, the value initially passed through this parameter is not directly set by the calling function. Instead, it is tied to the policy_info parameter so that the number of integers in policy_info is transparently passed in through this parameter. Boundary Crossings Mach Messaging and Mach Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 114In the function itself, the function checks the count parameter to verify that the buffer size is at least the size of the data to be returned to prevent exceeding array bounds. The function changes the value stored in count to be the desired size and returns an error if the buffer is not large enough (unless the buffer pointer is null, in which case it returns success). Otherwise, it dereferences the various fields of the policy_info parameter and in so doing, stores appropriate values into it, then returns. Note: Since Mach RPC is done via message passing, inout parameters are technically call-by-value-return and not call-by-reference. For more realistic call-by-reference, you need to pass a pointer. The distinction is not particularly significant except when aliasing occurs. (Aliasing means having a single variable visible in the same scope under two or more different names.) In addition to the routine, Mach RPC also has a simpleroutine. A simpleroutine is a routine that is, by definition, asynchronous. It can have no out or inout parameters and no return value. The caller does not wait for the function to return. One possible use for this might be to tell an I/O device to send data as soon as it is ready. In that use, the simpleroutine might simply wait for data, then send a message to the calling task to indicate the availability of data. Another important feature of MIG is that of the subsystem. In MIG, a subsystem is a group of routines and simpleroutines that are related in some way. For example, the semaphore subsystem contains related routinesthat operate on semaphores. There are also subsystemsfor varioustimers, parts of the virtual memory (VM) system, and dozens of others in various places throughout the kernel. Most of the time, if you need to use RPC, you will be doing it within an existing subsystem. The details of creating a new subsystem are beyond the scope of this document. Developers needing to add a new Mach subsystem should consult the Mach 3 ServerWriter’s Guide from The Open Group (TOG), which can be obtained from various locations on the internet. Another feature of MIG is the type. A type in MIG is exactly the same thing as it is in programming languages. However, the construction of aggregate types differs somewhat. type clock_flavor_t = int; type clock_attr_t = array[*:1] of int; type mach_timespec_t = struct[2] of int; Data of type array is passed as the user-space address of what is assumed to be a contiguous array of the base type, while a struct is passed by copying all of the individual values of an array of the base type. Otherwise, these are treated similarly. A “struct” is not like a C struct, as elements of a MIG struct must all be of the same base type. Boundary Crossings Mach Messaging and Mach Interprocess Communication (IPC) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 115The declaration syntax issimilar to Pascal, where *:1 and 2 representsizesfor the array orstructure, respectively. The *:1 construct indicates a variable-sized array, where the size can be up to 1, inclusive, but no larger. Calling RPC From User Applications RPC, as mentioned previously, is virtually transparent to the client. The procedure call looks like any other C function call, and no additional library linkage is needed. You need only to bring the appropriate headers in with a #include directive. The compiler automatically recognizes the call as a remote procedure call and handles the underlying MIG aspects for you. BSD syscall API The syscall API is the traditional UNIX way of calling kernel functions from user space. Its implementation variesfrom one part of the kernel to the next, however, and it is completely unsupported for loadable modules. For this reason, it is not a recommended way of getting data into or out of the kernel in OS X unless you are writing a file system. File systems have to support a number of standard system calls (for example, mount), but do so by means of generic file system routinesthat call the appropriate file-system functions. Thus, if you are writing a file system, you need to implement those functions, but you do not need to write the code that handles the system calls directly. For more information on implementing syscall support in file systems,see the chapter “File Systems Overview” (page 106). BSD ioctl API The ioctl interface provides a way for an application to send certain commands or information to a device driver. These can be used for parameter tuning (though this is more commonly done with sysctl), but can also be used for sending instructions for the driver to perform a particular task (for example, rewinding a tape drive). The use of the ioctl interface is essentially the same under OS X as it is in other BSD-derived operating systems, except in the way that device drivers register themselves with the system. In OS X, unlike most BSDs, the contents of the /dev directory are created dynamically by the kernel. This file system mounted on /dev is referred to as devfs. You can, of course, still manually create device nodes with mknod, because devfs is union mounted over the root file system. Boundary Crossings BSD syscall API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 116The I/O Kit automatically registers some types of devices with devfs, creating a node in /dev. If your device family does not do that, you can manually register yourself in devfs using cdevsw_add or bdevsw_add (for character and block devices, respectively). When registering a device manually with devfs, you create a struct cdevsw or struct bdevsw yourself. In that device structure, one of the function pointers is to an ioctl function. You must define the particular values passed to the ioctl function in a header file accessible to the person compiling the application. A user application can also look up the device using the I/O Kit function call getMatchingServices and then use various I/O Kit calls to tune parameter instead. For more information on looking up a device driver from an application, see the document Accessing Hardware From Applications. You can also find additional information about writing an ioctl in The Design and Implementation of the 4.4 BSD Operating System. See the bibliography at the end of this document for more information. BSD sysctl API The system control (sysctl) API is specifically designed for kernel parameter tuning. This functionality supersedesthe syscall API, and also provides an easy way to tune simple kernel parameters without actually needing to write a handler routine in the kernel. The sysctl namespace is divided into several broad categories corresponding to the purpose of the parameters in it. Some of these areas include ● kern—general kernel parameters ● vm—virtual memory options ● fs—filesystem options ● machdep—machine dependent settings ● net—network stack settings ● debug—debugging settings ● hw—hardware parameters (generally read-only) ● user—parameters affecting user programs ● ddb—kernel debugger Most of the time, programs use the sysctl call to retrieve the current value of a kernel parameter. For example, in OS X, the hw sysctl group includesthe option ncpu, which returnsthe number of processorsin the current computer (or the maximum number of processors supported by the kernel on that particular computer, whichever is less). Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 117The sysctl API can also be used to modify parameters (though most parameters can only be changed by the root). For example, in the net hierarchy, net.inet.ip.forwarding can be set to 1 or 0, to indicate whether the computer should forward packets between multiple interfaces (basic routing). General Information on Adding a sysctl When adding a sysctl, you must do all of the following first: ● add the following includes: #include #include #include #include ● add -no-cpp-precomp to your compiler options in Project Builder (or to CFLAGS in your makefile if building by hand). Adding a sysctl Procedure Call Adding a system control (sysctl) was once a daunting task requiring changes to dozens of files. With the current implementation, a system control can be added simply by writing the appropriate handler functions and then registering the handler with the system at runtime. The old-style sysctl, which used fixed numbers for each control, is deprecated. Note: Because this is largely a construct of the BSD subsystem, all path names in this section can be assumed to be from /path/to/xnu-version/bsd/. Also, you may safely assume that all program code snippets should go into the main source file for your subsystem or module unless otherwise noted, and that in the case of modules, function calls should be made from your start or stop routines unless otherwise noted. The preferred way of adding a sysctl looks something like the following: SYSCTL_PROC(_hw, OID_AUTO, l2cr, CTLTYPE_INT|CTLFLAG_RW, &L2CR, 0, &sysctl_l2cr, "I", "L2 Cache Register"); Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 118The _PROC part indicates that you are registering a procedure to provide the value (as opposed to simply reading from a static address in kernel memory). _hw is the top level category (in this case, hardware), and OID_AUTO indicates that you should be assigned the next available control ID in that category (as opposed to the old-style, fixed ID controls). l2cr is the name of your control, which will be used by applications to look up the number of your control using sysctlbyname. Note: Not all top level categories will necessarily accept the addition of a user-specified new-style sysctl. If you run into problems, you should try a different top-level category. CTLTYPE_INT indicates that the value being changed is an integer. Other legal values are CTLTYPE_NODE, CTLTYPE_STRING, CTLTYPE_QUAD, and CTLTYPE_OPAQUE (also known as CTLTYPE_STRUCT). CTLTYPE_NODE isthe only one that isn’tsomewhat obvious. It refersto a node in the sysctl hierarchy that isn’t directly usable, but instead is a parent to other entries. Two examples of nodes are hw and kern. CTLFLAG_RW indicatesthat the value can be read and written.Other legal values are CTLFLAG_RD, CTLFLAG_WR, CTLFLAG_ANYBODY, and CTLFLAG_SECURE. CTLFLAG_ANYBODY means that the value should be modifiable by anybody. (The default is for variables to be changeable only by root.) CTLFLAG_SECURE means that the variable can be changed only when running at securelevel <= 0 (effectively, in single-user mode). L2CR is the location where the sysctl will store its data. Since the address is set at compile time, however, this must be a global variable or a static local variable. In this case, L2CR is a global of type unsigned int. The number 0 is a second argument that is passed to your function. This can be used, for example, to identify which sysctl was used to call your handler function if the same handler function is used for more than one control. In the case of strings, this is used to store the maximum allowable length for incoming values. sysctl_l2cr is the handler function for this sysctl. The prototype for these functions is of the form static int sysctl_l2cr SYSCTL_HANDLER_ARGS; If the sysctl is writable, the function may either use sysctl_handle_int to obtain the value passed in from user space and store it in the default location or use the SYSCTL_IN macro to store it into an alternate buffer. This function must also use the SYSCTL_OUT macro to return a value to user space. "I" indicates that the argument should refer to a variable of type integer (or a constant, pointer, or other piece of data of equivalent width), as opposed to "L" for a long, "A" for a string, "N" for a node (a sysctl that is the parent of a sysctl category or subcategory), or "S" for a struct. "L2 Cache Register" is a human-readable description of your sysctl. In order for a control to be accessible from an application, it must be registered. To do this, you do the following: Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 119sysctl_register_oid(&sysctl__hw_l2cr); You should generally do this in an init routine for a loadable module. If your code is not part of a loadable module, you should add your sysctl to the list of built-in OIDs in the file kern/sysctl_init.c. If you study the SYSCTL_PROC constructor macro, you will notice that sysctl__hw_l2cr is the name of a variable created by that macro. This meansthat the SYSCTL_PROC line must be before sysctl_register_oid in the file, and must be in the same (or broader) scope. This name is in the form of sysctl_ followed by the name of it’s parent node, followed by another underscore ( _ ) followed by the name of your sysctl. A similar function, sysctl_unregister_oid exists to remove a sysctl from the registry. If you are writing a loadable module, you should be certain to do this when your module is unloaded. In addition to registering your handler function, you also have to write the function. The following is a typical example static int myhandler SYSCTL_HANDLER_ARGS { int error, retval; error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); if (!error && req->newptr) { /* We have a new value stored in the standard location.*/ /* Do with it as you see fit here. */ printf("sysctl_test: stored %d\n", SCTEST); } else if (req->newptr) { /* Something was wrong with the write request */ /* Do something here if you feel like it.... */ } else { /* Read request. Always return 763, just for grins. */ printf("sysctl_test: read %d\n", SCTEST); retval=763; error=SYSCTL_OUT(req, &retval, sizeof retval); } /* In any case, return success or return the reason for failure */ return error; Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 120} This demonstrates the use of SYSCTL_OUT to send an arbitrary value out to user space from the sysctl handler. The “phantom” req argument is part of the function prototype when the SYSCTL_HANDLER_ARGS macro is expanded, as is the oidp variable used elsewhere. The remaining arguments are a pointer (type indifferent) and the length of data to copy (in bytes). This code sample also introduces a new function, sysctl_handle_int, which takes the arguments passed to the sysctl, and writes the integer into the usual storage area (L2CR in the earlier example, SCTEST in this one). If you want to see the new value without storing it (to do a sanity check, for example), you should instead use the SYSCTL_IN macro, whose arguments are the same as SYSCTL_OUT. Registering a New Top Level sysctl In addition to adding new sysctl options, you can also add a new category or subcategory. The macro SYSCTL_DECL can be used to declare a node that can have children. This requires modifying one additional file to create the child list. For example, if your main C file does this: SYSCTL_DECL(_net_newcat); SYSCTL_NODE(_net, OID_AUTO, newcat, CTLFLAG_RW, handler, "new category"); then this is basically the same thing as declaring extern sysctl_oid_list sysctl__net_newcat_children in your program. In order for the kernel to compile, or the module to link, you must then add this line: struct sysctl_oid_list sysctl__net_newcat_children; If you are not writing a module, this should go in the file kern/kern_newsysctl.c. Otherwise, it should go in one of the files of your module. Once you have created this variable, you can use _net_newcat as the parent when creating a new control. As with any sysctl, the node (sysctl__net_newcat) must be registered with sysctl_register_oid and can be unregistered with sysctl_unregister_oid. Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 121Note: When creating a top level sysctl, parent is simply left blank, for example, SYSCTL_NODE( , OID_AUTO, _topname, flags, handler_fn, "desc"); Adding a Simple sysctl If your sysctl only needsto read a value out of a variable, then you do not need to write a function to provide access to that variable. Instead, you can use one of the following macros: ● SYSCTL_INT(parent, nbr, name, access, ptr, val, descr) ● SYSCTL_LONG(parent, nbr, name, access, ptr, descr) ● SYSCTL_STRING(parent, nbr, name, access, arg, len, descr) ● SYSCTL_OPAQUE(parent, nbr, name, access, ptr, len, descr) ● SYSCTL_STRUCT(parent, nbr, name, access, arg, type, descr) The first four parameters for each macro are the same as for SYSCTL_PROC (described in the previous section) as is the last parameter. The len parameter (where applicable) gives a length of the string or opaque object in bytes. The arg parameters are pointersjust like the ptr parameters. However, the parameters named ptr are explicitly described as pointers because you must explicitly use the “address of” (&) operator unless you are already working with a pointer. Parameters called arg either operate on base types that are implicitly pointers or add the & operator in the appropriate place during macro expansion. In both cases, the argument should refer to the integer, character, or other object that the sysctl will use to store the current value. The type parameter is the name of the type minus the “struct”. For example, if you have an object of type struct scsipi, then you would use scsipi as that argument. The SYSCTL_STRUCT macro is functionally equivalent to SYSCTL_OPAQUE, except that it hides the use of sizeof. Finally, the val parameter for SYSCTL_INT is a default value. If the value passed in ptr is NULL, this value is returned when the sysctl is used. You can use this, for example, when adding a sysctl that is specific to certain hardware or certain compile options. One possible example of this might be a special value for feature.version that means “not present.” If that feature became available (for example, if a module were loaded by some user action), it could then update that pointer. If that module were subsequently unloaded, it could set the pointer back to NULL. Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 122Calling a sysctl From User Space Unlike RPC, sysctl requires explicit intervention on the part of the programmer. To complicate thingsfurther, there are two different ways of calling sysctl functions, and neither one worksfor every control. The old-style sysctl call can only invoke a control if it is listed in a static OID table in the kernel. The new-style sysctlbyname call will work for any user-added sysctl, but not for those listed in the static table. Occasionally, you will even find a control that isregistered in both ways, and thus available to both calls. In order to understand the distinction, you must first consider the functions used. The sysctlbyname System Call If you are calling a sysctl that was added using the new sysctl method (including any sysctl that you may have added), then your sysctl does not have a fixed number that identifies it, since it was added dynamically to the system. Since there is no approved way to get this number from user space, and since the underlying implementation is not guaranteed to remain the same in future releases, you cannot call a dynamically added control using the sysctl function. Instead, you must use sysctlbyname. sysctlbyname(char *name, void *oldp, size_t *oldlenp, void *newp, u_int newlen) The parameter name is the name of the sysctl, encoded as a standard C string. The parameter oldp is a pointer to a buffer where the old value will be stored. The oldlenp parameter is a pointer to an integer-sized buffer that holds the current size of the oldp buffer. If the oldp buffer is not large enough to hold the returned data, the call will fail with errno set to ENOMEM, and the value pointed to by oldlenp will be changed to indicate the buffer size needed for a future call to succeed. Here is an example for reading an integer, in this case a buffer size. int get_debug_bufsize() { char *name="debug.bpf_bufsize"; int bufsize, retval; size_t len; len=4; retval=sysctlbyname(name, &bufsize, &len, NULL, 0); /* Check retval here */ return bufsize; } Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 123The sysctl System Call The sysctlbyname system call is the recommended way to call system calls. However, not every built-in system control is registered in the kernel in such a way that it can be called with sysctlbyname. For this reason, you should also be aware of the sysctl system call. Note: If you are adding a sysctl, it will be accessible using sysctlbyname. You should use this system call only if the sysctl you need cannot be retrieved using sysctlbyname. In particular, you should not assume that future versions of sysctl will be backed by traditional numeric OIDs except for the existing legacy OIDs, which will be retained for compatibility reasons. The sysctl system call is part of the original historical BSD implementation of system controls. You should not depend on its use for any control that you might add to the system. The classic usage of sysctl looks like the following sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, u_int newlen) System controls, in this form, are based on the MIB, or Management Information Base architecture. A MIB is a list of objects and identifiers for those objects. Each object identifier, or OID, is a list of integers that represent a tokenization of a path through the sysctl tree. For example, if the hw class of sysctl is number 3, the first integer in the OID would be the number 3. If the l2cr option is built into the system and assigned the number 75, then the second integer in the OID would be 75. To put it another way, each number in the OID is an index into a node’s list of children. Here is a short example of a call to get the bus speed of the current computer: int get_bus_speed() { int mib[2], busspeed, retval; unsigned int miblen; size_t len; mib[0]=CTL_HW; mib[1]=HW_BUS_FREQ; miblen=2; len=4; retval=sysctl(mib, miblen, &busspeed, &len, NULL, 0); Boundary Crossings BSD sysctl API 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 124/* Check retval here */ return busspeed; } For more information on the sysctl system call, see the manual page sysctl. Memory Mapping and Block Copying Memory mapping is one of the more common means of communicating between two applications or between an application and the kernel. While occasionally used by itself, it is usually used in conjunction with one of the other means of boundary crossing. One way of using memory mapping is known as shared memory. In this form, one or more pages of memory are mapped into the address space of two processes. Either process can then access or modify the data stored in those shared pages. This is useful when moving large quantities of data between processes, as it allows direct communication without multiple user-kernel boundary crossings. Thus, when moving large amounts of data between processes, this is preferable to traditional message passing. The same holds true with memory mapping between an application and the kernel. The BSD sysctl and syscall interfaces (and to an extent, Mach IPC) were designed to transfer small units of data of known size, such as an array of four integers. In this regard, they are much like a traditional C function call. If you need to pass a large amount of data to a function in C, you should pass a pointer. This is also true when passing data between an application and the kernel, with the addition of memory mapping or copying to allow that pointer to be dereferenced in the kernel. There are a number of limitations to the way that memory mapping can be used to exchange data between an application and the kernel. For one, memory allocated in the kernel cannot be written to by applications, including those running as root (unless the kernel is running in an insecure mode, such as single user mode). For this reason, if a buffer must be modified by an application, the buffer must be allocated by that program, not by the kernel. When you use memory mapping for passing data to the kernel, the application allocates a block of memory and fillsit with data. It then performs a system call that passesthe addressto the appropriate function in kernel space. It should be noted, however, that the address being passed is a virtual address, not a physical address, and more importantly, it is relative to the address space of the program, which is not the same as the address space of the kernel. Since the address is a user-space virtual address, the kernel must call special functions to copy the block of memory into a kernel buffer or to map the block of memory into the kernel’s address space. Boundary Crossings Memory Mapping and Block Copying 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 125In the OS X kernel, data is most easily copied into kernel space with the BSD copyin function, and back out to user space with the copyout function. For large blocks of data, entire pages will be memory mapped using copy-on-write. For this reason, it is generally not useful to do memory mapping by hand. Getting data from the kernel to an application can be done in a number of ways. The most common method is the reverse of the above, in which the application passes in a buffer pointer, the kernel scribbles on a chunk of data, uses copyout to copy the buffer data into the address space of the application, and returns KERN_SUCCESS. Note that this is really using the buffer allocated in the application, even though the physical memory may have actually been allocated by the kernel. Assuming the kernel frees its reference to the buffer, no memory is wasted. A special case of memory mapping occurs when doing I/O to a device from user space. Since I/O operations can, in some cases, be performed by DMA hardware that operates based on physical addressing, it is vital that the memory associated with I/O buffers not be paged out while the hardware is copying data to or from the buffer. For this reason, when a driver or other kernel entity needs a buffer for I/O, it must take steps to mark it as not pageable. This step is referred to as wiring the pages in memory. Wiring pages into memory can also be helpful where high bandwidth, low latency communication is desired, as it prevents shared buffers from being paged out to disk. In general, however, this sort of workaround should be unnecessary, and is considered to be bad programming practice. Pages can be wired in two ways. When a memory region is allocated, it may be allocated in a nonpageable fashion. The details of allocating memory for I/O differ, depending on what part of the kernel you are modifying. This is described in more detail in the appropriate sections of this document, or in the case of the I/O Kit, in the API reference documentation (available from the developer section of Apple’s web site). Alternately, individual pages may be wired after allocation. The recommended way to do this is through a call to vm_wire in BSD parts of the kernel, with mlock from applications (but only by processes running as root), or with IOMemoryDescriptor::prepare in the I/O Kit. Because this can fail for a number of reasons, it is particularly crucial to check return values when wiring memory. The vm_wire call and other virtual memory topics are discussed in more detail in “Memory and Virtual Memory” (page 61). The IOMemoryDescriptor class is described in more detail in the I/O Kit API reference available from the developer section of Apple’s web site. Boundary Crossings Memory Mapping and Block Copying 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 126Summary Crossing the user-kernel boundary is not a trivial task. Many mechanisms exist for this communication, and each one has specific advantages and disadvantages, depending on the environment and bandwidth requirements. Security is a constant concern to prevent inadvertently allowing one program to access data or files from another program or user. It is every kernel programmer’s personal responsibility to take security into account any time that data crosses the user-kernel boundary. Boundary Crossings Summary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 127This chapter is not intended as an introduction to synchronization. It is assumed that you have some understanding of the basic concepts of locks and semaphores already. If you need additional background reading,synchronization is covered in most introductory operating systemstexts. However,since synchronization in the kernel is somewhat different from locking in an application this chapter does provide a brief overview to help ease the transition, or for experienced kernel developers, to refresh your memory. As an OS X kernel programmer, you have many choices of synchronization mechanisms at your disposal. The kernel itself provides two such mechanisms: locks and semaphores. A lock is used for basic protection of shared resources. Multiple threads can attempt to acquire a lock, but only one thread can actually hold it at any given time (at least for traditional locks—more on this later). While that thread holds the lock, the other threads must wait. There are several different types of locks, differing mainly in what threads do while waiting to acquire them. A semaphore is much like a lock, except that a finite number of threads can hold itsimultaneously. Semaphores can be thought of as being much like piles of tokens. Multiple threads can take these tokens, but when there are none left, a thread must wait until another thread returns one. It is important to note that semaphores can be implemented in many different ways,so Mach semaphores may not behave in the same way assemaphores on other platforms. In addition to locks and semaphores, certain low-level synchronization primitives like test and set are also available, along with a number of other atomic operations. These additional operations are described in libkern/gen/OSAtomicOperations.c in the kernelsources. Such atomic operations may be helpful if you do not need something asrobust as a full-fledged lock orsemaphore. Since they are not generalsynchronization mechanisms, however, they are beyond the scope of this chapter. Semaphores Semaphores and locks are similar, except that with semaphores, more than one thread can be doing a given operation at once. Semaphores are commonly used when protecting multiple indistinct resources. For example, you might use a semaphore to prevent a queue from overflowing its bounds. OS X uses traditional counting semaphores rather than binary semaphores (which are essentially locks). Mach semaphores obey Mesa semantics—that is, when a thread is awakened by a semaphore becoming available, it is not executed immediately. This presents the potential for starvation in multiprocessor situations when the 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 128 Synchronization Primitivessystem is under low overall load because other threads could keep downing the semaphore before the just-woken thread gets a chance to run. This is something that you should consider carefully when writing applications with semaphores. Semaphores can be used any place where mutexes can occur. This precludes their use in interrupt handlers or within the context of the scheduler, and makes it strongly discouraged in the VM system. The public API for semaphores is divided between the MIG–generated task.h file (located in your build output directory, included with #include ) and osfmk/mach/semaphore.h (included with #include ). The public semaphore API includes the following functions: kern_return_t semaphore_create(task_t task, semaphore_t *semaphore, int policy, int value) kern_return_t semaphore_signal(semaphore_t semaphore) kern_return_t semaphore_signal_all(semaphore_t semaphore) kern_return_t semaphore_wait(semaphore_t semaphore) kern_return_t semaphore_destroy(task_t task, semaphore_t semaphore) kern_return_t semaphore_signal_thread(semaphore_t semaphore, thread_act_t thread_act) which are described in or xnu/osfmk/mach/semaphore.h (except for create and destroy, which are described in . The use of these functions is relatively straightforward with the exception of the semaphore_create, semaphore_destroy, and semaphore_signal_thread calls. The value and semaphore parametersfor semaphore_create are exactly what you would expect—a pointer to the semaphore structure to be filled out and the initial value for the semaphore, respectively. The task parameter refers to the primary Mach task that will “own” the lock. This task should be the one that is ultimately responsible for the subsequent destruction of the semaphore. The task parameter used when calling semaphore_destroy must match the one used when it was created. For communication within the kernel, the task parameter should be the result of a call to current_task. For synchronization with a user process, you need to determine the underlying Mach task for that process by calling current_task on the kernel side and mach_task_self on the application side. task_t current_task(void); // returns the kernel task port task_t mach_task_self(void);// returns the task port of the current thread Synchronization Primitives Semaphores 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 129Note: In the kernel, be sure to always use current_task. In the kernel, mach_task_self returns a pointer to the kernel’s VM map, which is probably not what you want. The details of user-kernel synchronization are beyond the scope of this document. The policy parameter is passed asthe policy for the wait queue contained within the semaphore. The possible values are defined in osfmk/mach/sync_policy.h. Current possible values are: ● SYNC_POLICY_FIFO ● SYNC_POLICY_FIXED_PRIORITY ● SYNC_POLICY_PREPOST The FIFO policy is, asthe name suggests, first-in-first-out. The fixed priority policy causes wait queue reordering based on fixed thread priority policies. The prepost policy causes the semaphore_signal function to not increment the counter if no threads are waiting on the queue. This policy is needed for creating condition variables (where a thread is expected to always wait until signalled). See the section “Wait Queues and Wait Primitives” (page 87) for more information. The semaphore_signal_thread call takes a particular thread from the wait queue and places it back into one of the scheduler’s wait-queues, thus making that thread available to be scheduled for execution. If thread_act is NULL, the first thread in the queue is similarly made runnable. With the exception of semaphore_create and semaphore_destroy, these functions can also be called from user space via RPC. See “Calling RPC From User Applications” (page 116) for more information. Condition Variables The BSD portion of OS X provides msleep, wakeup, and wakeup_one, which are equivalent to condition variables with the addition of an optional time-out. You can find these functions in sys/proc.h in the Kernel framework headers. msleep(void *channel, lck_mtx_t *mtx, int priority, const char *wmesg, struct timespec *timeout); msleep0(vvoid *channel, lck_mtx_t *mtx, int priority, const char *wmesg, uint64_t deadline); wakeup(void *channel); wakeup_one(void *channel); Synchronization Primitives Condition Variables 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 130The msleep call is similar to a condition variable. It puts a thread to sleep until wakeup or wakeup_one is called on that channel. Unlike a condition variable, however, you can set a timeout measured in clock ticks. This means that it is both a synchronization call and a delay. The prototypes follow: msleep(void *channel, lck_mtx_t *mtx, int priority, const char *wmesg, struct timespec *timeout); msleep0(vvoid *channel, lck_mtx_t *mtx, int priority, const char *wmesg, uint64_t deadline); wakeup(void *channel); wakeup_one(void *channel); The three sleep calls are similar except in the mechanism used for timeouts. The function msleep0 is not recommended for general use. In these functions, channel is a unique identifier representing a single condition upon which you are waiting. Normally, when msleep is used, you are waiting for a change to occur in a data structure. In such cases, it is common to use the address of that data structure as the value for channel, as this ensures that no code elsewhere in the system will be using the same value. The priority argument has three effects. First, when wakeup is called, threads are inserted in the scheduling queue at this priority. Second, if the bit (priority & PCATCH) is set, msleep0 does not allow signals to interrupt the sleep. Third, if the bit (priority & PDROP) is zero, msleep0 drops the mutex on sleep and reacquires it upon waking. If (priority & PDROP) is one, msleep0 drops the mutex if it has to sleep, but does not reacquire it. The subsystem argument is a short text string that represents the subsystem that is waiting on this channel. This is used solely for debugging purposes. The timeout argument is used to set a maximum wait time. The thread may wake sooner, however, if wakeup or wakeup_one is called on the appropriate channel. It may also wake sooner if a signal isreceived, depending on the value of priority. In the case of msleep0, this is given as a mach abstime deadline. In the case of msleep, this is given in relative time (seconds and nanoseconds). Outside the BSD portion of the kernel, condition variables may be implemented using semaphores. Synchronization Primitives Condition Variables 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 131Locks OS X (and Mach in general) has three basic types of locks: spinlocks, mutexes, and read-write locks. Each of these has different uses and different problems. There are also many other types of locks that are not implemented in OS X, such as spin-sleep locks, some of which may be useful to implement for performance comparison purposes. Spinlocks A spinlock is the simplest type of lock. In a system with a test-and-set instruction or the equivalent, the code looks something like this: while (test_and_set(bit) != 0); In other words, until the lock is available, it simply “spins” in a tight loop that keeps checking the lock until the thread’s time quantum expires and the next thread begins to execute. Since the entire time quantum for the first thread must complete before the next thread can execute and (possibly) release the lock, a spinlock is very wasteful of CPU time, and should be used only in places where a mutex cannot be used, such as in a hardware exception handler or low-level interrupt handler. Note that a thread may not block while holding a spinlock, because that could cause deadlock. Further, preemption is disabled on a given processor while a spinlock is held. There are three basic types of spinlocks available in OS X: lck_spin_t (which supersedes simple_lock_t), usimple_lock_t, and hw_lock_t. You are strongly encouraged to not use hw_lock_t; it is only mentioned for the sake of completeness. Of these, only lck_spin_t is accessible from kernel extensions. The u in usimple stands for uniprocessor, because they are the only spinlocks that provide actual locking on uniprocessorsystems. Traditionalsimple locks, by contrast, disable preemption but do notspin on uniprocessor systems. Note that in most contexts, it is not useful to spin on a uniprocessor system, and thus you usually only need simple locks. Use of usimple locks is permissible for synchronization between thread context and interrupt context or between a uniprocessor and an intelligent device. However, in most cases, a mutex is a better choice. Important: Simple and usimple locks that could potentially be shared between interrupt context and thread context must have their use coordinated with spl (see glossary). The IPL (interrupt priority level) must always be the same when acquiring the lock, otherwise deadlock may result. (This is not an issue for kernel extensions, however, as the spl functions cannot be used there.) The spinlock functions accessible to kernel extensions consist of the following: Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 132extern lck_spin_t *lck_spin_alloc_init( lck_grp_t *grp, lck_attr_t *attr); extern void lck_spin_init( lck_spin_t *lck, lck_grp_t *grp, lck_attr_t *attr); extern void lck_spin_lock( lck_spin_t *lck); extern void lck_spin_unlock( lck_spin_t *lck); extern void lck_spin_destroy( lck_spin_t *lck, lck_grp_t *grp); extern void lck_spin_free( lck_spin_t *lck, lck_grp_t *grp); extern wait_result_t lck_spin_sleep( lck_spin_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible); extern wait_result_t lck_spin_sleep_deadline( lck_spin_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible, uint64_t deadline); Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 133Prototypes for these locks can be found in . The arguments to these functions are described in detail in “Using Lock Functions” (page 139). Mutexes A mutex, mutex lock, or sleep lock, is similar to a spinlock, except that instead of constantly polling, it places itself on a queue of threads waiting for the lock, then yields the remainder of its time quantum. It does not execute again until the thread holding the lock wakesit (or in some userspace variations, until an asynchronous signal arrives). Mutexes are more efficient than spinlocksfor most purposes. However, they are less efficient in multiprocessing environments where the expected lock-holding time is relatively short. If the average time is relatively short but occasionally long, spin/sleep locks may be a better choice. Although OS X does not support spin/sleep locksin the kernel, they can be easily implemented on top of existing locking primitives. If your code performance improves as a result of using such locks, however, you should probably look for ways to restructure your code, such as using more than one lock or moving to read-write locks, depending on the nature of the code in question. See “Spin/Sleep Locks” (page 138) for more information. Because mutexes are based on blocking, they can only be used in places where blocking is allowed. For this reason, mutexes cannot be used in the context of interrupt handlers. Interrupt handlers are not allowed to block because interrupts are disabled for the duration of an interrupt handler, and thus, if an interrupt handler blocked, it would prevent the scheduler from receiving timer interrupts, which would prevent any other thread from executing, resulting in deadlock. For a similar reason, it is not reasonable to block within the scheduler. Also, blocking within the VM system can easily lead to deadlock if the lock you are waiting for is held by a task that is paged out. However, unlike simple locks, it is permissible to block while holding a mutex. This would occur, for example, if you took one lock, then tried to take another, but the second lock was being held by another thread. However, this is generally not recommended unless you carefully scrutinize all uses of that mutex for possible circular waits, as it can result in deadlock. You can avoid this by always taking locks in a certain order. In general, blocking while holding a mutex specific to your code isfine aslong as you wrote your code correctly, but blocking while holding a more global mutex is probably not, since you may not be able to guarantee that other developers’ code obeys the same ordering rules. A Mach mutex is of type mutex_t. The functions that operate on mutexes include: lck_mtx_t *lck_mtx_alloc_init(lck_grp_t *grp, lck_attr_t *attr); extern void lck_mtx_init( lck_mtx_t *lck, Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 134lck_grp_t *grp, lck_attr_t *attr); extern void lck_mtx_lock( lck_mtx_t *lck); extern void lck_mtx_unlock( lck_mtx_t *lck); extern void lck_mtx_destroy(lck_mtx_t *lck, lck_grp_t *grp); extern void lck_mtx_free( lck_mtx_t *lck, lck_grp_t *grp); extern wait_result_tlck_mtx_sleep( lck_mtx_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible); extern wait_result_tlck_mtx_sleep_deadline( lck_mtx_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible, uint64_t deadline); extern void lck_mtx_assert( lck_mtx_t *lck, unsigned int type); as described in . The arguments to these functions are described in detail in “Using Lock Functions” (page 139). Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 135Read-Write Locks Read-write locks (also called shared-exclusive locks) are somewhat different from traditional locks in that they are not always exclusive locks. A read-write lock is useful when shared data can be reasonably read concurrently by multiple threads except while a thread is modifying the data. Read-write locks can dramatically improve performance if the majority of operations on the shared data are in the form of reads(since it allows concurrency), while having negligible impact in the case of multiple writes. A read-write lock allows this sharing by enforcing the following constraints: ● Multiple readers can hold the lock at any time. ● Only one writer can hold the lock at any given time. ● A writer must block until all readers have released the lock before obtaining the lock for writing. ● Readers arriving while a writer is waiting to acquire the lock will block until after the writer has obtained and released the lock. The first constraint allows read sharing. The second constraint prevents write sharing. The third prevents read-write sharing, and the fourth prevents starvation of the writer by a steady stream of incoming readers. Mach read-write locks also provide the ability for a reader to become a writer and vice-versa. In locking terminology, an upgrade is when a reader becomes a writer, and a downgrade is when a writer becomes a reader. To prevent deadlock, some additional constraints must be added for upgrades and downgrades: ● Upgrades are favored over writers. ● The second and subsequent concurrent upgrades will fail, causing that thread’s read lock to be released. The first constraint is necessary because the reader requesting an upgrade is holding a read lock, and the writer would not be able to obtain a write lock until the reader releases its read lock. In this case, the reader and writer would wait for each other forever. The second constraint is necessary to prevents the deadlock that would occur if two readers wait for the other to release its read lock so that an upgrade can occur. The functions that operate on read-write locks are: extern lck_rw_t *lck_rw_alloc_init( lck_grp_t *grp, lck_attr_t *attr); extern void lck_rw_init( lck_rw_t *lck, lck_grp_t *grp, Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 136lck_attr_t *attr); extern void lck_rw_lock( lck_rw_t *lck, lck_rw_type_t lck_rw_type); extern void lck_rw_unlock( lck_rw_t *lck, lck_rw_type_t lck_rw_type); extern void lck_rw_lock_shared( lck_rw_t *lck); extern void lck_rw_unlock_shared( lck_rw_t *lck); extern void lck_rw_lock_exclusive( lck_rw_t *lck); extern void lck_rw_unlock_exclusive( lck_rw_t *lck); extern void lck_rw_destroy( lck_rw_t *lck, lck_grp_t *grp); extern void lck_rw_free( lck_rw_t *lck, lck_grp_t *grp); extern wait_result_t lck_rw_sleep( lck_rw_t *lck, lck_sleep_action_t lck_sleep_action, Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 137event_t event, wait_interrupt_t interruptible); extern wait_result_t lck_rw_sleep_deadline( lck_rw_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible, uint64_t deadline); This is a more complex interface than that of the other locking mechanisms, and actually is the interface upon which the other locks are built. The functions lck_rw_lock and lck_rw_lock lock and unlock a lock as either shared (read) or exclusive (write), depending on the value of lck_rw_type., which can contain either LCK_RW_TYPE_SHARED or LCK_RW_TYPE_EXCLUSIVE. You should always be careful when using these functions, as unlocking a lock held in shared mode using an exclusive call or vice-versa will lead to undefined results. The arguments to these functions are described in detail in “Using Lock Functions” (page 139). Spin/Sleep Locks Spin/sleep locks are not implemented in the OS X kernel. However, they can be easily implemented on top of existing locks if desired. For short waits on multiprocessor systems, the amount of time spent in the context switch can be greater than the amount of time spent spinning. When the time spent spinning while waiting for the lock becomes greater than the context switch overhead, however, mutexes become more efficient. For this reason, if there is a large degree of variation in wait time on a highly contended lock, spin/sleep locks may be more efficient than traditional spinlocks or mutexes. Ideally, a program should be written in such a way that the time spent holding a lock is always about the same, and the choice of locking is clear. However, in some cases, this is not practical for a highly contended lock. In those cases, you may consider using spin/sleep locks. Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 138The basic principle ofspin/sleep locksissimple. A thread takesthe lock if it is available. If the lock is not available, the thread may enter a spin cycle. After a certain period of time (usually a fraction of a time quantum or a small number of time quanta), the spin routine’s time-out is reached, and it returns failure. At that point, the lock places the waiting thread on a queue and puts it to sleep. In other variations on this design, spin/sleep locks determine whether to spin or sleep according to whether the lock-holding thread is currently on another processor (or is about to be). For short wait periods on multiprocessor computers, the spin/sleep lock is more efficient than a mutex, and roughly as efficient as a standard spinlock. For longer wait periods, the spin/sleep lock is significantly more efficient than the spinlock and only slightly less efficient than a mutex. There is a period near the transition between spinning and sleeping in which the spin/sleep lock may behave significantly worse than either of the basic lock types, however. Thus, spin/sleep locks should not be used unless a lock is heavily contended and has widely varying hold times. When possible, you should rewrite the code to avoid such designs. Using Lock Functions While most of the locking functions are straightforward, there are a few detailsrelated to allocating, deallocating, and sleeping on locks that require additional explanation. As the syntax of these functions is identical across all of the lock types, this section explains only the usage for spinlocks. Extending this to other lock types is left as a (trivial) exercise for the reader. The first thing you must do when allocating locks is to allocate a lock group and a lock attribute set. Lock groups are used to name locks for debugging purposes and to group locks by function for general understandability. Lock attribute sets allow you to set flags that alter the behavior of a lock. The following code illustrates how to allocate an attribute structure and a lock group structure for a lock. In this case, a spinlock is used, but with the exception of the lock allocation itself, the process is the same for other lock types. Listing 17-1 Allocating lock attributes and groups (lifted liberally from kern_time.c) lck_grp_attr_t *tz_slock_grp_attr; lck_grp_t *tz_slock_grp; lck_attr_t *tz_slock_attr; lck_spin_t *tz_slock; /* allocate lock group attribute and group */ tz_slock_grp_attr = lck_grp_attr_alloc_init(); lck_grp_attr_setstat(tz_slock_grp_attr); Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 139tz_slock_grp = lck_grp_alloc_init("tzlock", tz_slock_grp_attr); /* Allocate lock attribute */ tz_slock_attr = lck_attr_alloc_init(); //lck_attr_setdebug(tz_slock_attr); // set the debug flag //lck_attr_setdefault(tz_slock_attr); // clear the debug flag /* Allocate the spin lock */ tz_slock = lck_spin_alloc_init(tz_slock_grp, tz_slock_attr); The first argument to the lock initializer, of type lck_grp_t, is a lock group. This is used for debugging purposes, including lock contention profiling. The details of lock tracing are beyond the scope of this document, however, every lock must belong to a group (even if that group contains only one lock). The second argument to the lock initializer, of type lck_attr_t, contains attributes for the lock. Currently, the only attribute available islock debugging. This attribute can be set using lck_attr_setdebug and cleared with lck_attr_setdefault. To dispose of a lock, you simply call the matching free functions. For example: lck_spin_free(tz_slock, tz_slock_grp); lck_attr_free(tz_slock_attr); lck_grp_free(tz_slock_grp); lck_grp_attr_free(tz_slock_grp_attr); Note: While you can safely dispose of the lock attribute and lock group attribute structures, it is important to keep track of the lock group associated with a lock as long as the lock exists, since you will need to pass the group to the lock's matching free function when you deallocate the lock (generally at unload time). The other two interesting functions are lck_spin_sleep and lck_spin_sleep_deadline. These functions release a spinlock and sleep until an event occurs, then wake. The latter includes a timeout, at which point it will wake even if the event has not occurred. extern wait_result_t lck_spin_sleep( lck_rspin_t *lck, Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 140lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible); extern wait_result_t lck_spin_sleep_deadline( lck_spin_t *lck, lck_sleep_action_t lck_sleep_action, event_t event, wait_interrupt_t interruptible, uint64_t deadline); The parameter lck_sleep_action controls whether the lock will be reclaimed after sleeping prior to this function returning. The valid options are: LCK_SLEEP_DEFAULT Release the lock while waiting for the event, then reclaim it. Read-write locks are held in the same mode as they were originally held. LCK_SLEEP_UNLOCK Release the lock and return with the lock unheld. LCK_SLEEP_SHARED Reclaim the lock in shared mode (read-write locks only). LCK_SLEEP_EXCLUSIVE Reclaim the lock in exclusive mode (read-write locks only). The event parameter can be any arbitrary integer, but it must be unique across the system. To ensure uniqueness, a common programming practice isto use the address of a global variable (often the one containing a lock) as the event value. For more information on these events, see “Event and Timer Waits” (page 143). The parameter interruptible indicates whether the scheduler should allow the wait to be interrupted by asynchronous signals. If this is false, any false wakes will result in the process going immediately back to sleep (with the exception of a timer expiration signal, which will still wake lck_spin_sleep_deadline). Synchronization Primitives Locks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 141This chapter containsinformation about miscellaneousservices provided by the OS X kernel. For most projects, you will probably never need to use most of these services, but if you do, you will find it hard to do without them. This chapter containsthese sections:“Using Kernel Time Abstractions” (page 142),“Boot Option Handling” (page 146), “Queues” (page 147), and “Installing Shutdown Hooks” (page 148). Using Kernel Time Abstractions There are two basic groups of time abstractionsin the kernel. One group includesfunctionsthat provide delays and timed wake-ups. The other group includesfunctions and variablesthat provide the current wall clock time, the time used by a given process, and other similar information. This section describes both aspects of time from the perspective of the kernel. Obtaining Time Information There are a number of ways to get basic time information from within the kernel. The officially approved methods are those that Mach exports in kern/clock.h. These include the following: void clock_get_uptime(uint64_t *result); void clock_get_system_microtime( uint32_t *secs, uint32_t *microsecs); void clock_get_system_nanotime( uint32_t *secs, uint32_t *nanosecs); void clock_get_calendar_microtime( uint32_t *secs, uint32_t *microsecs); void clock_get_calendar_nanotime( uint32_t *secs, uint32_t *nanosecs); 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 142 Miscellaneous Kernel ServicesThe function clock_get_uptime returns a value in AbsoluteTime units. For more information on using AbsoluteTime, see “Using Mach Absolute Time Functions” (page 144). The functions clock_get_system_microtime and clock_get_system_nanotime return 32-bit integers containing seconds and microseconds or nanoseconds, respectively, representing the system uptime. The functions clock_get_calendar_microtime and clock_get_calendar_nanotime return 32-bit integers containing seconds and microseconds or nanoseconds, respectively, representing the current calendar date and time since the epoch (January 1, 1970). In some parts of the kernel, you may find other functions that return type mach_timespec_t. This type is similar to the traditional BSD struct timespec, except that fractions of a second are measured in nanoseconds instead of microseconds: struct mach_timespec { unsigned int tv_sec; clock_res_t tv_nsec; }; typedef struct mach_timespec *mach_timespec_t; In addition to the traditional Mach functions, if you are writing code in BSD portions of the kernel you can also get the current calendar (wall clock) time as a BSD timeval, as well as find out the calendar time when the system was booted by doing the following: #include struct timeval tv=time; /* calendar time */ struct timeval tv_boot=boottime; /* calendar time when booting occurred */ For other information, you should use the Mach functions listed previously. Event and Timer Waits Each part of the OS X kernel has a distinct API for waiting a certain period of time. In most cases, you can call these functions from other parts of the kernel. The I/O Kit provides IODelay and IOSleep. Mach provides functions based on AbsoluteTime, as well as a few based on microseconds. BSD provides msleep. Miscellaneous Kernel Services Using Kernel Time Abstractions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 143Using IODelay and IOSleep IODelay, provided by the I/O Kit, abstracts a timed spin. If you are delaying for a short period of time, and if you need to be guaranteed that your wait will not be stopped prematurely by delivery of asynchronous events, this is probably the best choice. If you need to delay for several seconds, however, this is a bad choice, because the CPU that executes the wait will spin until the time has elapsed, unable to handle any other processing. IOSleep puts the currently executing thread to sleep for a certain period of time. There is no guarantee that your thread will execute after that period of time, nor isthere a guarantee that your thread will not be awakened by some other event before the time has expired. It is roughly equivalent to the sleep call from user space in this regard. The use of IODelay and IOSleep are straightforward. Their prototypes are: IODelay(unsigned microseconds); IOSleep(unsigned milliseconds); Note the differing units. It is not practical to put a thread to sleep for periods measured in microseconds, and spinning for several milliseconds is also inappropriate. Using Mach Absolute Time Functions The following Mach time functions are commonly used. Several others are described in osfmk/kern/clock.h. Note: These are not the same functions as those listed in kern/clock.h in the Kernel framework. These functions are not exposed to kernel extensions, and are only for use within the kernel itself. void delay(uint64_t microseconds); void clock_delay_until(uint64_t deadline); void clock_absolutetime_interval_to_deadline(uint64_t abstime, uint64_t *result); void nanoseconds_to_absolutetime(uint64_t nanoseconds, uint64_t *result); void absolutetime_to_nanoseconds(uint64_t abstime, uint64_t *result); These functions are generally straightforward. However, a few points deserve explanation. Unless specifically stated, all times, deadlines, and so on, are measured in abstime units. The abstime unit is equal to the length of one bus cycle,so the duration is dependent on the busspeed of the computer. For thisreason, Mach provides conversion routines between abstime units and nanoseconds. Miscellaneous Kernel Services Using Kernel Time Abstractions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 144Many time functions, however, provide time in seconds with nanosecond remainder. In this case, some conversion is necessary. For example, to obtain the current time as a mach abstime value, you might do the following: uint32_t secpart; uint32_t nsecpart; uint64_t nsec, abstime; clock_get_calendar_nanotime(&secpart, &nsecpart); nsec = nsecpart + (1000000000ULL * secpart); //convert seconds to nanoseconds. nanoseconds_to_absolutetime(nsec, &abstime); The abstime value is now stored in the variable abstime. Using msleep In addition to Mach and I/O Kit routines, BSD provides msleep, which is the recommended way to delay in the BSD portions of the kernel. In other parts of the kernel, you should either use wait_queue functions or use assert_wait and thread_wakeup functions, both of which are closely tied to the Mach scheduler, and are described in “Kernel Thread APIs” (page 85). Because this function is more commonly used for waiting on events, it is described further in “Condition Variables” (page 130). Handling Version Dependencies Many time-related functions such as clock_get_uptime changed as a result of the transition to KPIs in OS X v.10.4. While these changes result in a cleaner interface, this can prove challenging if you need to make a kernel extension that needs to obtain time information across multiple versions of OS X in a kernel extension that would otherwise have no version dependencies (such as an I/O Kit KEXT). Here is a list of time-related functions that are available in both pre-KPI and KPI versions of OS X: uint64_t mach_absolute_time(void); Declared In: Dependency: com.apple.kernel.mach This function returns a Mach absolute time value for the current wall clock time in units of uint64_t. Miscellaneous Kernel Services Using Kernel Time Abstractions 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 145void microtime(struct timeval *tv); Declared In: Dependency: com.apple.kernel.bsd This function returns a timeval struct containing the current wall clock time. void microuptime(struct timeval *tv); Declared In: Dependency: com.apple.kernel.bsd This function returns a timeval struct containing the current uptime. void nanotime(struct timespec *ts); Declared In: Dependency: com.apple.kernel.bsd This function returns a timespec struct containing the current wall clock time. void nanouptime(struct timespec *ts); Declared In: Dependency: com.apple.kernel.bsd This function returns a timespec struct containing the current uptime. Note: The structure declarationsfor struct timeval and struct timespec differ between 10.3 and 10.4 in their use of int, int32_t, and long data types. However, because the structure packing for the underlying data types is identical in the 32-bit world, these structures are assignment compatible. In addition to these APIs, the functionality marked __APPLE_API_UNSTABLE in was adopted as-is in OS X v.10.4 and is no longer marked unstable. Boot Option Handling OS X provides a simple parse routine, PE_parse_boot_arg, for basic boot argument passing. It supports both flags and numerical value assignment. For obtaining values, you write code similar to the following: unsigned int argval; if (PE_parse_boot_arg("argflag", &argval)) { Miscellaneous Kernel Services Boot Option Handling 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 146/* check for reasonable value */ if (argval < 10 || argval > 37) argval = 37; } else { /* use default value */ argval = 37; } Since PE_parse_boot_arg returns a nonzero value if the flag exists, you can check for the presence of a flag by using a flag that starts with a dash (-) and ignoring the value stored in argvalue. The PE_parse_boot_arg function can also be used to get a string argument. To do this, you must pass in the address of an array of type char as the second argument. The behavior of PE_parse_boot_arg is undefined if a string is passed in for a numeric variable or vice versa. Its behavior is also undefined if a string exceeds the storage space allocated. Be sure to allow enough space for the largest reasonable string including a null delimiter. No attempt is made at bounds checking, since an overflow is generally a fatal error and should reasonably prevent booting. Queues As part of its BSD infrastructure, the OS X kernel provides a number of basic support macrosto simplify handling of linked lists and queues. These are implemented as C macros, and assume a standard C struct. As such, they are probably not suited for writing code in C++. The basic types of lists and queues included are ● SLIST, a singly linked list ● STAILQ, a singly linked tail queue ● LIST, a doubly linked list ● TAILQ, a doubly linked tail queue SLIST is ideal for creating stacks or for handling large sets of data with few or no removals. Arbitrary removal, however, requires an O(n) traversal of the list. STAILQ is similar to SLIST except that it maintains pointers to both ends of the queue. This makes it ideal for simple FIFO queues by adding entries at the tail and fetching entries from the head. Like SLIST, it is inefficient to remove arbitrary elements. Miscellaneous Kernel Services Queues 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 147LIST is a doubly linked version of SLIST. The extra pointersrequire additionalspace, but allow O(1) (constant time) removal of arbitrary elements and bidirectional traversal. TAILQ is a doubly linked version of STAILQ. Like LIST, the extra pointers require additional space, but allow O(1) (constant time) removal of arbitrary elements and bidirectional traversal. Because their functionality is relatively simple, their use is equally straightforward. These macros can be found in xnu/bsd/sys/queue.h. Installing Shutdown Hooks Although OS X does not have traditional BSD-style shutdown hooks, the I/O Kit provides equivalent functionality in recent versions. Since the I/O Kit provides this functionality, you must call it from C++ code. To register for notification, you call registerSleepWakeInterest (described in IOKit/RootDomain.h) and register for sleep notification. If the system is about to be shut down, your handler is called with the message type kIOMessageSystemWillPowerOff. If the system is about to reboot, your handler gets the message type kIOMessageSystemWillRestart. If the system is about to reboot, your handler gets the message type kIOMessageSystemWillSleep. If you no longer need to receive notification (for example, if your KEXT gets unloaded), be certain to release the notifier with IONofitier::release to avoid a kernel panic on shutdown. For example, the following sample KEXT registersforsleep notifications, then logs a message with IOLog when a sleep notification occurs: #include #include #include #include #include #define ALLOW_SLEEP 1 IONotifier *notifier; extern "C" { Miscellaneous Kernel Services Installing Shutdown Hooks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 148IOReturn mySleepHandler( void * target, void * refCon, UInt32 messageType, IOService * provider, void * messageArgument, vm_size_t argSize ) { IOLog("Got sleep/wake notice. Message type was %d\n", messageType); #if ALLOW_SLEEP acknowledgeSleepWakeNotification(refCon); #else vetoSleepWakeNotification(refCon); #endif return 0; } kern_return_t sleepkext_start (kmod_info_t * ki, void * d) { void *myself = NULL; // Would pass the self pointer here if in a class instance notifier = registerPrioritySleepWakeInterest( &mySleepHandler, myself, NULL); return KERN_SUCCESS; } kern_return_t sleepkext_stop (kmod_info_t * ki, void * d) { notifier->remove(); return KERN_SUCCESS; } } // extern "C" Miscellaneous Kernel Services Installing Shutdown Hooks 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 149As discussed in the chapter “Kernel Architecture Overview” (page 14), OS X provides a kernel extension mechanism as a means of allowing dynamic loading of code into the kernel, without the need to recompile or relink. Because these kernel extensions (KEXTs) provide both modularity and dynamic loadability, they are a natural choice for any relatively self-contained service that requires access to internal kernel interfaces. Because KEXTs run in supervisor mode in the kernel’s address space, they are also harder to write and debug than user-level modules, and must conform to strict guidelines. Further, kernel resources are wired (permanently resident in memory) and are thus more costly to use than resources in a user-space task of equivalent functionality. In addition, although memory protection keeps applications from crashing the system, no such safeguards are in place inside the kernel. A badly behaved kernel extension in OS X can cause as much trouble as a badly behaved application or extension could in Mac OS 9. Bugs in KEXTs can have far more severe consequences than bugs in user-level code. For example, a memory access error in a user application can, at worst, cause that application to crash. In contrast, a memory access error in a KEXT causes a kernel panic, crashing the operating system. Finally, for security reasons, some customers restrict or don’t permit the use of third-party KEXTs. As a result, use of KEXTs is strongly discouraged in situations where user-level solutions are feasible. OS X guarantees that threading in applications is just as efficient as threading inside the kernel, so efficiency should not be an issue. Unless your application requireslow-level accessto kernel interfaces, you should use a higher level of abstraction when developing code for OS X. When you are trying to determine if a piece of code should be a KEXT, the default answer is generally no . Even if your code was a system extension in Mac OS 9, that does not necessarily mean that it should be a kernel extension in OS X. There are only a few good reasons for a developer to write a kernel extension: ● Your code needsto take a primary interrupt—that is,something in the (built-in) hardware needsto interrupt the CPU and execute a handler. ● The primary client of your code is inside the kernel—for example, a block device whose primary client is a file system. ● Your code needs to access kernel interfaces that are not exported to user space. ● Your code has other special requirements that cannot be satisfied in a user space application. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 150 Kernel Extension OverviewIf your code does not meet any of the above criteria (and possibly even if it does), you should consider developing it as a library or a user-level daemon, or using one of the user-level plug-in architectures (such as QuickTime components or the Core Graphics framework) instead of writing a kernel extension. If you are writing device drivers or code to support a new volume format or networking protocol, however, KEXTs may be the only feasible solution. Fortunately, while KEXTs may be more difficult to write than user-space code, several tools and procedures are available to enhance the development and debugging process. See “Debugging Your KEXT” (page 153) for more information. This chapter provides a conceptual overview of KEXTs and how to create them. If you are interested in building a simple KEXT, see the Apple tutorials listed in the bibliography. These provide step-by-step instructions for creating a simple, generic KEXT or a basic I/O Kit driver. Implementation of a Kernel Extension (KEXT) Kernel extensions are implemented as bundles, folders that the Finder treats as single files. See the chapter about bundles in Mac Technology Overview for a discussion of bundles.The KEXT bundle can contain the following: ● Information property list—a text file that describes the contents, settings, and requirements of the KEXT. This file is required. A KEXT bundle need contain nothing more than this file, although most KEXTs contain one or more kernel modules as well. See the chapter about software configuration in Mac Technology Overview for further information about property lists. ● KEXT binary—a file in Mach-O format, containing the actual binary code used by the KEXT. A KEXT binary (also known as a kernel module or KMOD) represents the minimum unit of code that can be loaded into the kernel. A KEXT usually contains one KEXT binary. If no KEXT binaries are included, the information property list file must contain a reference to another KEXT and change its default settings. ● Resources—for example, icons or localization dictionaries. Resources are optional; they may be useful for a KEXT that needs to display a dialog or menu. At present, no resources are explicitly defined for use with KEXTs. ● KEXT bundles—a kext can contain other KEXTs. This can be used for plug-ins that augment features of a KEXT. Kernel Extension Dependencies Any KEXT can declare that it is dependent upon any other KEXT. The developer lists these dependencies in the OSBundleLibraries dictionary in the module’s property list file. Kernel Extension Overview Implementation of a Kernel Extension (KEXT) 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 151Before a KEXT isloaded, all of itsrequirements are checked. Those required extensions(and their requirements) are loaded first, iterating back through the lists until there are no more required extensions to load. Only after all requirements are met, is the requested KEXT loaded as well. For example, device drivers (a type of KEXT) are dependent upon (require) certain families (another type of KEXT). When a driver isloaded, itsrequired families are also loaded to provide necessary, common functionality. To ensure that all requirements are met, each device drivershould list all of itsrequirements(families and other drivers) in its property list. See the chapter “I/O Kit Overview” (page 94), for an explanation of drivers and families. It is important to list all dependencies for each KEXT. If your KEXT fails to do so, your KEXT may not load due to unrecognized symbols, thusrendering the KEXT useless. Dependenciesin KEXTs can be considered analogous to required header files or librariesin code development; in fact, the Kernel Extension Manager usesthe standard linker to resolve KEXT requirements. Building and Testing Your Extension After creating the necessary property list and C or C++ source files, you use Project Builder to build your KEXT. Any errors in the source code are brought to your attention during the build and you are given the chance to edit your source files and try again. To test your KEXT, however, you need to leave Project Builder and work in the Terminal application (or in console mode). In console mode, all system messages are written directly to your screen, as well as to a log file (/var/log/system.log). If you work in the Terminal application, you must view system messages in the log file or in the Console application.You also need to log in to the root account (or use the su or sudo command), since only the root account can load kernel extensions. When testing your KEXT, you can load and unload it manually, as well as check the load status. You can use the kextload command to load any KEXT. A manual page for kextload is included in OS X. (On OS X prior to 10.2, you must use the kmodload command instead.) Note that this command is useful only when developing a KEXT. Eventually, after it has been tested and debugged, you install your KEXT in one of the standard places (see “Installed KEXTs” (page 154) for details). Then, it will be loaded and unloaded automatically at system startup and shutdown or whenever it is needed (such as when a new device is detected). Kernel Extension Overview Building and Testing Your Extension 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 152Debugging Your KEXT KEXT debugging can be complicated. Before you can debug a KEXT, you must first enable kernel debugging, as OS X is not normally configured to permit debugging the kernel. Only the root account can enable kernel debugging, and you need to reboot OS X for the changes to take effect. (You can use sudo to gain root privileges if you don’t want to enable a root password.) Kernel debugging is performed using two OS X computers, called the development or debug host and the debug target. These computers must be connected over a reliable network connection on the same subnet (or within a single local network). Specifically, there must not be any intervening IP routers or other devices that could make hardware-based Ethernet addressing impossible. The KEXT is registered (and loaded and run) on the target. The debugger is launched and run on the debug host. You can also rebuild your KEXT on the debug host, after you fix any errors you find. Debugging must be performed in this fashion because you must temporarily halt the kernel on the target in order to use the debugger. When you halt the kernel, all other processes on that computer stop. However, a debugger running remotely can continue to run and can continue to examine (or modify) the kernel on the target. Note that bugs in KEXTs may cause the target kernel to freeze or panic. If this happens, you may not be able to continue debugging, even over a remote connection; you have to reboot the target and start over, setting a breakpoint just before the code where the KEXT crashed and working very carefully up to the crash point. Developers generally debug KEXTs using gdb, a source-level debugger with a command-line interface. You will need to work in the Terminal application to run gdb. For detailed information about using gdb, see the documentation included with OS X. You can also use the help command from within gdb. Some features of gdb are unavailable when debugging KEXTs because of implementation limitations. For example: ● You can’t use gdb to call a function or method in a KEXT. ● You should not use gdb to debug interrupt routines. The former is largely a barrier introduced by the C++ language. The latter may work in some cases but is not recommended due to the potential for gdb to interrupt something upon which kdp (the kernel shim used by gdb) depends in order to function properly. Use care that you do not halt the kernel for too long when you are debugging (for example, when you set breakpoints). In a short time, internal inconsistencies can appear that cause the target kernel to panic or freeze, forcing you to reboot the target. Kernel Extension Overview Debugging Your KEXT 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 153Additional information about debugging can be found in “When Things Go Wrong: Debugging the Kernel” (page 161). Installed KEXTs The Kernel Extension Manager (KEXT Manager) is responsible for loading and unloading all installed KEXTs (commands such as kextload are used only during development). Installed KEXTs are dynamically added to the running OS X kernel as part of the kernel’s address space. An installed and enabled KEXT is invoked as needed. Important: Note that KEXTs are only wrappers(bundles) around a property list, KEXT binaries(or references to other KEXTs), and optional resources. The KEXT describes what is to be loaded; it is the KEXT binaries that are actually loaded. KEXTs are usually installed in the folder /System/Libraries/Extensions. The Kernel Extension Manager (in the form of a daemon, kextd), always checks here. KEXTs can also be installed in ROM or inside an application bundle. Installing KEXTs in an application bundle allows an application to register those KEXTs without the need to install them permanently elsewhere within the system hierarchy. This may be more convenient and allows the KEXT to be associated with a specific, running application. When it starts, the application can register the KEXT and, if desired, unregister it on exit. For example, a network packet sniffer application might employ a Network Kernel Extension (NKE). A tape backup application would require that a tape driver be loaded during the duration of the backup process. When the application exits, the kernel extension is no longer needed and can be unloaded. Note that, although the application is responsible for registering the KEXT, this is no guarantee that the corresponding KEXTs are actually ever loaded. It is still up to a kernel component, such as the I/O Kit, to determine a need, such as matching a piece of hardware to a desired driver, thus causing the appropriate KEXTs (and their dependencies) to be loaded. Kernel Extension Overview Installed KEXTs 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 154This chapter is not about building kernel extensions (KEXTs). There are a number of good KEXT tutorials on Apple’s developer documentation site (http://developer.apple.com/documentation). This chapter is about adding new in-kernel modules(optional parts of the kernel), building kernels, and debugging kernel and kernel extension builds. The discussion is divided into three sections. The first, “Adding New Files or Modules” (page 155), describes how to add new functionality into the kernel itself. You should only add files into the kernel when the use of a KEXT is not possible (for example, when adding certain low-level motherboard hardware support). The second section, “Building Your First Kernel” (page 158), describes how to build a kernel, including how to build a kernel with debugger support, how to add new options, and how to obtain sources that are of similar vintage to those in a particular version of OS X or Darwin. The third section, “When Things Go Wrong: Debugging the Kernel” (page 161), tells how to debug a kernel or kernel module using ddb and gdb. This is a must-read for anyone doing kernel development. Adding New Files or Modules In this context, the term module is used loosely to refer to a collection of related files in the kernel that are controlled by a single config option at compile time. It does not refer to loadable modules (KEXTs). This section describes how to add additional files that will be compiled into the kernel, including how to add a new config option for an additional module. Modifying the Configuration Files The details of adding a new file or module into the kernel differ according to what portion of the kernel contains the file. If you are adding a new file or module into the Mach portion of the kernel, you need to list it in various filesin xnu/osfmk/conf. For the BSD portion of the kernel, you should list it in variousfilesin xnu/bsd/conf. In either case, the procedure is basically the same, just in a different directory. This section is divided into two subsections. The first describes adding the module itself and the second describes enabling the module. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 155 Building and Debugging KernelsAdding the Files or Modules In the appropriate conf directory, you need to add your files or modules into various files. The files MASTER, MASTER.ppc, and MASTER.i386 contain the list of configuration options that should be built into the kernel for all architectures, PowerPC, and i386, respectively. These are supplemented by files, files.ppc, and files.i386, which contain associations between compile options and the files that are related to them for their respective architectures. The format for these two files is relatively straightforward. If you are adding a new module, you should first choose a name for that module. For example, if your module is called mach_foo, you should then add a new option line near the top of files that is whitespace (space or tab) delimited and looks like this: OPTIONS/mach_foo optional mach_foo The first part defines the name of the module as it will be used in #if statements in the code. (See “Modifying the Source Code Files” (page 157) for more information.) The second part is alwaysthe word optional. The third part tells the name of the option as used to turn it on or off in a MASTER file. Any line with mach_foo in the last field will be enabled only if there is an appropriate line in a MASTER file. Then, later in the file, you add osfmk/foo/foo_main.c optional mach_foo osfmk/foo/foo_bar.c optional mach_foo and so on, for each new file associated with that module. This also applies if you are adding a file to an existing module. If you are adding a file that is not associated with any module at all, you add a line that looks like the following to specify that this file should always be included: osfmk/crud/mandatory_file.c standard If you are not adding any modules, then you’re done. Otherwise, you also need to enable your option in one of the MASTER files. Enabling Module Options To enable a module option (as described in the files files), you must add an entry for that option into one of the MASTER files. If your code is not a BSD pseudo-device, you should add something like the following: options MACH_FOO Building and Debugging Kernels Adding New Files or Modules 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 156Otherwise, you should add something like this: pseudo-device mach_foo In the case of a pseudo-device (for example, /dev/random), you can also add a number. When your code checks to see if it should be included, it can also check that number and allocate resources for more than one pseudo-device. The meaning of multiple pseudo-devicesis device-dependent. An example of thisis ppp, which allocates resources for two simultaneous PPP connections. Thus, in the MASTER.ppc file, it has the line: pseudo-device ppp 2 Modifying the Source Code Files In the OS X kernel, all source code files are automatically compiled. It is the responsibility of the C file itself to determine whether its contents need to be included in the build or not. In the example above, you created a module called mach_foo. Assume that you want this file to compile only on PowerPC-based computers. In that case, you should have included the option only in MASTER.ppc and not in MASTER.i386. However, by default, merely specifying the file foo_main.c in files causes it to be compiled, regardless of compile options specified. To make the code compile only when the option mach_foo is included in the configuration, you should begin each C source file with the lines #include #if (MACH_FOO > 0) and end it with #endif /* MACH_FOO */ If mach_foo is a pseudo-device and you need to check the number of mach_foo pseudo-devices included, you can do further tests of the value of MACH_FOO. Note that the file is not something you create. It is created by the makefiles themselves. You must run make exporthdrs before make all to generate these files. Building and Debugging Kernels Adding New Files or Modules 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 157Building Your First Kernel Before you can build a kernel, you must first obtain source code. Source code for the OS X kernel can be found in the Darwin xnu project on http://www.opensource.apple.com. To find out your current kernel version, use the command uname -a. If you run into trouble, search the archives of the darwin-kernel and darwin-development mailing lists for information. If that doesn’t help, ask for assistance on either list. The list archives and subscription information can be found at http://www.lists.apple.com. Note: Before you begin, make sure you extract the sources in a directory whose path does not contain any “special” characters (non-alphanumeric characters other than dash and underscore), as having such characters in the path leading up to the build directory can cause compiling to fail. Also, make sure that /usr/local/bin is in your PATH environment variable as follows: If you are using a csh derivative such as tcsh, you should add set path = (/usr/local/bin $path) to your .tcshrc file If you are using a Bourne shell derivative, you should add export PATH=/usr/local/bin:$PATH to your .bashrc file. Important: Once you have obtained and extracted the sources, before you begin compiling kernelsupport tools, you should configure your system to build using gcc 3.3. The OS X v10.4 kernel will not build using gcc 4.0. To do this, type: sudo gcc_select 3.3 Important: Before building anything, you should make sure you are running the latest version of OS X with the latest developer tools. The xnu compile process may reference various external headers from /System/Library/Frameworks. These headers are only installed as part of a developer toolsinstallation, not as part of the normal OS X install process. Next, you will need to compile several support tools. Get the bootstrap_cmds, Libstreams, kext_tools, IOKitUser, and cctools packagesfrom http://www.opensource.apple.com. Extract the filesfrom these .tar packages, then do the following: sudo mkdir -p /usr/local/bin sudo mkdir -p /usr/local/lib cd bootstrap_cmds-version/relpath.tproj make Building and Debugging Kernels Building Your First Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 158sudo make install cd ../../Libstreams-version make sudo make install cd ../cctools-version sudo cp /usr/include/ar.h \ /System/Library/Frameworks/Kernel.framework/Headers In the cctools package, modify the Makefile, and change the COMMON_SUBDIRS line (including the continuation line after it) to read: COMMON_SUBDIRS = libstuff libmacho misc Finally, issue the following commands: make RC_OS=macos sudo cp misc/seg_hack.NEW /usr/local/bin/seg_hack cd ld make RC_OS=macos kld_build sudo cp static_kld/libkld.a /usr/local/lib sudo ranlib /usr/local/lib/libkld.a Now you’re done with the cctools project. One final step remains: compiling kextsymboltool. To do this, extract the kext_tools tarball, then do the following: sudo mkdir -p /System/Library/Frameworks/IOKit.framework/Versions/A/PrivateHeaders/kext cd /System/Library/Frameworks/IOKit.framework/ sudo ln -s Versions/A/PrivateHeaders PrivateHeaders sudo cp PATH_TO_IOKITUSER/IOKitUser-version/kext.subproj/*.h PrivateHeaders/kext cd PATH_TO_KEXT_TOOLS/kext_tools-version gcc kextsymboltool.c -o kextsymboltool sudo cp kextsymboltool /usr/local/bin Building and Debugging Kernels Building Your First Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 159Warning: If you do not use a version of kextsymboltool that is at least as current as your kernel, you will get serious compile failures. If you see the error message “exported name not in import list”, there’s a good chance you aren’t using a current kextsymboltool. Congratulations. You now have all the necessary tools, libraries, and header files to build a kernel. The next step is to compile the kernel itself. First, change directories into the xnu directory. Next, you need to set a few environment variables appropriately. For your convenience, the kernel sources contain shell scripts to do this for you. If you are using sh, bash, zsh, or some other Bourne-compatible shell, issue the following command: source SETUP/setup.sh If you are using csh, tcsh, or a similar shell, use the following command: source SETUP/setup.csh Then, you should be able to type make exporthdrs make all and get a working kernel in BUILD/obj/RELEASE_PPC/mach_kernel (assuming you are building a RELEASE kernel for PowerPC, of course). If things don’t work, the darwin-kernel mailing list a good place to get help. Building an Alternate Kernel Configuration When building a kernel, you may want to build a configuration other than the RELEASE configuration (the default shipping configuration). Additional configurations are RELEASE_TRACE, DEBUG, DEBUG_TRACE, and PROFILE. These configurations add various additional options (except PROFILE, which is reserved for future expansion, and currently maps onto RELEASE). Building and Debugging Kernels Building an Alternate Kernel Configuration 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 160The most useful and interesting configurations are RELEASE and DEBUG. The release configuration should be the same as a stock Apple-released kernel, so this is interesting only if you are building source that differs from that which was used to build the kernel you are already running. Compiling a kernel without specifying a configuration results in the RELEASE configuration being built. The DEBUG configuration enables ddb, the in-kernel serial debugger. The ddb debugger is helpful to debug panics that occur early in boot or within certain parts of the Ethernet driver. It is also useful for debugging low-level interrupt handler routines that cannot be debugged by using the more traditional gdb. To compile an alternate kernel configuration, you should follow the same basic procedure as outlined previously, changing the final make statement slightly. For example, to build the DEBUG configuration, instead of typing make all you type make KERNEL_CONFIGS=DEBUG all and wait. To turn on additional compile options, you must modify one of the MASTER files. For information on modifying these files, see the section “Enabling Module Options” (page 156). When Things Go Wrong: Debugging the Kernel No matter how careful your programming habits, sometimes things don’t work right the first time. Kernel panics are simply a fact of life during development of kernel extensions or other in-kernel code. There are a number of ways to track down problems in kernel code. In many cases, you can find the problem through careful use of printf or IOLog statements. Some people swear by this method, and indeed, given sufficient time and effort, any bug can be found and fixed without using a debugger. Of course, the key words in that statement are “given sufficient time and effort.” For the rest of us, there are debuggers: gdb and ddb. Setting Debug Flags in Open Firmware With the exception of kernel panics or calls to PE_enter_debugger, it is not possible to do remote kernel debugging without setting debug flags in Open Firmware. These flags are relevant to both gdb and ddb debugging and are important enough to warrant their own section. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 161To set these flags, you can either use the nvram program (from the OS X command line) or access your computer’s Open Firmware. You can access Open Firmware this by holding down Command-Option-O-F at boot time. For most computers, the default is for Open Firmware to present a command–line prompt on your monitor and accept input from your keyboard. For some older computers you must use a serial line at 38400, 8N1. (Technically, such computers are not supported by OS X, but some are usable under Darwin, and thus they are mentioned here for completeness.) From an Open Firmware prompt, you can set the flags with the setenv command. From the OS X command line, you would use the nvram command. Note that when modifying these flags you should always look at the old value for the appropriate Open Firmware variables and add the debug flags. For example, if you want to set the debug flagsto 0x4, you use one of the following commands. For computers with recent versions of Open Firmware, you would type printenv boot-args setenv boot-args original_contents debug=0x4 from Open Firmware or nvram boot-args nvram boot-args="original_contents debug=0x4" from the command line (as root). For older firmware versions, the interesting variable is boot-command. Thus, you might do something like printenv boot-command setenv boot-command 0 bootr debug=0x4 from Open Firmware or nvram boot-command nvram boot-command="0 bootr debug=0x4" from the command line (as root). Of course, the more important issue is what value to choose for the debug flags. Table 20-1 (page 163) lists the debugging flags that are supported in OS X. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 162Table 20-1 Debugging flags Symbolic name Flag Meaning DB_HALT 0x01 Halt at boot-time and wait for debugger attach (gdb). DB_PRT 0x02 Send kernel debugging printf output to console. Drop into debugger on NMI (Command–Power, Command-Option-Control-Shift-Escape, or interrupt switch). DB_NMI 0x04 DB_KPRT 0x08 Send kernel debugging kprintf output to serial port. DB_KDB 0x10 Make ddb (kdb) the default debugger (requires a custom kernel). DB_SLOG 0x20 Output certain diagnostic info to the system log. Allow debugger to ARP and route (allows debugging across routers and removes the need for a permanent ARP entry, but is a potential security hole)—not available in all kernels. DB_ARP 0x40 DB_KDP_BP_DIS 0x80 Support old versions of gdb on newer systems. DB_LOG_PI_SCRN 0x100 Disable graphical panic dialog. The option DB_KDP_BP_DIS is not available on all systems, and should not be important if your target and host systems are running the same or similar versions of OS X with matching developer tools. The last option is only available in Mac OS 10.2 and later. Avoiding Watchdog Timer Problems Macintosh computers have various watchdog timers designed to protect the system from certain types of failures. There are two primary watchdog timersin common use: the power management watchdog timer (not present on all systems) and the system crash watchdog timer. Both watchdogs are part of the power management hardware. The first of these, the power management watchdog timer, is designed to restore the system to a known safe state in the event of unexpected communication loss between the power management hardware and the CPU. Thistimer is only present in G4 and earlier desktops and laptops and in early G5 desktops. More specifically, it is present only in machines containing a PMU (Power Management Unit) chip. Under normal circumstances, when communication with the PMU chip is lost, the PMU driver will attempt to get back in sync with the PMU chip. With the possible exception of a momentary loss of keyboard and mouse control, you probably won't notice that anything has happened (and you should never even experience such a stall unless you are writing a device driver that disables interrupts for an extended period of time). Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 163The problem occurs when the disruption in communication is caused by entering the debugger while the PMU chip is in one of these "unsafe" states. If the chip is left in one of these "unsafe" states for too long, it will shut the computer down to prevent overheating or other problems. This problem can be significantly reduced by operating the PMU chip in polled mode. This prevents the watchdog timer from activating. You should only use this option when debugging, however, as it diminishes performance and a crashed system could overheat. To disable this watchdog timer, add the argument pmuflags=1 to the kernel's boot arguments. See “Setting Debug Flags in Open Firmware” (page 161) for information about how to add a boot argument. The second type of watchdog timer is the system crash watchdog timer. This is normally only enabled in OS X Server. If your target machine is running OS X Server, your system will automatically reboot within seconds after a crash to maximize server uptime. You can disable this automatic reboot on crash feature in the server administration tool. Choosing a Debugger There are two basic debugging environments supported by OS X: ddb and gdb. ddb is a built-in debugger that works over a serial line. By contrast, gdb is supported using a debugging shim built into the kernel, which allows a remote computer on the same physical network to attach after a panic (or sooner if you pass certain options to the kernel). For problems involving network extensions or low-level operating system bringups, ddb is the only way to do debugging. For other bugs, gdb is generally easier to use. For completeness, this chapter describes how to use both ddb and gdb to do basic debugging. Since gdb itself is well documented and is commonly used for application programming, this chapter assumes at least a passing knowledge of the basics of using gdb and focuses on the areas where remote (kernel) gdb differs. Note: Only systems with serial hardware support ddb. Thus, it is only possible to use ddb on PowerMac G4 and older systems. Using gdb for Kernel Debugging gdb, short for the GNU Debugger, is a piece of software commonly used for debugging software on UNIX and Linux systems. This section assumes that you have used gdb before, and does not attempt to explain basic usage. In standard OS X builds (and in your builds unless you compile with ddb support), gdb support is built into the system but is turned off except in the case of a kernel panic. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 164Of course, many software failures in the kernel do not result in a kernel panic but still cause aberrant behavior. For these reasons, you can pass additional flags to the kernel to allow you to attach to a remote computer early in boot or after a nonmaskable interrupt (NMI), or you can programmatically drop into the debugger in your code. You can cause the test computer (the debug target) to drop into the debugger in the following ways: ● debug on panic ● debug on NMI ● debug on boot ● programmatically drop into the default debugger The function PE_enter_debugger can be called from anywhere in the kernel, although if gdb is your default debugger, a crash will result if the network hardware is not initialized or if gdb cannot be used in that particular context. This call is described in the header pexpert/pexpert.h. After you have decided what method to use for dropping into the debugger on the target, you must configure your debug host (the computer that will actually be running gdb). Your debug hostshould be running a version of OS X that is comparable to the version running on your target host. However, it should not be running a customized kernel, since a debug host crash would be problematic, to say the least. Note: It is possible to use a non-OS X system as your debug host. This is not a trivial exercise, however, and a description of building a cross-gdb is beyond the scope of this document. When using gdb, the best results can be obtained when the source code for the customized kernel is present on your debug host. This not only makes debugging easier by allowing you to see the lines of code when you stop execution, it also makes it easier to modify those lines of code. Thus, the ideal situation is for your debug host to also be your build computer. This is not required, but it makes things easier. If you are debugging a kernel extension, it generally suffices to have the source for the kernel extension itself on your debug host. However, if you need to see kernel-specific structures, having the kernel sources on your debug host may also be helpful. Once you have built a kernel using your debug host, you must then copy it to your target computer and reboot the target computer. At this point, if you are doing panic-only debugging, you should trigger the panic. Otherwise, you should tell your target computer to drop into the debugger by issuing an NMI (or by merely booting, in the case of debug=0x1). Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 165Next, unless your kernelsupports ARP while debugging (and unless you enabled it with the appropriate debug flag), you need to add a permanent ARP entry for the target. It will be unable to answer ARP requests while waiting for the debugger. This ensures that your connection won’t suddenly disappear. The following example assumes that your target is target.foo.com with an IP number of 10.0.0.69: $ ping -c 1 target_host_name ping results: .... $ arp -an target.foo.com (10.0.0.69): 00:a0:13:12:65:31 $ sudo arp -s target.foo.com 00:a0:13:12:65:31 $ arp -an target.foo.com (10.0.0.69) at00:a0:13:12:65:31 permanent Now, you can begin debugging by doing the following: gdb /path/to/mach_kernel source /path/to/xnu/osfmk/.gdbinit p proc0 source /path/to/xnu/osfmk/.gdbinit target remote-kdp attach 10.0.0.69 Note that the mach kernel passed as an argument to gdb should be the symbol–laden kernel file located in BUILD/obj/DEBUG_PPC/mach_kernel.sys (for debug kernel builds, RELEASE_PPC for non-debug builds), not the bootable kernel that you copied onto the debug target. Otherwise most of the gdb macros will fail. The correct kernel should be several times as large as a normal kernel. You must do the p proc0 command and source the .gdbinit file (from the appropriate kernel sources) twice to work around a bug in gdb. Of course, if you do not need any of the macros in .gdbinit, you can skip those two instructions. The macros are mostly of interest to people debugging aspects of Mach, though they also provide ways of obtaining information about currently loaded KEXTs. Warning: It may not be possible to detach in a way that the target computer’s kernel continues to run. If you detach, the target hangs until you reattach. It is not always possible to reattach, though the situation is improving in this area. Do not detach from the remote kernel! Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 166If you are debugging a kernel module, you need to do some additional work to get debugging symbol information about the module. First, you need to know the load address for the module. You can get this information by running kextstat (kmodstat on systems running OS X v10.1 or earlier) as root on the target. If you are already in the debugger, then assuming the target did not panic, you should be able to use the continue function in gdb to revive the target, get this information, then trigger another NMI to drop back into the debugger. If the target is no longer functional, and if you have a fully symbol–laden kernel file on your debug host that matches the kernel on your debug target, you can use the showallkmods macro to obtain this information. Obtaining a fully symbol–laden kernel generally requires compiling the kernel yourself. Once you have the load address of the module in question, you need to create a symbol file for the module. You do this in different ways on different versions of OS X. For versions 10.1 and earlier, you use the kmodsyms program to create a symbol file for the module. If your KEXT is called mykext and it is loaded at address 0xf7a4000, for example, you change directories to mykext.kext/Contents/MacOS and type: kmodsyms -k path/to/mach_kernel -o mykext.sym mykext@0xf7a4000 Be sure to specify the correct path for the mach kernel that is running on your target (assuming it is not the same as the kernel running on your debug host). For versions after 10.1, you have two options. If your KEXT does not crash the computer when it loads, you can ask kextload to generate the symbols at load time by passing it the following options: kextload -s symboldir mykext.kext It will then write the symbols for your kernel extension and its dependencies into files within the directory you specified. Of course, this only works if your target doesn’t crash at or shortly after load time. Alternately, if you are debugging an existing panic, or if your KEXT can’t be loaded without causing a panic, you can generate the debugging symbols on your debug host. You do this by typing: kextload -n -s symboldir mykext.kext If will then prompt you for the load address of the kernel extension and the addresses of all its dependencies. As mentioned previously, you can find the addresses with kextstat (or kmodstat) or by typing showallkmods inside gdb. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 167You should now have a file or files containing symbolic information that gdb can use to determine address–to–name mappings within the KEXT. To add the symbols from that KEXT, within gdb on your debug host, type the command add-symbol-file mykext.sym for each symbol file. You should now be able to see a human-readable representation of the addresses of functions, variables, and so on. Special gdb I/O Addressing Issues As described in “Address Spaces” (page 70), some Macintosh hardware has a third addressing mode called I/O addressing which differs from both physical and virtual addressing modes. Most developers will not need to know about these modes in any detail. Where some developers may run into problems is debugging PCI device drivers and attempting to access device memory/registers. To allow I/O-mapped memory dumping, do the following: set kdp_read_io=1 To dump in physical mode, do the following: set kdp_trans_off=1 For example: (gdb) x/x 0xf8022034 0xf8022034: Cannot access memory at address 0xf8022034 (gdb) set kdp_trans_off=1 (gdb) x/x 0xf8022034 0xf8022034: Cannot access memory at address 0xf8022034 (gdb) set kdp_read_io=1 (gdb) x/x 0xf8022034 0xf8022034: 0x00000020 (gdb) Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 168If you experience problems accessing I/O addresses that are not corrected by this procedure, please contact Apple Developer Technical Support for additional assistance. Using ddb for Kernel Debugging When doing typical debugging, gdb is probably the best solution. However, there are times when gdb cannot be used or where gdb can easily run into problems. Some of these include ● drivers for built-in Ethernet hardware ● interrupt handlers (the hardware variety, not handler threads) ● early bootstrap before the network hardware is initialized When gdb is not practical (or if you’re curious), there is a second debug mechanism that can be compiled into OS X. This mechanism is called ddb, and is similar to the kdb debugger in most BSD UNIX systems. It is not quite as easy to use as gdb, mainly because of the hardware needed to use it. Unlike gdb (which uses Ethernet for communication with a kernel stub), ddb is built into the kernel itself, and interacts directly with the user over a serial line. Also unlike gdb, using ddb requires building a custom kernel using the DEBUG configuration. For more information on building this kernel, see “Building Your First Kernel” (page 158). Note: ddb requires an actual built-in hardware serial line on the debug target. Neither PCI nor USB serial adapters will work. In order to work reliably for interrupt-level debugging, ddb controls the serial ports directly with a polled-mode driver without the use of the I/O Kit. If your debug target does not have a factory serial port, third-party adapter boards may be available that replace your internal modem with a serial port. Since these devices use the built-in serial controller, they should work for ddb. It is not necessary to install OS X drivers for these devices if you are using them only to support ddb debugging. The use of these serial port adapter cards is not an officially supported configuration, and not all computers support the third-party adapter boards needed for ddb support. Consult the appropriate adapter board vendor for compatibility information. If your target computer has two serial ports, ddb uses the modem port (SCC port 0). However, if your target has only one serial port, that port is probably attached to port 1 of the SCC cell, which means that you have to change the default port if you want to use ddb. To use this port (SCC port 1), change the line: const int console_unit=0; Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 169in osfmk/ppc/serial_console.c to read: const int console_unit=1; and recompile the kernel. Once you have a kernel with ddb support, it isrelatively easy to use. First, you need to set up a terminal emulator program on your debug host. If your debug host is running Mac OS 9, you might use ZTerm, for example. For OS X computers, or for computers running Linux or UNIX, minicom provides a good environment. Setting up these programs is beyond the scope of this document. Important: Serial port settings for communicating with ddb must be 57600 8N1. Hardware handshaking may be on, but is not necessary. Note: For targets whose Open Firmware uses the serial ports, remember that the baud rate for communicating with Open Firmware is 38400 and that hardware handshaking must be off. Once you boot a kernel with ddb support, a panic will allow you to drop into the debugger, as will a call to PE_enter_debugger. If the DB_KDB flag is not set, you will have to press the D key on the keyboard to use ddb. Alternately, if both DB_KDB and DB_NMI are set, you should be able to drop into ddb by generating a nonmaskable interrupt (NMI). See “Setting Debug Flags in Open Firmware” (page 161) for more information on debug flags. To generate a nonmaskable interrupt, hold down the command, option, control, and shift keys and hit escape (OS X v10.4 and newer), hold down the command key while pressing the power key on your keyboard (on hardware with a power key), or press the interrupt button on your target computer. At this point, the system should hang, and you should see ddb output on the serial terminal. If you do not, check your configuration and verify that you have specified the correct serial port on both computers. Commands and Syntax of ddb The ddb debugger is much more gdb-like than previous versions, but it still has a syntax that is very much its own (shared only with other ddb and kdb debuggers). Because ddb is substantially different from what most developers are used to using, this section outlines the basic commands and syntax. The commands in ddb are generally in this form: command[/switch] address[,count] Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 170The switches can be one of those shown in Table 20-2 (page 171). Table 20-2 Switch options in ddb Switch Description /A Print the location with line number if possible /I Display as instruction with possible alternate machine-dependent format /a Print the location being displayed /b Display or process by bytes Display low 8 bits as a character (nonprinting characters as octal) or count instructions while executing (depends on instruction) /c /d Display as signed decimal /h Display or process by half word (16 bits) /i Display as an instruction /l Display or process by long word (32 bits) /m Display as unsigned hex with character dump for each line /o Display in unsigned octal /p Print cumulative instruction count and call tree depth at each call or return statement /r Display in current radix, signed /s Display the null-terminated string at address (nonprinting as octal). Display in unsigned decimal or set breakpoint at a user space address (depending on command). /u /x Display in unsigned hex /z Display in signed hex The ddb debugger has a rich command set that has grown over its lifetime. Its command set is similar to that of ddb and kdb on other BSD systems, and their manual pages provide a fairly good reference for the various commands. The command set for ddb includes the following commands: Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 171break[/u] addr Set a breakpoint at the address specified by addr. Execution will stop when the breakpoint is reached. The /u switch means to set a breakpoint in user space. c or continue[/c] Continue execution after reaching a breakpoint. The /c switch meansto count instructions while executing. call Call a function. cond Set condition breakpoints. This command is not supported on PowerPC. cpu cpunum Causes ddb to switch to run on a different CPU. d or delete [addr|#] Delete a breakpoint. This takes a single argument that can be either an address or a breakpoint number. dk Equivalent to running kextstat while the target computer is running. This lists loaded KEXTs, their load addresses, and various related information. dl vaddr Dumps a range of memory starting from the address given. The parameter vaddr is a kernel virtual address. If vaddr is not specified, the last accessed address is used. See also dr, dv. dm Displays mapping information for the last address accessed. dmacro name Delete the macro called name. See macro. dp Displays the currently active page table. dr addr Dumps a range of memory starting from the address given. The parameter address is a physical address. If addr is not specified, the last accessed address is used. See also dl, dv. ds Dumps save areas of all Mach tasks. dv [addr [vsid]] Dumps a range of memory starting from the address given. The parameter addr is a virtual address in the address space indicated by vsid. If addr is not specified, the last accessed address is used. Similarly, if vsid is not specified, the last vsid is used. See also dl, dr. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 172dwatch addr Delete a watchpoint. See watch. dx Displays CPU registers. examine See print. gdb Switches to gdb mode, allowing gdb to attach to the computer. lt On PowerPC only: Dumps the PowerPC exception trace table. macro name command [ ; command .. ] Create a macro called name that executesthe listed commands. You can show a macro with the command show macro name or delete it with dmacro name. match[/p] Stop at the matching return instruction. If the /p switch is not specified, summary information is printed only at the final return. print[/AIabcdhilmorsuxz] addr1 [addr2 ...] Print the values at the addresses given in the format specified by the switch. If no switch is given, the last used switch is assumed. Synonymous with examine and x. Note that some of the listed switches may work for examine and not for print. reboot Reboots the computer. Immediately. Without doing any file-system unmounts or other cleanup. Do not do this except after a panic. s or step Single step through instructions. search[/bhl] addr value [mask[,count]] Search memory for value starting at addr. If the value is not found, this command can wreak havoc. This command may take other formatting values in addition to those listed. set $name [=] expr Sets the value of the variable or register named by name to the value indicated by expr. show Display system data. For a list of information that can be shown, type the show command by itself. Some additional options are available for certain options, particularly show all. For those suboptions, type show all by itself. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 173trace[/u] Prints a stack backtrace. If the /u flag is specified, the stack trace extends to user space if supported by architecture-dependent code. until[/p] Stop at the next call or return. w or write[/bhl] addr expr1 [expr2 ... ] Writes the value of expr1 to the memory location stored at addr in increments of a byte, half word, or long word. If additional expressions are specified, they are written to consecutive bytes, half words, or long words. watch addr[,size] Sets a watchpoint on a particular address. Execution stops when the value stored at that address is modified. Watch points are not supported on PowerPC. Warning: Watching addresses in wired kernel memory may cause unrecoverable errors on i386. x Short for examine. See print. xb Examine backward. Execute the last examine command, but use the address previous to the last one used (jumping backward by increments of the last width displayed). xf Examine forward. Execute the last examine command, but use the address following the last one used (jumping by increments of the last width displayed). The ddb debugger should seem relatively familiar to users of gdb, and its syntax was changed radically from its predecessor, kdb, to be more gdb-like. However, it is still sufficiently different that you should take some time to familiarize yourself with its use before attempting to debug something with it. It is far easier to use ddb on a system whose memory hasn’t been scribbled upon by an errant DMA request, for example. Building and Debugging Kernels When Things Go Wrong: Debugging the Kernel 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 174This bibliography contains related material that may be of interest. The editions listed are the editions that were current when this list was compiled, but newer versions may be available. Apple OS X Publications The following Apple publications have information that could be of interest to you if you are programming in the kernel: Hello Debugger: Debugging a Device Driver With GDB (tutorial). Hello I/O Kit: Creating a Device Driver With Xcode (tutorial) Hello Kernel: Creating a Kernel Extension With Xcode (tutorial). Accessing Hardware From Applications I/O Kit Fundamentals Network Kernel Extensions Programming Guide Network Kernel Extensions (legacy) Mac Technology Overview Porting UNIX/Linux Applications to OS X I/O Kit Device Driver Design Guidelines Packaging Your KEXT for Distribution and Installation(tutorial). General UNIX and Open Source Resources A Quarter Century of UNIX . Peter H. Salus. Addison-Wesley, 1994.ISBN 0-201-54777-5. Berkeley Software Distribution . CSRG, UC Berkeley. USENIX and O’Reilly, 1994.ISBN 1-56592-082-1. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 175 BibliographyTheCathedralandtheBazaar:MusingsonLinuxandOpenSourcebyanAccidentalRevolutionary . Eric S.Raymond. O’Reilly & Associates, 1999.ISBN 1-56592-724-9. The New Hacker’s Dictionary . 3rd. Ed., Eric S. Raymond. MIT Press, 1996. ISBN 0-262-68092-0. Open Sources: Voices from the Open Source Revolution . Edited by Chris DiBona, Sam Ockman & Mark Stone. O’Reilly & Associates, 1999. ISBN 1-56592-582-3. Proceedings of the First Conference on Freely Redistributable Software . Free Software Foundation. FSF, 1996. ISBN 1-882114-47-7. The UNIX Desk Reference: The hu.man Pages. Peter Dyson. Sybex, 1996. ISBN 0-7821-1658-2. The UNIX Programming Environment. Brian W. Kernighan, Rob Pike. Prentice Hall, 1984. ISBN 0-13-937681-X (paperback), ISBN 0-13-937699-2 (hardback). BSD and UNIX Internals Advanced Topics in UNIX: Processes, Files, and Systems. Ronald J. Leach. Wiley, 1996. ISBN 1-57176-159-4. The Complete FreeBSD. Greg Lehey, Walnut Creek CDROM Books, 1999. ISBN 1-57176-246-9. The Design and Implementation of the 4.4BSD Operating System. Marshall Kirk McKusick, et al. Addison-Wesley, 1996. ISBN 0-201-54979-4. The Design of the UNIX Operating System. Maurice J. Bach. Prentice Hall, 1986. ISBN 0-13-201799-7. Linux Kernel Internals 2nd edition . Michael Beck, et al. Addison-Wesley, 1997. ISBN 0-201-33143-8. Lions’ Commentary on UNIX 6th Edition with Source Code . John Lions. Peer-to-Peer, 1996. ISBN 1-57398-013-7. Panic!: UNIX System Crash Dump Analysis. Chris Drake, Kimberly Brown. Prentice Hall, 1995. ISBN 0-13-149386-8. UNIX Internals: The New Frontiers. Uresh Vahalia. Prentice-Hall, 1995. ISBN 0-13-101908-2. UNIX Systems for Modern Architectures: Symmetric Multiprocessing and Caching for Kernel Programmers. Curt Schimmel. Addison-Wesley, 1994. ISBN 0-201-63338-8. Optimizing PowerPC Code . Gary Kacmarcik. Addison-Wesley Publishing Company, 1995. ISBN 0-201-40839-2. BerkeleySoftwareArchitectureManual4.4BSDEdition .WilliamJoy,Robert Fabry, Samuel Leffler,M.KirkMcKusick, Michael Karels. Computer Systems Research Group, Computer Science Division, Department of Electrical Engineering and Computer Science, University of California, Berkeley. Bibliography BSD and UNIX Internals 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 176Mach CMU Computer Science: A 25th Anniversary Commemorative . Richard F. Rashid, Ed. ACM Press, 1991. ISBN 0-201-52899-1. Load Distribution, Implementation for the Mach Microkernel . Dejan S. Milojicic. Vieweg Verlag, 1994. ISBN 3-528-05424-7. Programming under Mach . Boykin, et al. Addison-Wesley, 1993. ISBN 0-201-52739-1. Mach Workshop Proceedings. USENIX Association. October, 1990. Mach Symposium Proceedings.USENIX Association. November, 1991. Mach III Symposium Proceedings. USENIX Association. April, 1993, ISBN 1-880446-49-9. Mach 3 Documentation Series. Open Group Research Institute (RI), now Silicomp: Final Draft Specifications OSF/1 1.3 Engineering Release . RI. May 1993. OSF Mach Final Draft Kernel Principles. RI. May, 1993. OSF Mach Final Draft Kernel Interfaces. RI. May, 1993. OSF Mach Final Draft Server Writer’s Guide . RI. May, 1993. OSF Mach Final Draft Server Library Interfaces, RI, May, 1993. Research Institute Microkernel Series. Open Group Research Institute (RI): Operating Systems Collected Papers. Volume I. RI. March, 1993. Operating Systems Collected Papers. Volume II. RI. October,1993. Operating Systems Collected Papers. Volume III. RI. April, 1994. Operating Systems Collected Papers. Volume IV. RI. October, 1995. Mach: A New Kernel Foundation for UNIX Development. Proceedings of the Summer 1986 USENIX Conference. Atlanta, GA., http://www.usenix.org. UNIX as an Application Program. Proceedings of the Summer 1990 USENIX Conference. Anaheim, CA., http://www.usenix.org. OSF RI papers (Spec ‘93): OSF Mach Final Draft Kernel Interfaces Bibliography Mach 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 177OSF Mach Final Draft Kernel Principles OSF Mach Final Draft Server Library Interfaces OSF Mach Final Draft Server Writer's Guide OSF Mach Kernel Interface Changes OSF RI papers (Spec ‘94): OSF RI 1994 Mach Kernel Interfaces Draft OSF RI 1994 Mach Kernel Interfaces Draft (Part A) OSF RI 1994 Mach Kernel Interfaces Draft (Part B) OSF RI 1994 Mach Kernel Interfaces Draft (Part C) OSF RI papers (miscellaneous): Debugging an object oriented system using the Mach interface Unix File Access and Caching in a Multicomputer Environment Untyped MIG: The Protocol Untyped MIG: What Has Changed and Migration Guide Towards a World-Wide Civilization of Objects A Preemptible Mach Kernel A Trusted, Scalable, Real-Time Operating System Environment Mach Scheduling Framework Networking UNIX Network Programming . Volume 1, Networking APIs: Sockets and XTI . W. Richard Stevens. Prentice Hall, 1998, ISBN 0-13-490012-X. UNIX Network Programming . Volume 2, Interprocess Communications. W. Richard Stevens. Prentice Hall, 1998. ISBN 0-13-081081-9. TCP/IP Illustrated . Volume 1, The Protocols. W. Richard Stevens. Addison-Wesley, 1994. ISBN 0-201-63346-9. Bibliography Networking 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 178TCP/IP Illustrated . Volume 2, The Implementation .W. Richard Stevens.Addison-Wesley, 1995. ISBN0-201-63354-X. TCP/IP Illustrated . Volume 3, TCP for Transactions, HTTP, NNTP, and the UNIX Domain Protocols. W. Richard Stevens. Addison-Wesley, 1996. ISBN 0-201-63495-3. Operating Systems Advanced Computer Architecture: Parallelism, Scalability, Programmability . Kai Hwang. McGraw-Hill, 1993. ISBN 0-07-031622-8. Concurrent Systems: An Integrated Approach to Operating Systems, Database, and Distributed Systems. Jean Bacon. Addison-Wesley, 1993. ISBN 0-201-41677-8. Distributed Operating Systems. Andrew S. Tanenbaum. Prentice Hall, 1995. ISBN 0-13-219908-4. Distributed Operating Systems: The Logical Design . A. Goscinski. Addison-Wesley, 1991. ISBN 0-201-41704-9. Distributed Systems, Concepts, and Designs. G. Coulouris, et al. Addison-Wesley, 1994. ISBN 0-201-62433-8. Operating System Concepts. 4th Ed., Abraham Silberschatz, Peter Galvin. Addison-Wesley, 1994. ISBN 0-201-50480-4. POSIX Information Technology-PortableOperating SystemInterface (POSIX): SystemApplication ProgramInterface (API) (C Language). ANSI/IEEE Std. 1003.1. 1996 Edition. ISO/IEC 9945-1: 1996. IEEE Standards Office. ISBN 1-55937-573-6. Programming with POSIX Threads. David R. Butenhof. Addison Wesley Longman, Inc., 1997. ISBN 0-201-63392-2. Programming Advanced Programming in theUNIX Environment. RichardW. Stevens.Addison-Wesley, 1992. ISBN0-201-56317-7. Debugging with GDB: The GNU Source-Level Debugger Eighth Edition for GDB version 5.0 . Richard Stallman et al. Cygnus Support. http://developer.apple.com/documentation/DeveloperTools/gdb/gdb/gdb_toc.html. Open Source Development with CVS , Karl Franz Fogel. Coriolis Group, 1999. ISBN: 1-57610-490-7. Porting UNIX Software: From Download to Debug . Greg Lehey. O’Reilly, 1995. ISBN 1-56592-126-7. Bibliography Operating Systems 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 179The Standard C Library . P.J. Plauger. Prentice Hall, 1992. ISBN 0-13-131509-9. Websites and Online Resources Apple’s developer website (http://www.apple.com/developer/) is a general repository for developer documentation. Additionally, the following sites provide more domain-specific information. Apple’s Public Source projects and Darwin http://www.opensource.apple.com/ The Berkeley Software Distribution (BSD) http://www.FreeBSD.org http://www.NetBSD.org http://www.OpenBSD.org BSD Networking http://www.kohala.com/start/ Embedded C++ http://www.caravan.net/ec2plus GDB, GNUPro Toolkit 99r1 Documentation http://www.redhat.com/docs/manuals/gnupro/ The Internet Engineering Task Force (IETF) http://www.ietf.org jam http://www.perforce.com/jam/jam.html The PowerPC CPU http://www.freescale.com/webapp/sps/site/homepage.jsp?nodeId=0162468rH3bTdG The Single UNIX Specification Version 2 http://www.opengroup.org/onlinepubs/007908799 Bibliography Websites and Online Resources 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 180The USENIX Association; USENIX Proceedings http://www.usenix.org http://www.usenix.org/publications/library/ Security and Cryptography Applied Cryptography: Protocols, Algorithms, and Source Code in C. Bruce Schneier. John Wiley & Sons, 1994. ISBN 0-471-59756-2. comp.security newsgroup (news:comp.security). comp.security.unix newsgroup (news:comp.security.unix). Computer Security . Dieter Gollmann. John Wiley and Son Ltd, 1999. ISBN 0-471-97844-2. Foundations of Cryptography . Oded Goldreich. Cambridge University Press, 2001. ISBN 0-521-79172-3. Secrets and Lies: Digital Security in a Networked World . Bruce Schneier. John Wiley & Sons, 2000. ISBN 0-471-25311-1. Bibliography Security and Cryptography 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 181This table describes the changes to Kernel Programming Guide . Date Notes 2012-02-16 Updated for OS X v10.7. Added a chapter that discusses the early stages of the boot process. “The Early Boot Process” (page 21) was formerly part of Daemons and Services Programming Guide , and was moved here during a reorganization of that book. 2011-03-08 2006-11-07 Added security information and improved kernel build instructions. 2006-10-03 Made minor corrections. 2006-05-23 Added a note about pmuflags to the debugging section. 2006-04-04 Removed out-of-date information for OS X v10.4. 2006-03-08 Updated some stale content for OS X version 10.4. 2006-01-10 Corrected locking prototypes. Made minor fixesto the file system section. Revised networking, synchronization, and kernel services APIs for OS X v10.4. 2005-11-09 Changed terminology from "fat binary" to "universal binary." Clarified the distinction between memory objects and VM objects. 2005-08-11 2005-07-07 Fixed minor errors in build instructions. 2005-06-04 Updated kernel build instructions for OS X v10.4; other minor fixes. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 182 Document Revision HistoryDate Notes Added information about generating NMI on newer hardware in OS X v10.4 and later; various other minor changes. 2005-04-29 2005-02-03 Made minor corrections. 2004-12-02 Made section number fix to man page reference in Chapter 14. 2004-11-01 Minor wording changes. Added details comparing current_task to mach_task_self. Added information about using AltiVec and floating point in the kernel. 2004-08-01 2003-09-01 Minor corrections to kernel build information Added information relating to Power Macintosh G5 VM issues and debugging. Clarified wait queue documentation (event_t). 2003-08-01 Minor update release. Added index and tweaked wording throughout. Fixed minor errata in debugging chapter. Added a few missing details in the security chapter and cleaned up the equations presented. Corrected a few very minor OS X v10.2-specific details that weren’t caught during the first revision. 2003-02-01 OS X v10.2 update release. Changed information on KEXT management, various small corrections (mainly wording improvements). 2002-08-01 Full web release to coincide with WWDC. Corrected a few minor errata from the previous release. 2002-06-01 2002-01-01 Initial partial web release. Document Revision History 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 183abstraction (v) The process of separating the interface to some functionality from the underlying implementation in such a way that the implementation can be changed without changing the way that piece of code is used. (n) The API (interface) for some piece of functionality that has been separated in this way. address space The virtual addressranges available to a given task (note: the task may be the kernel). In OS X, processes do not share the same address space. The addressspaces of multiple processes can, however, point to the same physical addressranges. This is referred to as shared memory. anonymous memory Virtual memory backed by the default pager to swap files, rather than by a persistent object. Anonymous memory is zero-initialized and exists only for the life of the task. See also default pager; task. API (application programming interface) The interface (calling convention) by which an application program accesses a service. This service may be provided by the operating system, by libraries, or by other parts of the application. Apple Public Source License Apple’s Open Source license, available at http://www.apple.com/publicsource. Darwin is distributed under this license. See also Open Source. AppleTalk A suite of network protocols that is standard on Macintosh computers. ASCII (American Standard Code for Information Interchange) A 7-bit character set (commonly represented using 8 bits) that defines 128 unique character codes. See also Unicode. BSD (Berkeley Software Distribution Formerly known as the Berkeley version of UNIX, BSD is now simply called the BSD operating system. The BSD portion of the OS X kernel is based on FreeBSD, a version of BSD. bundle A directory thatstores executable code and the software resources related to that code. Applications, plug-ins, and frameworks represent types of bundles. Except for frameworks, bundles are presented by the Finder as if they were a single file. Carbon An application environment in OS X that features a set of programming interfaces derived from earlier versions of the Mac OS. The Carbon APIs have been modified to work properly with OS X. Carbon applications can run in OS X, Mac OS 9, and all versions of Mac OS 8 later than Mac OS 8.1 (with appropriate libraries). Classic An application environment in OS X that lets users run non-Carbon legacy Mac OS software. It supports programs built for both Power PC and 68K processor architectures. clock An object used to abstract time in Mach. 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 184 GlossaryCocoa An advanced object-oriented development platform on OS X. Cocoa is a set of frameworks with programming interfaces in both Java and Objective-C. It is based on the integration of OPENSTEP, Apple technologies, and Java. condition variable Essentially a wait queue with additional locking semantics. When a thread sleeps waiting for some event to occur, it releases a related lock so that another thread can cause that event to occur. When the second thread posts the event, the first thread wakes up, and, depending on the condition variable semantics used, either takes the lock immediately or begins waiting for the lock to become available. console (1) A text-based login environment that also displays system log messages, kernel panics, and other information. (2) A special window in OS X that displays messages that would be printed to the text console if the GUI were not in use. This window also displays output written to the standard error and standard output streams by applications launched from the Finder. (3) An application by the same name that displays the console window. control port In Mach, access to the control port allows an object to be manipulated. Also called the privileged port. See also port; name port. cooperative multitasking A multitasking environment in which a running programcan receive processing time only if other programs allow it; each application must give up control of the processor cooperatively in order to allow others to run. Mac OS 9 is a cooperative multitasking environment. See also preemptive multitasking. copy-on-write A delayed copy optimization used in Mach. The object to be copied is marked temporarily read-only. When a thread attempts to write to any page in that object, a trap occurs, and the kernel copies only the page or pages that are actually being modified. See also thread. daemon A long-lived process, usually without a visible user interface, that performs a system-related service. Daemons are usually spawned automatically by the system and may either live forever or be regenerated at intervals. They may also be spawned by other daemons. Darwin The core of OS X, Darwin is an Open Source project that includes the Darwin kernel, the BSD commands and C libraries, and several additional features.The Darwin kernel is synonymous with the OS X kernel. default pager In Mach, one of the built-in pagers. The default pager handles nonpersistent (anonymous)memory. See also anonymousmemory; vnode pager; pager. demand paging An operating-system facility that brings pages of data from disk into physical memory only as they are needed. DLIL (Data Link Interface Layer) The part of the OS X kernel’s networking infrastructure that provides the interface between protocol handling and network device driversin the I/O Kit. A generalization of the BSD “ifnet” architecture. DMA (direct memory access) A means of transferring data between host memory and a peripheral device without requiring the host processor to move the data itself. This reduces processor overhead for I/O operations and may reduce contention on the processor bus. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 185driver Software that deals with getting data to and from a device, as well as control of that device. In the I/O Kit, an object that manages a piece of hardware (a device), implementing the appropriate I/O Kit abstractions for that device. See also object. DVD (Digital Versatile Disc) Originally, Digital Video Disc. An opticalstorage medium that provides greater capacity and bandwidth than CD-ROM; DVDs are frequently used for multimedia as well as data storage. dyld (dynamic link editor) A utility that allows programs to dynamically load (and link to) needed functions. EMMI (External Memory Management Interface) Mach’sinterface to memory objectsthat allowstheir contents to be contributed by user-mode tasks. See also external pager. Ethernet A family of high-speed local area network technologies in common use. Some common variants include 802.3 and 802.11 (Airport). exception An interruption to the normal flow of program control, caused by the program itself or by executing an illegal instruction. exception port A Mach port on which a task or thread receives messages when exceptions occur. external pager A module that manages the relationship between virtual memory and a backing store. External pagers are clients of Mach’s EMMI. The pager API is currently not exported to userspace. The built-in pagersin OS X are the default pager, the device pager, and the vnode pager. See also EMMI (External Memory Management Interface). family In the I/O Kit, a family defines a collection of software abstractions that are common to all devices of a particular category (for example, PCI, storage, USB). Families provide functionality and services to drivers. See also driver. FAT (file allocation table) A data structure used in the MS-DOS file system. Also synonymous with the file system that uses it. The FAT file system is also used as part of Microsoft Windows and has been adopted for use inside devices such as digital cameras. fat files See universal binaries. FIFO (first-in first-out) A data processing scheme in which data is read in the order in which it was written, processes are run in the order in which they were scheduled, and so forth. file descriptor A per-process unique, nonnegative integer used to identify an open file (or socket). firewall Software (or a computer running such software) that prevents unauthorized access to a network by users outside of the network. fixed-priority policy In Mach, a scheduling policy in which threads execute for a certain quantum of time, and then are put at the end of the queue of threads of equal priority. fork (1) A stream of data that can be opened and accessed individually under a common filename. The Macintosh Standard and Extended file systems store a separate “data” fork and a “resource” fork as part of every file; data in each fork can be accessed and manipulated independently of the other. (2) In BSD, fork is a system call that creates a new process. framework A bundle containing a dynamic shared library and associated resources, including image files, header files, and documentation. Frameworks Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 186are often used to provide an abstraction for manipulating device driver families from applications. FreeBSD A variant of the BSD operating system. See http://www.freebsd.org for details. gdb (GNU debugger) gdb is a powerful, source-level debugger with a command-line interface. gdb is a popular Open Source debugger and is included with the OS X developer tools. HFS (hierarchical file system) The Mac OS Standard file system format, used to represent a collection of files as a hierarchy of directories (folders), each of which may contain either files or foldersthemselves. HFS+ The Mac OS Extended file system format. This file system format was introduced as part of Mac OS 8.1, adding support for filenames longer than 31 characters, Unicode representation of file and directory names, and efficient operation on larger disks. host (1) The computer that is running (is host to) a particular program or service. The term is usually used to refer to a computer on a network. (2) In debugging, the computer that is running the debugger itself. In this context, the target is the machine running the application, kernel, or driver being debugged. host processor The microprocessor on which an application program resides. When an application is running, the host processor may call other, peripheral microprocessors, such as a digital signal processor, to perform specialized operations. IDE (integrated development environment) An application or set of tools that allows a programmer to write, compile, edit, and in some cases test and debug within an integrated, interactive environment. inheritance attribute In Mach, a value indicating the degree to which a parent process and its child process share pages in the parent process’s address space. A memory page can be inherited as copy-on-write, shared, or not at all. in-line data Data that’s included directly in a Mach message, rather than referred to by a pointer. See also out-of-line data. info plist See information property list. information property list A special form of property list with predefined keysforspecifying basic bundle attributes and information of interest, such as supported document types and offered services. See also bundle; property list. interrupt service thread A thread running in kernel space for handling I/O that is triggered by an interrupt, but does not run in an interrupt context. Also called an I/O service thread. I/O (input/output) The exchange of data between two parts of a computer system, usually between system memory and a peripheral device. I/O Kit Apple’s object-oriented I/O development model. The I/O Kit provides a framework for simplified driver development, supporting many families of devices. See also family. I/O service thread See interrupt service thread. IPC (interprocess communication) The transfer of information between processes or between the kernel and a process. IPL (interrupt priority level) A means of basic synchronization on uniprocessor systems in traditional BSD systems, set using the spl macro. Interrupts with lower priority than the current IPL will not be acted upon until the IPL is lowered. In many parts of the kernel, changing the IPL in OS X Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 187is not useful as a means ofsynchronization. New use of spl macros is discouraged. See also spl (set priority level). KDP The kernelshim used for communication with a remote debugger (gdb). Kerberos An authentication system based on symmetric key cryptography. Used in MIT Project Athena and adopted by the Open Software Foundation (OSF). kernel The complete OS X core operating-system environment that includes Mach, BSD, the I/O Kit, file systems, and networking components. kernel crash An unrecoverable system failure in the kernel caused by an illegal instruction, memory access exception, or other failure rather than explicitly triggered as in a panic. See also panic. kernel extension See KEXT (kernel extension). kernel mode See supervisor mode. kernel panic See panic. kernel port A Mach port whose receive right is held by the kernel. See also task port; thread port. KEXT (kernel extension) A bundle that extendsthe functionality of the kernel. The I/O Kit, File system, and Networking components are designed to allow and expect the creation and use of KEXTs. KEXT binary A file (or files) in Mach-O format, containing the actual binary code of a KEXT. A KEXT binary is the minimum unit of code that can be loaded into the kernel. Also called a kernel module or KMOD. See also KEXT (kernel extension); Mach-O. key signing In public key cryptography, to (electronically)state your trust that a public key really belongs to the person who claims to own it, and potentially that the person who claims to own it really is who he or she claims to be. KMOD (kernel module) See KEXT binary. lock A basic means of synchronizing multiple threads. Generally only one thread can “hold” a lock at any given time. While a thread is holding the lock, any other thread that tries to take it will wait, either by blocking or by spinning, depending on the nature of the lock. Some lock variants such as read-write locks allow multiple threads to hold a single lock under certain conditions. Mach The lowest level of the OS X kernel. Mach provides such basic services and abstractions as threads, tasks, ports, IPC, scheduling, physical and virtual address space management, VM, and timers. Mach-O Mach object file format. The preferred object file format for OS X. Mach server A task that providesservicesto clients, using a MIG-generated RPC interface. See also MIG (Mach interface generator). main thread By default, a process has one thread, the main thread. If a process has multiple threads, the main thread is the first thread in the process. A user process can use the POSIX thread API to create other user threads. makefile A makefile detailsthe files, dependencies, and rules by which an executable application is built. memory-mapped files A facility that maps virtual memory onto a physical file. Thereafter, any access to that part of virtual memory causes the corresponding page of the physical file to be accessed. The contents of the file can be changed by changing the contents in memory. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 188memory object An object managed by a pager that represents the memory, file, or other storage that backs a VM object. See also pager. memory protection A system of memory management in which programs are prevented from being able to modify or corrupt the memory partition of another program, usually through the use of separate address spaces. message A unit of data sent by one task or thread that is guaranteed to be delivered atomically to another task or thread. In Mach, a message consists of a header and a variable-length body. Some system services are invoked by passing a message from a thread to the Mach port representing the task that provides the desired service. microkernel A kernel implementing a minimal set of abstractions. Typically, higher-level OS services such as file systems and device drivers are implemented in layers above a microkernel, possibly in trusted user-mode servers. OS X is a hybrid between microkernel and monolithic kernel architectures. See also monolithic kernel. MIG (Mach interface generator) (1) A family of software that generates and supports the use of a procedure call interface to Mach’s system of interprocess communication. (2) The interface description language supported by MIG. monolithic kernel A kernel architecture in which all pieces of the kernel are closely intertwined. A monolithic kernel providessubstantial performance improvements. It is difficult to evolve the individual components independently, however. The OS X kernel is a hybrid of the monolithic and microkernel models. See also microkernel. multicast A process in which a single packet can be addressed to multiple recipients. Multicast is used, for example, in streaming video, in which many megabytes of data are sent over the network. multihoming The ability to have multiple network addresses in one computer, usually on different networks. For example, multihoming might be used to create a system in which one address is used to talk to hosts outside a firewall and the other to talk to hosts inside; the computer provides facilities for passing information between the two. multitasking The concurrent execution of multiple programs. OS X uses preemptive multitasking. Mac OS 9 uses cooperative multitasking. mutex See mutex lock (mutual exclusion lock). mutex lock (mutual exclusion lock) A type of lock characterized by putting waiting threads to sleep until the lock is available. named (memory) entry A handle (a port) to a mappable object backed by a memory manager. The object can be a region or a memory object. name port In Mach, accessto the name port allows non-privileged operations against an object (for example, obtaining information about the object). In effect, it provides a name for the object without providing any significant access to the object. See also port; control port. named region In Mach, a form of named memory entry that provides a form of memory sharing. namespace An agreed-upon context in which names (identifiers) can be defined. Within a given namespace, all names must be unique. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 189NAT (network address translation) A scheme that transforms network packets at a gateway so network addresses that are valid on one side of the gateway are translated into addresses that are valid on the other side. network A group of hosts that can communicate with each other. NFS (network file system) A commonly used file server protocol often found in UNIX and UNIX-based environments. NKE (network kernel extension) A type of KEXT that provides a way to extend and modify the networking infrastructure of OS X dynamically without recompiling or relinking the kernel. NMI (nonmaskable interrupt) An interrupt produced by a particular keyboard sequence or button that cannot be blocked in software. It can be used to interrupt a hung system, for example to drop into a debugger. nonsimple message In Mach, a message that contains either a reference to a port or a pointer to data. See also simple message. notify port A special Mach port that is part of a task. A task’s notify port receives messages from the kernel advising the task of changes in port access rights and of the status of messages it has sent. nub An I/O Kit object that represents a point of connection for a device or logical service. Each nub provides accessto the device orservice it represents, and provides such services as matching, arbitration, and power management. It is most common that a driver publishes one nub for each individual device or service it controls; it is possible for a driver that vends only a single device orservice to act asits own nub. NVRAM (nonvolatile RAM) RAM storage that retains its state even when the power is off. See also RAM (random-access memory). object (1) A collection of data. (2) In Mach, a collection of data, with permissions and ownership. (3) In object-oriented programming, an instance of a class. OHCI (Open Host Controller Interface) The register-level standards that are used by most USB and Firewire controller chips. Open Source Software that includesfreely available access to source code, redistribution, modification, and derived works. The full definition is available at http://www.opensource.org. Open Transport A communications architecture for implementing network protocols and other communication features on computers running classic Mac OS. Open Transport provides a set of programming interfacesthatsupports, among other things, both the AppleTalk and TCP/IP protocols. out-of-line data Data that’s passed by reference in a Mach message, rather than being included in the message. See also in-line data. packet An individual piece of information sent on a network. page (n) (1) The largest block of virtual address space for which the underlying physical address space is guaranteed contiguous—in other words, the unit of mapping between virtual and physical addresses. (2) logical page size: The minimum unit of information that an anonymous pager transfers between system memory and the backing store. (3) physical page size: The unit of information treated as a unit by a hardware MMU. The logical page size must be at least as large as the physical page size Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 190for hardware-based memory protection to be possible. (v) To move data between memory and a backing store. pager A module responsible for providing the data for the pages of a memory object. See also default pager; vnode pager. panic An unrecoverable system failure explicitly triggered by the kernel with a call to panic. See also kernel crash. PEF (Preferred Executable Format) The format of executable files used for applications and shared libraries in Mac OS 9; supported in OS X. The preferred format for OS X is Mach-O. physical address An address to which a hardware device,such as a memory chip, can directly respond. Programs, including the Mach kernel, use virtual addresses that are translated to physical addresses by mapping hardware controlled by the Mach kernel. pmap Part of Mach VM that provides an abstract way to set and fetch virtual to physical mappings from hardware. The pmap system is the machine-dependent layer of the VM system. port In Mach, a secure unidirectional channel for communication between tasks running on a single system. In IP transport protocols, an integer identifier used to select a receiving service for an incoming packet, or to specify the sender of an outgoing packet. port name In Mach, an integer index into a port namespace; a port right is specified with respect to its port name. See also port rights. portrights In Mach, the ability to send to or receive from a Mach port. Also known as port access rights. port set In Mach, a set of zero or more Mach ports. A thread can receive messages sent to any of the ports contained in a port set by specifying the port set as a parameter to msg_receive(). POSIX (Portable Operating System Interface) A standard that defines a set of operating-system services. It is supported by ISO/IEC, IEEE, and The Open Group. preemption The act of interrupting a currently running program in order to give time to another task. preemptive multitasking A type of multitasking in which the operating system can interrupt a currently running task in order to run another task, as needed. See also cooperative multitasking. priority In scheduling, a number that indicates how likely a thread is to run. The higher the thread’s priority, the more likely the thread isto run. See also scheduling policy. process A BSD abstraction for a running program. A process’s resources include an address space, threads, and file descriptors. In OS X, a process is based on one Mach task and one or more Mach threads. process identifier (PID), A number that uniquely identifies a process. Also called a process ID. programmed I/O I/O in which the CPU accomplishes data transfer with explicit load and store instructions to device registers, rather than DMA, and without the use of interrupts. This data transfer is often done in a byte-by-byte, or word-by-word fashion. Also known as direct or polled I/O. See also DMA (direct memory access). property list A textual way to represent data. Elements of the property list represent data of certain types,such as arrays, dictionaries, and strings. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 191System routines allow programs to read property lists into memory and convert the textual data representation into “real” data. See also information property list. protected memory See memory protection. protocol handler A network module that extracts data from input packets (giving the data to interested programs) and inserts data into output packets(giving the output packet to the appropriate network device driver). pthreads The POSIX threads implementation. See also POSIX (Portable Operating System Interface); thread. quantum The fixed amount of time a thread or process can run before being preempted. RAM (random-access memory) Memory that a microprocessor can either read from or write to. real-time performance Performance characterized by guaranteed worst-case response times. Real-time support is important for applications such as multimedia. receive rights In Mach, the ability to receive messages on a Mach port. Only one task at a time can have receive rights for any one port. See also send rights. remote procedure call See RPC (remote procedure call). reply port A Mach port associated with a thread that is used in remote procedure calls. ROM (read-only memory) Memory that cannot be written to. root (1) An administrative account with special privileges. For example, only the root account can load kernel extensions.(2) In graph theory, the base of a tree. (3) root directory: The base of a file system tree. (4) root file system: The primary file system off which a computer boots, so named because it includes the root node of the file system tree. routine In Mach, a remote procedure call that returns a value. This can be used for synchronous or asynchronous operations. See also simpleroutine. RPC (remote procedure call) An interface to IPC that appears (to the caller) as an ordinary function call. In Mach, RPCs are implemented using MIG-generated interface libraries and Mach messages. scheduling The determination of when each process or task runs, including assignment of start times. scheduling policy In Mach, how the thread’s priority isset and under what circumstancesthe thread runs. See also priority. SCSI (Small Computer Systems Interface) A standard communications protocol used for connecting devicessuch as disk drivesto computers. Also, a family of physical bus designs and connectors commonly used to carry SCSI communication. semaphore Similar to a lock, except that a finite number of threads can be holding a semaphore at the same time. See also lock. send rights In Mach, the ability to send messages to a Mach port. Many tasks can have send rights for the same port. See also receive rights. session key In cryptography, a temporary key that is only used for one message, one connection session, orsimilar. Session keys are generally treated asshared secrets, and are frequently exchanged over a channel encrypted using public key cryptography. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 192shadow object In Mach VM, a memory object that holds modified pages that originally belonged to another memory object. Thisis used when an object that was duplicated in a copy-on-write fashion is modified. If a page is not found in this shadow object, the original object is referenced. simple message In Mach, a message that contains neither references to ports nor pointers to data. See also nonsimple message. simpleroutine In Mach, a remote procedure call that does not return a value, and has no out or inout parameters. This can be used for asynchronous operations. See also routine. SMP (symmetric multiprocessing) A system architecture in which two or more processors are managed by one kernel, share the same memory, have equal access to I/O devices, and in which any task, including kernel tasks, can run on any processor. spinlock Any of a family of lock types characterized by continuously polling to see if a lock is available, rather than putting the waiting thread to sleep. spin/sleep lock Any of a family of lock types characterized by some combination of the behaviors of spinlocks and mutex (sleep) locks. spl (set priority level) A macro thatsetsthe current IPL. Interrupts with lower priority than the current IPL will not be acted upon until the IPL is lowered. The spl macros have no effect in many parts of OS X, so their use is discouraged as a means of synchronization in new programming except when modifying code that already uses spl macros. See also IPL (interrupt priority level). socket (1) In a user process, a file descriptor that has been allocated using socket(2). (2) In the kernel, the data structure allocated when the kernel’s implementation of the socket(2) call is made. (3) In AppleTalk protocols, a socket serves the same purpose as a port in IP transport protocols. submap A collection of mappingsin the VM system that is shared among multiple Mach tasks. supervisor mode Also known as kernel mode, the processor mode in which certain privileged instructions can be executed, including those related to page table management, cache management, clock setting, and so on. symmetric multiprocessing See SMP (symmetric multiprocessing). task A Mach abstraction, consisting of a virtual address space and a port namespace. A task itself performs no computation; rather, it isthe framework in which threads run. See also thread. task port A kernel port that represents a task and is used to manipulate that task. See also kernel port; thread port. TCP/IP (Transmission Control Protocol/Internet Protocol) An industry standard protocol used to deliver messages between computers over the network. TCP/IP is the primary networking protocol used in OS X. thread The unit of program execution. A thread consists of a program counter, a set of registers, and a stack pointer. See also task. thread port A kernel port that represents a thread and is used to manipulate that thread. See also kernel port; task port. thread-safe code Code that can be executed safely by multiple threads simultaneously. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 193time-sharing policy In Mach, a scheduling policy in which a thread’s priority is raised and lowered to balance its resource consumption against other timesharing threads. UDF (Universal Disk Format) The file system format used in DVD disks. UFS (UNIX file system) An industry standard file system format used in UNIX and similar operating systems such as BSD. UFS in OS X is a derivative of 4.4BSD UFS. Unicode A 16-bit character set that defines unique character codes for characters in a wide range of languages. Unlike ASCII, which defines 128 distinct characters typically represented in 8 bits, there are as many as 65,536 distinct Unicode characters that represent the unique characters used in most foreign languages. universal binaries Executable files containing object code for more than one machine architecture. UPL (universal page list) A data structure used when communicating with the virtual memory system. UPLs can be used to change the behavior of pages with respect to caching, permissions, mapping, and so on. USB (Universal Serial Bus) A multiplatform bus standard that can support up to 127 peripheral devices, including printers, digital cameras, keyboards and mice, and storage devices. UTF-8 (Unicode Transformation Format 8) A format used to represent a sequence of 16-bit Unicode characters with an equivalent sequence of 8-bit characters, none of which are zero. This sequence of characters can be represented using an ordinary C language string. VFS (virtual file system) A set of standard internal file-system interfaces and utilities that facilitate support for additional file systems. VFS provides an infrastructure for file systems built into the kernel. virtual address An address as viewed from the perspective of an application. Each task has its own range of virtual addresses, beginning at address zero. The Mach VM system makes the CPU hardware map these addresses onto physical memory. See also physical address. virtual memory A system in which addresses as seen by software are not the same as addressesseen by the hardware. This provides support for memory protection, reduces the need for code relocatability, and allows the operating system to provide the illusion to each application that it has resources much larger than those that could actually be backed by RAM. VM See virtual memory. vnode An in-memory data structure containing information about a file. vnode pager In Mach, one of the built-in pagers. The vnode pager maps files into memory objects. See also default pager; pager. work loop The main loop of an application or KEXT that waits repeatedly for incoming events and dispatches them. XML (Extensible Markup Language) A dialect of SGML (Standard Generalized Markup Language), XML provides a metalanguage containing rules for constructing specialized markup languages. XML users can create their own tags, making XML very flexible. Glossary 2012-02-16 | © 2002, 2012 Apple Inc. All Rights Reserved. 194Apple Inc. © 2002, 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, AppleTalk, Carbon, Cocoa, Finder, FireWire, Keychain, Logic, Mac, Mac OS, Macintosh, Objective-C, OS X, Pages, Panther, Power Mac,Quartz,QuickTime, Spaces, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. .Mac is a service mark of Apple Inc., registered in the U.S. and other countries. NeXT and OPENSTEP are trademarks of NeXT Software, Inc., registered in the U.S. and other countries. DEC is a trademark of Digital Equipment Corporation. Intel and Intel Core are registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries. Java is a registered trademark of Oracle and/or its affiliates. OpenGL is a registered trademark of Silicon Graphics, Inc. PowerPC and the PowerPC logo are trademarks of International Business Machines Corporation, used under license therefrom. SPEC is a registered trademark of the Standard Performance Evaluation Corporation (SPEC). UNIX is a registered trademark of The Open Group. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. RED Workflows with Final Cut Pro X White Paper June 2012White Paper 2 RED Workflows with Final Cut Pro X With the continuing popularity of the RED® family of cameras (www.red.com), Final Cut Pro X editors have been looking for proven workflows with REDCODE® RAW files. This white paper outlines how professional production companies are achieving excellent results when recording with RED cameras, editing in Final Cut Pro X, and finishing in applications such as DaVinci Resolve. This document outlines a complete RED-based post-production workflow, following the steps below: 1. Transcode REDCODE RAW files to Apple ProRes using REDCINE-X® PRO. 2. Batch sync audio and video files. 3. Import synced files into Final Cut Pro X. During import, Final Cut Pro X can automatically create lightweight Apple ProRes 422 (Proxy) files for editing. Or, if you have a lot of footage and multiple editors, you can use Compressor to create the Apple ProRes 422 (Proxy) files. 4. Edit and lock picture with Final Cut Pro X. 5. Export an XML file of the project from Final Cut Pro X. 6. Color grade the project in DaVinci Resolve using either high-quality Apple ProRes or R3D RAW files. You can relink the project XML file to the original R3D files in either REDCINE-X PRO or DaVinci Resolve. 7. Export an XML file from DaVinci Resolve and import it back into Final Cut Pro X. 8. Export a final master from Final Cut Pro X. This method combines the best of both worlds—the speed of editing with Apple ProRes on a wide variety of notebook and desktop systems, and the color grading advantages of RAW when finishing. You can further simplify this workflow by transcoding to high-quality Apple ProRes files and using those throughout color grading and delivery. The sections below include additional detail about each stage of the workflow. Transcode REDCODE RAW Files to Apple ProRes RED cameras record a RAW file (R3D) that must be “debayered” and decompressed to convert the original sensor data to viewable pixels, so that the file can play back in video editing software. Apple ProRes is an excellent choice for this conversion, because it’s a codec optimized for both quality and editing speed. Apple ProRes is a full frame size, intra-frame codec designed to efficiently use multiple processors for playback and rendering. The free RED application REDCINE-X PRO supports Apple ProRes encoding, which can be accelerated using the RED ROCKET® card. REDCINE-X PRO also allows you to apply a “one-light” color correction during the transcoding process, giving your footage a more finished look for editing and review.White Paper 3 RED Workflows with Final Cut Pro X In the Field As workflows expand to include field review and even rough cut editing, digital imaging technicians (DITs) are actively transcoding R3D footage to Apple ProRes using high-end portable systems. A typical field-based workflow includes these steps: • Copy the footage from the camera’s recording medium, like the REDMAG™ removable solid-state drive (SSD). • Create backups so that camera originals can be stored in two different places for data protection. • Create Apple ProRes dailies by transcoding the R3D files to Apple ProRes files for editing and H.264 files for uploading to a secure website for client review. Alternatively, after making backup copies, you can deliver the R3D files to the post facility for transcoding to Apple ProRes dailies. Choose Transcoding Settings When you transcode your files to Apple ProRes, choose the level of quality that’s appropriate to your specific production. Workflow Apple ProRes codec Disk space is a consideration, or you’re editing a large multicam project. Apple ProRes 422 (Proxy) or Apple ProRes 422 (LT) You’re delivering Apple ProRes files as a final master for the web or TV. Apple ProRes 422 or Apple ProRes 422 (HQ) You’re delivering for theater projection or effects compositing. Apple ProRes 4444 Although you can transcode to the final delivery quality and then work with that throughout post-production, it’s more efficient to work with smaller frame sizes and higher image compression during the craft edit. So even though you may have shot at 4K or 5K resolution in the field, you can transcode to a smaller frame size to save time and disk space. For example, you can set the resolution to 1920x1080 or 1280x720, and you can set the debayer quality to 1/4. If you’re generating Apple ProRes files for use as proxy media, you can also choose to superimpose, or “burn in,” the source timecode and filename over the image. This makes it easy to go back to the original R3D files at any point during post-production for a quick visual double-check that the files are correct. For more details, see the REDCINE-X PRO manual at https://www.red.com/downloads. Note: You can speed up transcoding by using a RED ROCKET card, which offloads the processor-intensive debayer and decompression tasks from software to custom hardware. RED ROCKET can be a valuable tool when transcoding a large number of shots.White Paper 4 RED Workflows with Final Cut Pro X Apply One-Light Color Correction When recording with RED cameras, it’s common to shoot a scene “flat” to avoid clipping highlights and shadows and provide more flexibility when manipulating images in post-production. This recording setup can give the footage a washed-out appearance. Many editors and clients prefer working with more visually appealing images that include higher contrast and color saturation. To accommodate this workflow, the free REDCINE-X PRO application allows you to add a one-light color correction as part of the transcoding process. You can choose from several presets to create more common looks, or you can create your own look. Be sure to keep the original names of the R3D files when you generate new Apple ProRes media so that you can easily relink to them later. After you apply the one-light color correction during transcoding, it stays with the image until you go back to the original R3D file and create a new Apple ProRes version. Batch Sync Audio and Video Files After all your media has been transcoded, you can choose to sync second-source audio to the video files. You can sync the files directly in Final Cut Pro X using the built-in synchronization feature that analyzes waveforms to match the scratch audio in your video files to the high-quality audio from your field recorder. You can also use a third-party application like Intelligent Assistance’s Sync-N-Link X (www.intelligentassistance.com), RED’s REDCINE-X PRO (www.red.com/learn), or Singular Software’s PluralEyes (www.singularsoftware.com). Simply select all the audio and Apple ProRes video files and batch sync. Then export the XML to Final Cut Pro X, and all of the synced material is imported into an event, ready for editing. Import Files into Final Cut Pro X After creating Apple ProRes files with REDCINE-X PRO, you can import these files directly into Final Cut Pro X. Even if you transcode R3D files to a high-quality Apple ProRes codec, such as Apple ProRes 4444, you may still choose to use lightweight Apple ProRes 422 (Proxy) files for editing. Final Cut Pro X allows you to generate Apple ProRes proxy files in the background and seamlessly switch to these files for editing, providing great flexibility when editing on a notebook, for example. To create proxy files while importing media 1. In Final Cut Pro, choose File > Import > Files. 2. Select a file or folder, or Command-click to select multiple files to import. 3. Do one of the following: • To add the imported files to an existing event: Select “Add to existing Event,” and choose the event from the pop-up menu. • To create a new event: Select “Create new Event,” type a name in the text field, and choose the disk where you want to store the event from the “Save to” pop-up menu. 4. To have Final Cut Pro copy your media files and add them to the Final Cut Pro Events folder you specified, select the “Copy files to Final Cut Events folder” checkbox. If you’re working with a SAN and want to keep the files in a central location and have multiple users link to them, leave this option unselected. For more information, see Final Cut Pro X: Xsan Best Practices.White Paper 5 RED Workflows with Final Cut Pro X 5. Select the “Create proxy media” checkbox. When this option is selected, Final Cut Pro creates Apple ProRes 422 (Proxy) files in the background after the media files are imported. You can begin to edit your project and, when the proxy files are created, you can open Playback preferences and switch to the proxy files with a single click. 6. Click Import. Final Cut Pro imports your media in the background, and then creates proxy files in the background. You can view the progress of the background tasks in the Background Tasks window. You can now begin editing, even if importing and transcoding are not yet complete. To switch to the Apple ProRes proxy files, select “Use proxy media” in Final Cut Pro Playback preferences. It’s just as easy to switch back to the original media when the creative editing is finished and you want to work on color or effects at the highest quality. When you change these settings, all media in events and projects is affected. Edit in Final Cut Pro X and Export XML After all your media has been imported into Final Cut Pro X, you can edit just as you would any other project. The application was designed for modern, file-based workflows, making it easy to browse, organize, and edit large amounts of material. Use skimming to quickly view your footage. Mark range-based keywords and favorites, and save custom searches as Smart Collections. Quickly and easily arrange clips in the Timeline and add titles and effects, which render in the background as you work. When you’re finished editing, you can send your project to a third-party finishing system such as DaVinci Resolve. Just select the project in the Project Library, choose File > Export XML, and select a location to save the XML file. Color Grade in DaVinci Resolve and Export XML Choose Apple ProRes or RAW for Grading Before importing the Final Cut Pro X XML file into DaVinci Resolve, you should choose between a few different color grading workflows. If you edited with Apple ProRes 422 (HQ) or Apple ProRes 4444 in Final Cut Pro X, you may want to grade these same files in DaVinci Resolve. Alternatively, you can relink the project to the original R3D files in either DaVinci Resolve or REDCINE-X PRO. These RAW files offer a wide range of values to use when grading, which can help improve the look of images that were shot without extensive lighting control or that need a unique style. You can get more image detail out of the highlights and shadows, which is why so many colorists choose to use the RAW files in the color grading stage. White Paper 6 RED Workflows with Final Cut Pro X To relink to the original R3D media in DaVinci Resolve 1. In DaVinci Resolve Preferences, add the location of the R3D files to the Media Storage Volumes list. 2. Save the preferences and reopen DaVinci Resolve. 3. On the Browse page, import the R3D files to the Media Pool. 4. On the Conform page, in the Timeline Management section, click the Load button. 5. Select the XML file that you exported from Final Cut Pro X. 6. In the Load XML window, deselect “Automatically import source clips into media pool.” 7. Choose any other options that are applicable to your project, and click Ok. The XML file is imported and relinked to the corresponding media in the Media Pool using reel name and timecode. A new session appears in the Timeline Management list, and the edit appears in the Timeline. Note: Alternatively, if you’re working with large amounts of media and DaVinci Resolve 8.1 or later, you can have DaVinci Resolve relink to the R3D files automatically when you import the XML file. Just be sure to select the following checkboxes: • Automatically import source clips into media pool • Ignore file extensions when matching Render New Media After color grading the final project in DaVinci Resolve, you can choose the render format based on your final delivery. For example, you may choose to render Apple ProRes 4444 for theater projection, or Apple ProRes 422 if you’re delivering a master for the web or TV. You may want to set a handle length for the rendered media (at least one second), so that you can make additional changes such as adding a longer dissolve or extending an edit. For more details, see the DaVinci Resolve manual at http://www.blackmagic-design.com/support. Export XML from DaVinci Resolve and Import into Final Cut Pro X After you render the media in DaVinci Resolve, you can transfer the project back to Final Cut Pro X by exporting an XML file. To export an XML file from DaVinci Resolve 1. Open the Conform page and, in the Timeline Management list, select the session you want to export an XML file from. 2. Click the Export button at the bottom of the Timeline Management list. 3. In the Export XML dialog, choose FCP X XML 1.1 Files from the Format pop-up menu, type a name and choose a location for the exported XML file, and click Save. An XML version of that session is saved, complete with internal references to the graded media you rendered, and ready for importing into Final Cut Pro X. Import the XML file back into Final Cut Pro X using the Import XML command in the File menu. Make sure that you’re linking to the high-quality media by selecting “Use original or optimized media” in the Playback pane of the Final Cut Pro Preferences window. Now you can add finished audio, adjust titles, insert graphics, and continue to make editorial changes. Because you’ve imported the individual media files and the XML metadata instead of a single QuickTime movie, you can make changes right up to the last minute before delivery. For information about Final Cut Pro X, see Final Cut Pro X Help.White Paper 7 RED Workflows with Final Cut Pro X Copyright © 2012 Apple Inc. All rights reserved. Apple, the Apple logo, Final Cut, Final Cut Pro, QuickTime, and Xsan are trademarks of Apple Inc., registered in the U.S. and other countries. R3D, RED, REDCINE, REDCINE-X, REDCODE, REDMAG, and RED ROCKET are trademarks or registered trademarks of Red.com, Inc. in the United States and other countries. The YouTube logo is a trademark of Google Inc. Other product and company names mentioned herein may be trademarks of their respective companies. Mention of third-party products is for informational purposes only and constitutes neither an endorsement nor a recommendation. Apple assumes no responsibility with regard to the performance or use of these products. Product specifications are subject to change without notice. 019-2378 June 2012 Export a Master from Final Cut Pro X The final step in the workflow is to export a finished master from Final Cut Pro X. To export your project as a master file 1. To make sure the project’s render format is set to the quality level you want for the final master, select the project in the Project Library, click the Inspector button in the toolbar, and click the Project Properties button . The Render Format pop-up menu shows the current render codec. 2. Select the project in the Project Library and choose Share > Export Media (or press Command-E). 3. Choose an option from the Export pop-up menu. The default setting, Video and Audio, creates a movie file containing both video and audio. For information about the other options, see Final Cut Pro X Help. To export a file that matches the project’s properties, choose Current Settings from the “Video codec” pop-up menu. When you export using Current Settings, the final master is exported at the quality of the render settings, and the export is as fast as a file copy with no further compression added. 4. To see details about the file that will be output, click Summary. 5. Click Next, type a name and choose a location for the exported file, and click Save. If you’re exporting for review on the web, you can export an H.264 version directly to a private account on YouTube or Vimeo. You can also burn the project to a DVD, or to a Blu-ray disc if you have a third-party Blu-ray burner. If you have Compressor installed, you can choose Share > Send to Compressor to transfer your project to that application for total control over your final export settings. Compressor also allows you to set up render clusters that use the processors of multiple computers on a network. Create a Compressor droplet for drag-and-drop simplicity, or create custom export settings to match unique delivery requirements. If you need to output to tape, all three major video I/O device manufacturers offer free software to support tape delivery. The applications are AJA‘s VTR Xchange, Blackmagic Design’s Media Express, and Matrox’s Vetura. Download the application that works with your video I/O device and use the QuickTime export from Final Cut Pro X to lay back to tape. Conclusion Using Apple ProRes for editing and R3D RAW files for color grading enables a highly flexible workflow optimized for speed, quality, and creative control. This process also takes advantage of the metadata and XML capabilities of Final Cut Pro X, which have been designed for the future of file-based production. By using this document as a template for working with RED and Final Cut Pro X, editors and post-production facilities can further customize the process to suit their unique needs. Transitioning to ARC Release NotesContents Transitioning to ARC Release Notes 3 Summary 3 ARC Overview 4 ARC Enforces New Rules 5 ARC Introduces New Lifetime Qualifiers 7 ARC Uses a New Statement to Manage Autorelease Pools 11 Patterns for Managing Outlets Become Consistent Across Platforms 11 Stack Variables Are Initialized with nil 12 Use Compiler Flags to Enable and Disable ARC 12 Managing Toll-Free Bridging 12 The Compiler Handles CF Objects Returned From Cocoa Methods 13 Cast Function Parameters Using Ownership Keywords 14 Common Issues While Converting a Project 15 Frequently Asked Questions 19 Document Revision History 23 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 2Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. Rather than having to think about about retain and release operations, ARC allows you to concentrate on the interesting code, the object graphs, and the relationships between objects in your application. {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} {app_code} Reference counting manually Automatic Reference Counting retain/release code retain/release code retain/release code retain/release code retain/release code retain/release code Time to produce Time to produce Summary ARC works by adding code at compile time to ensure that objects live as long as necessary, but no longer. Conceptually, it follows the same memory management conventions as manual reference counting (described in Advanced Memory Management Programming Guide ) by adding the appropriate memory management calls for you. 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 3 Transitioning to ARC Release NotesIn order for the compiler to generate correct code, ARC restricts the methods you can use and how you use toll-free bridging (see “Toll-Free Bridged Types”). ARC also introduces new lifetime qualifiers for object references and declared properties. ARC is supported in Xcode 4.2 for OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS 5. Weak references are not supported in OS X v10.6 and iOS 4. Xcode provides a tool that automates the mechanical parts of the ARC conversion (such as removing retain and release calls) and helps you to fix issues the migrator can’t handle automatically (choose Edit > Refactor > Convert to Objective-C ARC). The migration tool converts all filesin a project to use ARC. You can also choose to use ARC on a per-file basis if it’s more convenient for you to use manual reference counting for some files. See also: ● Advanced Memory Management Programming Guide ● Memory Management Programming Guide for Core Foundation ARC Overview Instead of you having to remember when to use retain, release, and autorelease, ARC evaluates the lifetime requirements of your objects and automatically inserts appropriate memory management calls for you at compile time. The compiler also generates appropriate dealloc methods for you. In general, if you’re only using ARC the traditional Cocoa naming conventions are important only if you need to interoperate with code that uses manual reference counting. A complete and correct implementation of a Person class might look like this: @interface Person : NSObject @property NSString *firstName; @property NSString *lastName; @property NSNumber *yearOfBirth; @property Person *spouse; @end @implementation Person @end Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 4(Object properties are strong by default; the strong attribute is described in “ARC Introduces New Lifetime Qualifiers” (page 7).) Using ARC, you could implement a contrived method like this: - (void)contrived { Person *aPerson = [[Person alloc] init]; [aPerson setFirstName:@"William"]; [aPerson setLastName:@"Dudney"]; [aPerson setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]]; NSLog(@"aPerson: %@", aPerson); } ARC takes care of memory management so that neither the Person nor the NSNumber objects are leaked. You could also safely implement a takeLastNameFrom: method of Person like this: - (void)takeLastNameFrom:(Person *)person { NSString *oldLastname = [self lastName]; [self setLastName:[person lastName]]; NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]); } ARC ensures that oldLastName is not deallocated before the NSLog statement. ARC Enforces New Rules To work, ARC imposes some new rules that are not present when using other compiler modes. The rules are intended to provide a fully reliable memory management model; in some cases, they simply enforce best practice, in some others they simplify your code or are obvious corollaries of your not having to deal with memory management. If you violate these rules, you get an immediate compile-time error, not a subtle bug that may become apparent at runtime. ● You cannot explicitly invoke dealloc, or implement or invoke retain, release, retainCount, or autorelease. The prohibition extends to using @selector(retain), @selector(release), and so on. Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 5You may implement a dealloc method if you need to manage resources other than releasing instance variables. You do not have to (indeed you cannot) release instance variables, but you may need to invoke [systemClassInstance setDelegate:nil] on system classes and other code that isn’t compiled using ARC. Custom dealloc methods in ARC do not require a call to [super dealloc] (it actually results in a compiler error). The chaining to super is automated and enforced by the compiler. You can still use CFRetain, CFRelease, and other related functions with Core Foundation-style objects (see “Managing Toll-Free Bridging” (page 12)). ● You cannot use NSAllocateObject or NSDeallocateObject. You create objects using alloc; the runtime takes care of deallocating objects. ● You cannot use object pointers in C structures. Rather than using a struct, you can create an Objective-C class to manage the data instead. ● There is no casual casting between id and void *. You must use special caststhat tell the compiler about object lifetime. You need to do thisto cast between Objective-C objects and Core Foundation types that you pass as function arguments. For more details, see “Managing Toll-Free Bridging” (page 12). ● You cannot use NSAutoreleasePool objects. ARC provides @autoreleasepool blocks instead. These have an advantage of being more efficient than NSAutoreleasePool. ● You cannot use memory zones. There is no need to use NSZone any more—they are ignored by the modern Objective-C runtime anyway. To allow interoperation with manual retain-release code, ARC imposes a constraint on method naming: ● You cannot give an accessor a name that begins with new. This in turn means that you can’t, for example, declare a property whose name begins with new unless you specify a different getter: // Won't work: @property NSString *newTitle; // Works: @property (getter=theNewTitle) NSString *newTitle; Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 6ARC Introduces New Lifetime Qualifiers ARC introduces several new lifetime qualifiers for objects, and weak references. A weak reference does not extend the lifetime of the object it points to, and automatically becomes nil when there are no strong references to the object. You should take advantage of these qualifiers to manage the object graphs in your program. In particular, ARC does not guard against strong reference cycles (previously known as retain cycles—see “Practical Memory Management”). Judicious use of weak relationships will help to ensure you don’t create cycles. Property Attributes The keywords weak and strong are introduced as new declared property attributes, asshown in the following examples. // The following declaration is a synonym for: @property(retain) MyClass *myObject; @property(strong) MyClass *myObject; // The following declaration is similar to "@property(assign) MyClass *myObject;" // except that if the MyClass instance is deallocated, // the property value is set to nil instead of remaining as a dangling pointer. @property(weak) MyClass *myObject; Under ARC, strong is the default for object types. Variable Qualifiers You use the following lifetime qualifiers for variables just like you would, say, const. __strong __weak __unsafe_unretained __autoreleasing ● __strong is the default. An object remains “alive” as long as there is a strong pointer to it. ● __weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object. Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 7● __unsafe_unretained specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling. ● __autoreleasing is used to denote argumentsthat are passed by reference (id *) and are autoreleased on return. You should decorate variables correctly. When using qualifiers in an object variable declaration, the correct format is: ClassName * qualifier variableName; for example: MyClass * __weak myWeakReference; MyClass * __unsafe_unretained myUnsafeReference; Other variants are technically incorrect but are “forgiven” by the compiler. To understand the issue, see http://cdecl.org/. Take care when using __weak variables on the stack. Consider the following example: NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]]; NSLog(@"string: %@", string); Although string is used after the initial assignment, there is no other strong reference to the string object at the time of assignment; it is therefore immediately deallocated. The log statement shows that string has a null value. (The compiler provides a warning in this situation.) You also need to take care with objects passed by reference. The following code will work: NSError *error; BOOL OK = [myObject performOperationWithError:&error]; if (!OK) { // Report the error. // ... However, the error declaration is implicitly: Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 8NSError * __strong e; and the method declaration would typically be: -(BOOL)performOperationWithError:(NSError * __autoreleasing *)error; The compiler therefore rewrites the code: NSError * __strong error; NSError * __autoreleasing tmp = error; BOOL OK = [myObject performOperationWithError:&tmp]; error = tmp; if (!OK) { // Report the error. // ... The mismatch between the local variable declaration (__strong) and the parameter (__autoreleasing) causesthe compiler to create the temporary variable. You can get the original pointer by declaring the parameter id __strong * when you take the address of a __strong variable. Alternatively you can declare the variable as __autoreleasing. Use Lifetime Qualifiers to Avoid Strong Reference Cycles You can use lifetime qualifiers to avoid strong reference cycles. For example, typically if you have a graph of objects arranged in a parent-child hierarchy and parents need to refer to their children and vice versa, then you make the parent-to-child relationship strong and the child-to-parent relationship weak. Other situations may be more subtle, particularly when they involve block objects. In manual reference counting mode, __block id x; hasthe effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use __unsafe_unretained __block id x;. As the name __unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle. The following code fragment illustrates this issue using a pattern that is sometimes used in manual reference counting. Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 9MyViewController *myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; }; [self presentViewController:myController animated:YES completion:^{ [myController release]; }]; As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler: MyViewController * __block myController = [[MyViewController alloc] init…]; // ... myController.completionHandler = ^(NSInteger result) { [myController dismissViewControllerAnimated:YES completion:nil]; myController = nil; }; Alternatively, you can use a temporary __weak variable. The following example illustrates a simple implementation: MyViewController *myController = [[MyViewController alloc] init…]; // ... MyViewController * __weak weakMyViewController = myController; myController.completionHandler = ^(NSInteger result) { [weakMyViewController dismissViewControllerAnimated:YES completion:nil]; }; For non-trivial cycles, however, you should use: MyViewController *myController = [[MyViewController alloc] init…]; // ... MyViewController * __weak weakMyController = myController; myController.completionHandler = ^(NSInteger result) { Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 10MyViewController *strongMyController = weakMyController; if (strongMyController) { // ... [strongMyController dismissViewControllerAnimated:YES completion:nil]; // ... } else { // Probably nothing... } }; In some cases you can use __unsafe_unretained if the class isn’t __weak compatible. This can, however, become impractical for nontrivial cycles because it can be hard or impossible to validate that the __unsafe_unretained pointer is still valid and still points to the same object in question. ARC Uses a New Statement to Manage Autorelease Pools Using ARC, you cannot manage autorelease pools directly using the NSAutoreleasePool class. Instead, you use @autoreleasepool blocks: @autoreleasepool { // Code, such as a loop that creates a large number of temporary objects. } This simple structure allows the compiler to reason about the reference count state. On entry, an autorelease pool is pushed. On normal exit (break, return, goto, fall-through, and so on) the autorelease pool is popped. For compatibility with existing code, if exit is due to an exception, the autorelease pool is not popped. Thissyntax is available in all Objective-C modes. It is more efficient than using the NSAutoreleasePool class; you are therefore encouraged to adopt it in place of using the NSAutoreleasePool. Patterns for Managing Outlets Become Consistent Across Platforms The patternsfor declaring outletsin iOS and OS X change with ARC and become consistent across both platforms. The pattern you should typically adopt is: outletsshould be weak, except for those from File’s Owner to top-level objects in a nib file (or a storyboard scene) which should be strong. Full details are given in “Nib Files” in Resource Programming Guide . Transitioning to ARC Release Notes ARC Overview 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 11Stack Variables Are Initialized with nil Using ARC,strong, weak, and autoreleasing stack variables are now implicitly initialized with nil. For example: - (void)myMethod { NSString *name; NSLog(@"name: %@", name); } will log null for the value of name rather than perhaps crashing. Use Compiler Flags to Enable and Disable ARC You enable ARC using a new -fobjc-arc compiler flag. You can also choose to use ARC on a per-file basis if it’s more convenient for you to use manual reference counting for some files. For projects that employ ARC as the default approach, you can disable ARC for a specific file using a new -fno-objc-arc compiler flag for that file. ARC is supported in Xcode 4.2 and later OS X v10.6 and later (64-bit applications) and for iOS 4 and later. Weak references are not supported in OS X v10.6 and iOS 4. There is no ARC support in Xcode 4.1 and earlier. Managing Toll-Free Bridging In many Cocoa applications, you need to use Core Foundation-style objects, whether from the Core Foundation framework itself (such as CFArrayRef or CFMutableDictionaryRef) or from frameworks that adopt Core Foundation conventions such as Core Graphics (you might use types like CGColorSpaceRef and CGGradientRef). The compiler does not automatically manage the lifetimes of Core Foundation objects; you must call CFRetain and CFRelease (or the corresponding type-specific variants) as dictated by the Core Foundation memory management rules (see Memory Management Programming Guide for Core Foundation ). If you cast between Objective-C and Core Foundation-style objects, you need to tell the compiler about the ownership semantics of the object using either a cast (defined in objc/runtime.h) or a Core Foundation-style macro (defined in NSObject.h): ● __bridge transfers a pointer between Objective-C and Core Foundation with no transfer of ownership. ● __bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you. Transitioning to ARC Release Notes Managing Toll-Free Bridging 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 12You are responsible for calling CFRelease or a related function to relinquish ownership of the object. ● __bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC. ARC is responsible for relinquishing ownership of the object. For example, if you had code like this: - (void)logFirstNameOfPerson:(ABRecordRef)person { NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); NSLog(@"Person's first name: %@", name); [name release]; } you could replace it with: - (void)logFirstNameOfPerson:(ABRecordRef)person { NSString *name = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty)); NSLog(@"Person's first name: %@", name); } The Compiler Handles CF Objects Returned From Cocoa Methods The compiler understands Objective-C methods that return Core Foundation types follow the historical Cocoa naming conventions (see Advanced Memory Management Programming Guide ). For example, the compiler knows that, in iOS, the CGColor returned by the CGColor method of UIColor is not owned. You must still use an appropriate type cast, as illustrated by this example: NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; [colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; Transitioning to ARC Release Notes Managing Toll-Free Bridging 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 13Cast Function Parameters Using Ownership Keywords When you cast between Objective-C and Core Foundation objectsin function calls, you need to tell the compiler about the ownership semantics of the passed object. The ownership rules for Core Foundation objects are those specified in the Core Foundation memory management rules (see Memory Management Programming Guide for Core Foundation ); rules for Objective-C objects are specified in Advanced Memory Management Programming Guide . In the following code fragment, the array passed to the CGGradientCreateWithColors function requires an appropriate cast. Ownership of the object returned by arrayWithObjects: is not passed to the function, thus the cast is __bridge. NSArray *colors = <#An array of colors#>; CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations); The code fragment is shown in context in the following method implementation. Notice also the use of Core Foundation memory management functions where dictated by the Core Foundation memory management rules. - (void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); CGFloat locations[2] = {0.0, 1.0}; NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; [colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations); CGColorSpaceRelease(colorSpace); // Release owned Core Foundation object. CGPoint startPoint = CGPointMake(0.0, 0.0); CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds)); CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CGGradientRelease(gradient); // Release owned Core Foundation object. } Transitioning to ARC Release Notes Managing Toll-Free Bridging 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 14Common Issues While Converting a Project When migrating existing projects, you are likely to run into various issues. Here are some common issues, together with solutions. You can’t invoke retain, release, or autorelease. This is a feature. You also can’t write: while ([x retainCount]) { [x release]; } You can’t invoke dealloc. You typically invoke dealloc if you are implementing a singleton or replacing an object in an init methods. Forsingletons, use the shared instance pattern. In init methods, you don't have to call dealloc anymore, because the object will be freed when you overwrite self. You can’t use NSAutoreleasePool objects. Use the new @autoreleasepool{} construct instead. This forces a block structure on your autorelease pool, and is about six times faster than NSAutoreleasePool. @autoreleasepool even works in non-ARC code. Because @autoreleasepool is so much faster than NSAutoreleasePool, many old “performance hacks” can simply be replaced with unconditional @autoreleasepool. The migrator handles simple uses of NSAutoreleasePool, but it can't handle complex conditional cases, or cases where a variable is defined inside the body of the new @autoreleasepool and used after it. ARC requires you to assign the result of [super init] to self in init methods. The following is invalid in ARC init methods: [super init]; The simple fix is to change it to: self = [super init]; The proper fix is to do that, and check the result for nil before continuing: self = [super init]; if (self) { ... Transitioning to ARC Release Notes Common Issues While Converting a Project 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 15You can’t implement custom retain or release methods. Implementing custom retain or release methods breaks weak pointers. There are several common reasons for wanting to provide custom implementations: ● Performance. Please don’t do this any more; the implementation of retain and release for NSObject is much faster now. If you still find problems, please file bugs. ● To implement a custom weak pointer system. Use __weak instead. ● To implement singleton class. Use the shared instance pattern instead. Alternatively, use class instead of instance methods, which avoids having to allocate the object at all. “Assigned” instance variables become strong. Before ARC, instance variables were non-owning references—directly assigning an object to an instance variable did not extend the lifetime of the object. To make a property strong, you usually implemented or synthesized accessor methods that invoked appropriate memory management methods; in contrast, you may have implemented accessor methods like those shown in the following example to maintain a weak property. @interface MyClass : Superclass { id thing; // Weak reference. } // ... @end @implementation MyClass - (id)thing { return thing; } - (void)setThing:(id)newThing { thing = newThing; } // ... Transitioning to ARC Release Notes Common Issues While Converting a Project 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 16@end With ARC, instance variables are strong references by default—assigning an object to an instance variable directly does extend the lifetime of the object. The migration tool is not able to determine when an instance variable is intended to be weak. To maintain the same behavior as before, you must mark the instance variable as being weak, or use a declared property. @interface MyClass : Superclass { id __weak thing; } // ... @end @implementation MyClass - (id)thing { return thing; } - (void)setThing:(id)newThing { thing = newThing; } // ... @end Or: @interface MyClass : Superclass @property (weak) id thing; // ... @end @implementation MyClass @synthesize thing; // ... @end Transitioning to ARC Release Notes Common Issues While Converting a Project 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 17You can't use strong ids in C structures. For example, the following code won’t compile: struct X { id x; float y; }; This is because x defaults to strongly retained and the compiler can’t safely synthesize all the code required to make it work correctly. For example, if you pass a pointer to one of these structures through some code that ends up doing a free, each id would have to be released before the struct is freed. The compiler cannot reliably do this, so strong ids in structures are disallowed completely in ARC mode. There are a few possible solutions: 1. Use Objective-C objects instead of structs. This is considered to be best practice anyway. 2. If using Objective-C objects is sub-optimal, (maybe you want a dense array of these structs) then consider using a void* instead. This requires the use of the explicit casts, described below. 3. Mark the object reference as __unsafe_unretained. This approach may be useful for the semi-common patterns like this: struct x { NSString *S; int X; } StaticArray[] = { @"foo", 42, @"bar, 97, ... }; You declare the structure as: struct x { NSString * __unsafe_unretained S; int X; } This may be problematic and is unsafe if the object could be released out from under the pointer, but it is very useful for things that are known to be around forever like constant string literals. You can’t directly cast between id and void* (including Core Foundation types). This is discussed in greater detail in “Managing Toll-Free Bridging” (page 12). Transitioning to ARC Release Notes Common Issues While Converting a Project 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 18Frequently Asked Questions How do I think about ARC? Where does it put the retains/releases? Try to stop thinking about where the retain/release calls are put and think about your application algorithms instead. Think about “strong and weak” pointers in your objects, about object ownership, and about possible retain cycles. Do I still need to write dealloc methods for my objects? Maybe. Because ARC does not automate malloc/free, management of the lifetime of Core Foundation objects, file descriptors, and so on, you still free such resources by writing a dealloc method. You do not have to (indeed cannot) release instance variables, but you may need to invoke [self setDelegate:nil] on system classes and other code that isn’t compiled using ARC. dealloc methods in ARC do not require—or allow—a call to [super dealloc]; the chaining to super is handled and enforced by the runtime. Are retain cycles still possible in ARC? Yes. ARC automates retain/release, and inherits the issue of retain cycles. Fortunately, code migrated to ARC rarely starts leaking, because properties already declare whether the properties are retaining or not. How do blocks work in ARC? Blocks “just work” when you pass blocks up the stack in ARC mode, such as in a return. You don’t have to call Block Copy any more. You still need to use [^{} copy] when passing “down” the stack into arrayWithObjects: and other methods that do a retain. The one thing to be aware of isthat NSString * __block myString isretained in ARC mode, not a possibly dangling pointer. To get the previous behavior, use __block NSString * __unsafe_unretained myString or (better still) use __block NSString * __weak myString. Can I develop applications for OS X with ARC using Snow Leopard? No. The Snow Leopard version of Xcode 4.2 doesn’t support ARC at all on OS X, because it doesn’t include the 10.7 SDK. Xcode 4.2 for Snow Leopard does support ARC for iOS though, and Xcode 4.2 for Lion supports both OS X and iOS. This means you need a Lion system to build an ARC application that runs on Snow Leopard. Can I create a C array of retained pointers under ARC? Transitioning to ARC Release Notes Frequently Asked Questions 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 19Yes, you can, as illustrated by this example: // Note calloc() to get zero-filled memory. __strong SomeClass **dynamicArray = (__strong SomeClass **)calloc(sizeof(SomeClass *), entries); for (int i = 0; i < entries; i++) { dynamicArray[i] = [[SomeClass alloc] init]; } // When you're done, set each entry to nil to tell ARC to release the object. for (int i = 0; i < entries; i++) { dynamicArray[i] = nil; } free(dynamicArray); There are a number of aspects to note: ● You will need to write __strong SomeClass ** in some cases, because the default is __autoreleasing SomeClass **. ● The allocated memory must be zero-filled. ● You must set each element to nil before freeing the array (memset or bzero will not work). ● You should avoid memcpy or realloc. Is ARC slow? It depends on what you’re measuring, but generally “no.” The compiler efficiently eliminates many extraneous retain/release calls and much effort has been invested in speeding up the Objective-C runtime in general. In particular, the common “return a retain/autoreleased object” pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code. One issue to be aware of is that the optimizer is not run in common debug configurations, so expect to see a lot more retain/release traffic at -O0 than at -Os. Does ARC work in ObjC++ mode? Yes. You can even put strong/weak ids in classes and containers. The ARC compiler synthesizes retain/release logic in copy constructors and destructors etc to make this work. Which classes don’t support weak references? Transitioning to ARC Release Notes Frequently Asked Questions 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 20You cannot currently create weak references to instances of the following classes: NSATSTypesetter, NSColorSpace, NSFont, NSMenuView, NSParagraphStyle, NSSimpleHorizontalTypesetter, and NSTextView. Note: In addition, in OS X v10.7, you cannot create weak referencesto instances of NSFontManager, NSFontPanel, NSImage, NSTableCellView, NSViewController, NSWindow, and NSWindowController. In addition, in OS X v10.7 no classes in the AV Foundation framework support weak references. For declared properties, you should use assign instead of weak; for variables you should use __unsafe_unretained instead of __weak. In addition, you cannot create weak references from instances of NSHashTable, NSMapTable, or NSPointerArray under ARC. What do I have to do when subclassing NSCell or another class that uses NSCopyObject? Nothing special. ARC takes care of cases where you had to previously add extra retains explicitly. With ARC, all copy methods should just copy over the instance variables. Can I opt out of ARC for specific files? Yes. Transitioning to ARC Release Notes Frequently Asked Questions 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 21When you migrate a project to use ARC, the -fobjc-arc compiler flag is set as the default for all Objective-C source files. You can disable ARC for a specific class using the -fno-objc-arc compiler flag for that class. In Xcode, in the target Build Phasestab, open the Compile Sources group to reveal the source file list. Double-click the file for which you want to set the flag, enter -fno-objc-arc in the pop-up panel, then click Done. Is GC (Garbage Collection) deprecated on the Mac? Garbage collection is deprecated in OS X Mountain Lion v10.8, and will be removed in a future version of OS X. Automatic Reference Counting is the recommended replacement technology. To aid in migrating existing applications, the ARC migration tool in Xcode 4.3 and later supports migration of garbage collected OS X applications to ARC. Note: For apps targeting the Mac App Store, Apple strongly recommends you replace garbage collection with ARC as soon as feasible, because Mac App Store guidelines (see App Store Review Guidelines for Mac Apps) prohibit the use of deprecated technologies. Transitioning to ARC Release Notes Frequently Asked Questions 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 22This table describes the changes to Transitioning to ARC Release Notes. Date Notes 2012-07-17 Updated for OS X v10.8. 2012-03-14 Noted that under ARC properties are strong by default. 2012-02-16 Corrected out-of-date advice regarding C++ integration. 2012-01-09 Added note to search for weak references. First version of a document that describes how to transition code from manual retain/release to use ARC. 2011-10-12 2012-07-17 | © 2012 Apple Inc. All Rights Reserved. 23 Document Revision HistoryApple Inc. © 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrievalsystem, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apple’s copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Cocoa, Leopard, Mac, Objective-C, OS X, Snow Leopard, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. App Store and Mac App Store are service marks of Apple Inc. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.ASARESULT, THISDOCUMENT IS PROVIDED “AS IS,” AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state. App Sandbox Design GuideContents About App Sandbox 5 At a Glance 5 How to Use This Document 6 Prerequisites 6 See Also 6 App Sandbox Quick Start 8 Create the Xcode Project 8 Enable App Sandbox 10 Create a Code Signing Certificate for Testing 10 Specify the Code Signing Identity 11 Confirm That the App Is Sandboxed 12 Resolve an App Sandbox Violation 13 App Sandbox in Depth 15 The Need for a Last Line of Defense 15 Container Directories and File System Access 16 The App Sandbox Container Directory 16 The Application Group Container Directory 17 Powerbox and File System Access Outside of Your Container 17 Open and Save Dialog Behavior with App Sandbox 19 Entitlements and System Resource Access 20 Security-Scoped Bookmarks and Persistent Resource Access 21 Two Distinct Types of Security-Scoped Bookmark 21 Using Security-Scoped Bookmarks 22 App Sandbox and Code Signing 24 External Tools, XPC Services, and Privilege Separation 26 Designing for App Sandbox 27 Six Steps for Adopting App Sandbox 27 Determine Whether Your App Is Suitable for Sandboxing 27 Design a Development and Distribution Strategy 29 Resolve API Incompatibilities 29 Opening, Saving, and Tracking Documents 29 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 2Retaining Access to File System Resources 29 Creating a Login Item for Your App 30 Accessing User Data 30 Accessing Preferences of Other Apps 30 Apply the App Sandbox Entitlements You Need 31 Add Privilege Separation Using XPC 32 Implement a Migration Strategy 32 Migrating an App to a Sandbox 33 Creating a Container Migration Manifest 34 Undoing a Migration for Testing 36 An Example Container Migration Manifest 36 Use Variables to Specify Support-File Directories 37 Document Revision History 39 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 3 ContentsTables and Listings App Sandbox in Depth 15 Table 2-1 The App Sandbox mindset 15 Table 2-2 Open and Save class inheritance with App Sandbox 20 Migrating an App to a Sandbox 33 Table 4-1 How system directory variables resolve depending on context 37 Table 4-2 Variables for support-file directories 38 Listing 4-1 An example container migration manifest 36 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 4App Sandbox provides a last line of defense against stolen, corrupted, or deleted user data if malicious code exploits your app. App Sandbox also minimizes the damage from coding errors in your app or in frameworks you link against. Your app All system resources All user data Unrestricted access Other system resources Other user data Your app Unrestricted access No access Without App Sandbox With App Sandbox Your sandbox App Sandbox is an access control technology provided in OS X, enforced at the kernel level. Its strategy is twofold: 1. App Sandbox enables you to describe how your app interacts with the system. The system then grants your app the access it needs to get its job done, and no more. 2. App Sandbox allows the user to transparently grant your app additional access by way of Open and Save dialogs, drag and drop, and other familiar user interactions. At a Glance Based on simple security principles, App Sandbox provides strong defense against damage from malicious code. The elements of App Sandbox are container directories, entitlements, user-determined permissions, privilege separation, and kernel enforcement. It’s up to you to understand these elements and then to use your understanding to create a plan for adopting App Sandbox. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 5 About App SandboxRelevant chapters: “App Sandbox Quick Start” (page 8), “App Sandbox in Depth” (page 15) After you understand the basics, look at your app in light of this security technology. First, determine if your app issuitable forsandboxing. Most apps are. Design your developmentstrategy, resolve API incompatibilities, determine which entitlements you need, and consider applying privilege separation to maximize the defensive value of App Sandbox. Relevant chapter: “Designing for App Sandbox” (page 27) Some file system locations that your app uses are different when you adopt App Sandbox. In particular, you gain a container directory to be used for app support files, databases, caches, and other files apart from user documents. OS X and Xcode support migration of files from their legacy locations to your container. Relevant chapter: “Migrating an App to a Sandbox” (page 33) How to Use This Document To get up and running with App Sandbox, perform the tutorial in “App Sandbox Quick Start” (page 8). Before sandboxing an app you intend to distribute, be sure you understand “App Sandbox in Depth” (page 15). When you’re ready to startsandboxing a new app, or to convert an existing app to adopt App Sandbox, read “Designing for App Sandbox” (page 27). If you’re providing a new, sandboxed version of your app to users already running a version that is not sandboxed, read “Migrating an App to a Sandbox” (page 33). Prerequisites Before you read this document, make sure you understand the place of App Sandbox and code signing in the overall OS X development process by reading Mac App Programming Guide . See Also To complement the damage containment provided by App Sandbox, you must provide a first line of defense by adopting secure coding practices throughout your app. To learn how, read Security Overview and Secure Coding Guide . About App Sandbox How to Use This Document 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 6An important step in adopting App Sandbox is requesting entitlements for your app. For details on all the available entitlements, see Entitlement Key Reference . You can enhance the benefits of App Sandbox in a full-featured app by implementing privilege separation. You do this using XPC, an OS X implementation of interprocess communication. To learn the details of using XPC, read Daemons and Services Programming Guide . About App Sandbox See Also 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 7In this Quick Start you get an OS X app up and running in a sandbox. You verify that the app isindeed sandboxed and then learn how to troubleshoot and resolve a typical App Sandbox error. The apps you use are Xcode, Keychain Access, Activity Monitor, and Console. Create the Xcode Project The app you create in this Quick Start uses a WebKit web view and consequently uses a network connection. Under App Sandbox, network connections don’t work unless you specifically allow them—making this a good example app for learning about sandboxing. To create the Xcode project for this Quick Start 1. In Xcode 4, create a new Xcode project for an OS X Cocoa application. ● Name the project AppSandboxQuickStart. ● Set a company identifier, such as com.yourcompany, if none is already set. ● Ensure that Use Automatic Reference Counting is selected and that the other checkboxes are unselected. 2. In the project navigator, click the MainMenu nib file. The Interface Builder canvas appears. 3. In the Xcode dock, click the Window object. The app’s window is now visible on the canvas. 4. In the object library (in the utilities area), locate the WebView object. 5. Drag a web view onto the window on the canvas. 6. (Optional) To improve the display of the web view in the running app, perform the following steps: ● Drag the sizing controls on the web view so that it completely fills the window’s main view. ● Using the size inspector for the web view, ensure that all of the inner and outer autosizing contraints are active. 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 8 App Sandbox Quick Start7. Create and connect an outlet for the web view in the AppDelegate class. In Xcode, use the following specification: Outlet connection source The WebView object of the MainMenu nib file. Outlet variable location The interface block of the AppDelegate.h header file. Outlet name webView Storage weak At this point, if you were to build the app, Xcode would report an error because the project doesn’t yet use WebKit but does have a web view in the nib file. You take care of this in the next step. 8. Add the WebKit framework to the app. ● Import the WebKit framework by adding the following statement above the interface block in the AppDelegate.h header file: #import ● Link the WebKit framework to the Quick Start project as a required framework. 9. Add the following awakeFromNib method to the AppDelegate.m implementation file: - (void) awakeFromNib { [self.webView.mainFrame loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: @"http://www.apple.com"]]]; } On application launch, this method requeststhe specified URL from the computer’s network connection and then sends the result to the web view for display. Now, build and run the app—which is not yet sandboxed and so has free access to system resources including its network sockets. Confirm that the app’s window displays the page you specified in the awakeFromNib method. When done, quit the app. App Sandbox Quick Start Create the Xcode Project 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 9Enable App Sandbox You enable App Sandbox by selecting a checkbox in the Xcode target editor. In Xcode, click the project file in the project navigator and click the AppSandboxQuickStart target, if they’re not already selected. View the Summary tab of the target editor. To enable App Sandbox for the project 1. In the Summary tab of the target editor, click Enable Entitlements. An entitlement is a key-value pair, defined in a property list file, that confers a specific capability or security permission to a target. When you click Enable Entitlements, Xcode automatically checks the Code Sign Application checkbox and the Enable App Sandboxing checkbox. Together, these are the essential projectsettingsfor enabling App Sandbox. When you click Enable Entitlements, Xcode also creates a .entitlements property list file, visible in the project navigator. As you use the graphical entitlementsinterface in the target editor, Xcode updates the property list file. 2. Clear the contents of the iCloud entitlement fields. This Quick Start doesn’t use iCloud. Because Xcode automatically adds iCloud entitlement values when you enable entitlements, delete them as follows: ● In the Summary tab of the target editor,select and then delete the content of the iCloud Key-Value Store field. ● Click the top row in the iCloud Containers field and click the minus button. At this point in the Quick Start, you have enabled App Sandbox but have not yet provided a code signing identity for the Xcode project. Consequently, if you attempt to build the project now, the build fails. You take care of this in the next two sections. Create a Code Signing Certificate for Testing To build a sandboxed app in Xcode, you must have a code signing certificate and its associated private key in your keychain, and then use that certificate’s code signing identity in the project. The entitlements you specify, including the entitlement that enables App Sandbox, become part of the app’s code signature when you build the project. App Sandbox Quick Start Enable App Sandbox 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 10In this section, you create a code signing certificate. This simplified process lets you stay focused on the steps for enabling a sandbox. Important: A code signing certificate that you create as described in this Quick Start is not appropriate to use with an app you intend to distribute. Before you work on sandboxing an app you plan to distribute, read “App Sandbox and Code Signing” (page 24). To create a code signing certificate for testing App Sandbox 1. In Keychain Access (available in Applications/Utilities), choose KeyChain Access > Certificate Assistant > Create a Certificate. Certificate Assistant opens. Note: Before you invoke the “Create a Certificate” menu command, ensure that no key is selected in the Keychain Access main window. If a key is selected, the menu command is not available. 2. In Certificate Assistant, name the certificate something like My Test Certificate. 3. Complete the configuration of the certificate as follows: Identity type Self Signed Root Certificate type Code Signing Let me override defaults unchecked 4. Click Create. 5. In the alert that appears, click Continue. 6. In the Conclusion window, click Done. Your new code signing certificate, and its associated public and private keys, are now available in Keychain Access. Specify the Code Signing Identity Now, configure the Xcode project to use the code signing identity from the certificate you created in the previous task. App Sandbox Quick Start Specify the Code Signing Identity 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 11To specify the code signing identity for the project 1. View the Build Settings tab in the project editor. Take care that you are using the project editor, not the target editor. 2. In the Code Signing section, locate the Code Signing Identity row. 3. Click the value area of the Code Signing Identity row. 4. In the popup menu that opens, choose Other. 5. In the text entry window that opens, enter the exact name of the newly created code signing certificate, then press . If you’re using the suggested name from thisQuick Start, the name you enter is My Test Certificate. Now, build the app. The codesign tool may display an alert asking for permission to use the new certificate. If you do see this alert, click Always Allow. Confirm That the App Is Sandboxed Build and run the Quick Start app. The window opens, but if the app issuccessfully sandboxed, no web content appears. This is because you have not yet conferred permission to access a network connection. Apart from blocked behavior, there are two specific signs that an OS X app is successfully sandboxed. To confirm that the Quick Start app is successfully sandboxed 1. In Finder, look at the contents of the ~/Library/Containers/ folder. If the Quick Start app is sandboxed, there is now a container folder named after your app. The name includes the company identifier for the project, so the complete folder name would be, for example, com.yourcompany.AppSandboxQuickStart. The system creates an app’s container folder, for a given user, the first time the user runs the app. 2. In Activity Monitor, check that the system recognizes the app as sandboxed. ● Launch Activity Monitor (available in /Applications/Utilities). ● In Activity Monitor, choose View > Columns. Ensure that the Sandbox menu item is checked. ● In the Sandbox column, confirm that the value for the Quick Start app is Yes. App Sandbox Quick Start Confirm That the App Is Sandboxed 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 12To make it easier to locate the app in Activity monitor, enter the name of the Quick Start app in the Filter field. Tip: If the app crashes when you attempt to run it,specifically by receiving an EXC_BAD_INSTRUCTION signal, the most likely reason is that you previously ran a sandboxed app with the same bundle identifier but a different code signature. This crashing upon launch is an App Sandbox security feature that prevents one app from masquerading as another and thereby gaining access to the other app’s container. You learn how to design and build your apps, in light of this security feature, in “App Sandbox and Code Signing” (page 24). Resolve an App Sandbox Violation An App Sandbox violation occurs if your app tries to do something that App Sandbox does not allow. For example, you have already seen in this Quick Start that the sandboxed app is unable to retrieve content from the web. Fine-grained restriction over access to system resources is the heart of how App Sandbox provides protection should an app become compromised by malicious code. The most common source of App Sandbox violations is a mismatch between the entitlement settings you specified in Xcode and the needs of your app. In this section you observe and then correct an App Sandbox violation. To diagnose an App Sandbox violation 1. Build and run the Quick Start app. The app starts normally, but fails to display the webpage specified in its awakeFromNib method (as you’ve previously observed in “Confirm That the App Is Sandboxed” (page 12)). Because displaying the webpage worked correctly before you sandboxed the app, it is appropriate in this case to suspect an App Sandbox violation. 2. Open Console (available in /Applications/Utilities/) and ensure that All Messages is selected in the sidebar. In the filter field of the Console window, enter sandboxd to display only App Sandbox violations. sandboxd is the name of the App Sandbox daemon that reports on sandbox violations. The relevant messages, as displayed in Console, look similar to the following: 3:56:16 pm sandboxd: ([4928]) AppSandboxQuickS(4928) deny network-outbound 111.30.222.15:80 3:56:16 pm sandboxd: ([4928]) AppSandboxQuickS(4928) deny system-socket App Sandbox Quick Start Resolve an App Sandbox Violation 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 13The problem that generates these console messages is that the Quick Start app does not yet have the entitlement for outbound network access. Tip: To see the full backtraces for either violation, click the paperclip icon near the right edge of the corresponding Console message. The steps in the previous task illustrate the general pattern to use for identifying App Sandbox violations: 1. Confirm that the violation occurs only with App Sandbox enabled in your project. 2. Provoke the violation (such as by attempting to use a network connection, if your app is designed to do that). 3. Look in Console for sandboxd messages. There is also a simple, general pattern to use for resolving such violations. To resolve the App Sandbox violation by adding the appropriate entitlement 1. Quit the Quick Start app. 2. In the Summary tab of the target editor, look for the entitlement that corresponds to the reported sandboxd violation. In this case, the primary error is deny network-outbound. The corresponding entitlement is Allow Outgoing Network Connections. 3. In the Summary tab of the target editor, select the Allow Outgoing Network Connections checkbox. Doing so applies a TRUE value, for the needed entitlement, to the Xcode project. 4. Build and run the app. The intended webpage now displays in the app. In addition, there are no new App Sandbox violation messages in Console. App Sandbox Quick Start Resolve an App Sandbox Violation 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 14The access control mechanisms used by App Sandbox to protect user data are small in number and easy to understand. But the specific steps for you to take, as you adopt App Sandbox, are unique to your app. To determine what those steps are, you must understand the key concepts for this technology. The Need for a Last Line of Defense You secure your app against attack from malware by following the practices recommended in Secure Coding Guide . But despite your best efforts to build an invulnerable barrier—by avoiding buffer overflows and other memory corruptions, preventing exposure of user data, and eliminating other vulnerabilities—your app can be exploited by malicious code. An attacker needs only to find a single hole in your defenses, or in any of the frameworks and libraries that you link against, to gain control of your app’s interactions with the system. App Sandbox is designed to confront this scenario head on by letting you describe your app’s intended interactions with the system. The system then grants your app only the access your app needs to get its job done. If malicious code gains control of a properly sandboxed app, it is left with access to only the files and resources in the app’s sandbox. To successfully adopt App Sandbox, use a different mindset than you might be accustomed to, as suggested in Table 2-1. Table 2-1 The App Sandbox mindset When developing… When adopting App Sandbox… Add features Minimize system resource use Take advantage of access throughout your app Partition functionality, then distrust each part Use the most convenient API Use the most secure API View restrictions as limitations View restrictions as safeguards 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 15 App Sandbox in DepthWhen designing for App Sandbox, you are planning for the following worst-case scenario: Despite your best efforts, malicious code breaches an unintended security hole—either in your code or in a framework you’ve linked against. Capabilities you’ve added to your app become capabilities of the hostile code. Keep this in mind as you read the rest of this document. Container Directories and File System Access When you adopt App Sandbox, the system provides a special directory for use by your app—and only by your app—called a container. Each user on a system gets an individual container for your app, within their home directory; your app has unfettered read/write access to the container for the current user. The App Sandbox Container Directory The container has the following characteristics: ● It is located at a system-defined path, within the user’s home directory, that you can obtain by calling the NSHomeDirectory function. ● Your app has unrestricted read/write access to the container and its subdirectories. ● OS X path-finding APIs (above the POSIX layer) refer to locations that are specific to your app. Most of these path-finding APIsrefer to locationsrelative to your app’s container. For example, the container includes an individual Library directory (specified by the NSLibraryDirectory search path constant) for use only by your app, with individual Application Support and Preferences subdirectories. Using your container forsupport filesrequires no code change (from the pre-sandbox version of your app) but may require one-time migration, as explained in “Migrating an App to a Sandbox” (page 33). Some path-finding APIs (above the POSIX layer) refer to app-specific locations outside of the user’s home directory. In a sandboxed app, for example, the NSTemporaryDirectory function provides a path to a directory that is outside of the user’s home directory but specific to your app and within your sandbox; you have unrestricted read/write access to it for the current user. The behavior of these path-finding APIs is suitably adjusted for App Sandbox and no code change is needed. ● OS X establishes and enforces the connection between your app and its container by way of your app’s code signature. ● The container isin a hidden location, and so users do not interact with it directly. Specifically, the container is not for user documents. It is for files that your app uses, along with databases, caches, and other app-specific data. For a shoebox-style app, in which you provide the only user interface to the user’s content, that content goes in the container and your app has full access to it. App Sandbox in Depth Container Directories and File System Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 16iOS Note: Because it is not for user documents, an OS X container differs from an iOS container—which, in iOS, is the one and only location for user documents. In addition, an iOS container contains the app itself. This is not so in OS X. iCloud Note: Apple’s iCloud technology, as described in “iCloud Storage”, uses the name “container” as well. There is no functional connection between an iCloud container and an App Sandbox container. Thanks to code signing, no other sandboxed app can gain access to your container, even if it attempts to masquerade as your app by using your bundle identifier. Future versions of your app, however—provided that you use the same code signature and bundle identifier—do reuse your app’s container. The time at which a container directory is created for an App Sandbox–enabled app is when the app is first run. Because a container is within a user’s home folder, each user on a system gets their own container for your app. A given user’s container is created when that user first runs your app. The Application Group Container Directory In addition to per-app containers, beginning in OS X v10.7.4, an application can use entitlements to request access to a shared container that is common to multiple applications produced by the same development team. This container is intended for content that is not user-facing, such as shared caches or databases. Applicationsthat are members of an application group also gain the ability to share Mach and POSIX semaphores and to use certain other IPC mechanisms in conjunction with other group members. These group containers are automatically created or added into each app’s sandbox container as determined by the existence of these keys, and are stored in ~/Library/Group Containers/, where can be whatever name you choose. Your app can obtain the path to the group containers by calling the containerURLForSecurityApplicationGroupIdentifier: method of NSURL. For more details, see “Adding an Application to an Application Group” in Entitlement Key Reference . Powerbox and File System Access Outside of Your Container Your sandboxed app can access file system locations outside of its container in the following three ways: ● At the specific direction of the user App Sandbox in Depth Container Directories and File System Access 2012-09-19 | © 2012 Apple Inc. All Rights Reserved. 17● By using entitlements for specific file-system locations (described in “Entitlements and System Resource Access” (page 20)) ● When the file system location is in certain directories that are world readable The OS X security technology that interacts with the user to expand yoursandbox is called Powerbox. Powerbox has no API. Your app uses Powerbox transparently when you use the NSOpenPanel and NSSavePanel classes. You enable Powerbox by setting an entitlement using Xcode, as described in “Enabling User-Selected File Access” in Entitlement Key Reference . When you invoke an Open or Save d