Satıcı modülü yönergeleri

Satıcı modüllerinizin sağlamlığını ve güvenilirliğini artırmak için aşağıdaki yönergeleri kullanın. Pek çok yönerge izlendiğinde, doğru modül yükleme sırasını ve sürücülerin aygıtları araştırması gereken sırayı belirlemeyi kolaylaştırmaya yardımcı olabilir.

Bir modül bir kitaplık veya bir sürücü olabilir.

  • Kütüphane modülleri, diğer modüllerin kullanması için API'ler sağlayan kütüphanelerdir. Bu tür modüller genellikle donanıma özgü değildir. Kitaplık modüllerine örnek olarak bir AES şifreleme modülü, bir modül olarak derlenen remoteproc çerçevesi ve bir logbuffer modülü verilebilir. module_init() içindeki modül kodu, veri yapılarını ayarlamak için çalışır, ancak harici bir modül tarafından tetiklenmediği sürece başka hiçbir kod çalışmaz.

  • Sürücü modülleri, belirli bir aygıt türünü araştıran veya ona bağlanan sürücülerdir. Bu modüller donanıma özeldir. Sürücü modüllerine örnek olarak UART, PCIe ve video kodlayıcı donanımı verilebilir. Sürücü modülleri yalnızca ilgili aygıtları sistemde mevcut olduğunda etkinleşir.

    • Aygıt mevcut değilse çalışan tek modül kodu, sürücüyü sürücü çekirdek çerçevesine kaydeden module_init() kodudur.

    • Aygıt mevcutsa ve sürücü bu aygıtı başarılı bir şekilde araştırırsa veya bu aygıta bağlanırsa, diğer modül kodu çalıştırılabilir.

Modül giriş/çıkışını doğru kullanın

Sürücü modülleri bir sürücüyü module_init() e kaydetmeli ve bir sürücünün module_exit() deki kaydını silmelidir. Bu kısıtlamaları uygulamanın basit bir yolu, module_init() , *_initcall() veya module_exit() makrolarının doğrudan kullanımını önleyen sarmalayıcı makroları kullanmaktır.

  • Kaldırılabilen modüller için module_ subsystem _driver() kullanın. Örnekler: module_platform_driver() , module_i2c_driver() ve module_pci_driver() .

  • Kaldırılamayan modüller için, builtin_ subsystem _driver() kullanın. Örnekler: builtin_platform_driver() , builtin_i2c_driver() builtin_pci_driver() .

Bazı sürücü modülleri, birden fazla sürücüyü kaydettikleri için module_init() ve module_exit() kullanır. Birden fazla sürücüyü kaydetmek amacıyla module_init() ve module_exit() kullanan bir sürücü modülü için, sürücüleri tek bir sürücüde birleştirmeyi deneyin. Örneğin, ayrı sürücüleri kaydetmek yerine compatible dizeyi veya aygıtın yardımcı verilerini kullanarak farklılaştırma yapabilirsiniz. Alternatif olarak sürücü modülünü iki modüle bölebilirsiniz.

Başlatma ve çıkış işlevi istisnaları

Kitaplık modülleri sürücüleri kaydetmez ve veri yapılarını, iş kuyruklarını veya çekirdek iş parçacıklarını ayarlamak için bu işlevlere ihtiyaç duyabilecekleri için module_init() ve module_exit() üzerindeki kısıtlamalardan muaftır.

MODULE_DEVICE_TABLE makrosunu kullanın

Sürücü modülleri, modülü yüklemeden önce kullanıcı alanının sürücü modülü tarafından desteklenen cihazları belirlemesine olanak tanıyan MODULE_DEVICE_TABLE makrosunu içermelidir. Android, bu verileri, sistemde bulunmayan cihazlar için modül yüklemeyi önlemek gibi modül yüklemeyi optimize etmek için kullanabilir. Makronun kullanımına ilişkin örnekler için yukarı akış koduna bakın.

İleriye dönük olarak bildirilen veri türleri nedeniyle CRC uyumsuzluklarından kaçının

İleriye dönük olarak bildirilen veri türlerinin görünürlüğünü sağlamak için başlık dosyalarını eklemeyin. Bir başlık dosyasında ( header-Ah ) tanımlanan bazı yapılar, birleşimler ve diğer veri türleri, genellikle bu veri türlerine yönelik işaretçileri kullanan farklı bir başlık dosyasında ( header-Bh ) ileriye doğru bildirilebilir. Bu kod modeli, çekirdeğin kasıtlı olarak veri yapısını header-Bh kullanıcılarına özel tutmaya çalıştığı anlamına gelir.

header-Bh kullanıcıları, bu ileri bildirimli veri yapılarının iç kısımlarına doğrudan erişmek için header-Ah eklememelidir. Bunu yapmak, farklı bir çekirdek (GKI çekirdeği gibi) modülü yüklemeye çalıştığında CONFIG_MODVERSIONS CRC uyumsuzluğu sorunlarına (ABI uyumluluk sorunlarına neden olur) neden olur.

Örneğin, struct fwnode_handle include/linux/fwnode.h dosyasında tanımlanır, ancak struct fwnode_handle; include/linux/device.h dosyasında çünkü çekirdek struct fwnode_handle ayrıntılarını include/linux/device.h kullanıcılarından gizli tutmaya çalışıyor. Bu senaryoda, struct fwnode_handle üyelerine erişim sağlamak için bir modüle #include <linux/fwnode.h> eklemeyin. Bu tür başlık dosyalarını eklemeniz gereken herhangi bir tasarım, kötü bir tasarım desenine işaret eder.

Çekirdek çekirdek yapılarına doğrudan erişmeyin

Çekirdek çekirdek veri yapılarına doğrudan erişmek veya bunları değiştirmek, bellek sızıntıları, çökmeler ve gelecekteki çekirdek sürümleriyle uyumluluğun bozulması gibi istenmeyen davranışlara yol açabilir. Bir veri yapısı, aşağıdaki koşullardan herhangi birini karşıladığında çekirdek çekirdek veri yapısıdır:

  • Veri yapısı KERNEL-DIR /include/ altında tanımlanır. Örneğin, struct device ve struct dev_links_info . include/linux/soc tanımlanan veri yapıları muaftır.

  • Veri yapısı modül tarafından tahsis edilir veya başlatılır, ancak çekirdek tarafından dışa aktarılan bir fonksiyona girdi olarak dolaylı olarak (yapıdaki bir işaretçi aracılığıyla) veya doğrudan aktarılarak çekirdeğe görünür hale getirilir. Örneğin, bir cpufreq sürücü modülü struct cpufreq_driver başlatır ve ardından onu cpufreq_register_driver() öğesine girdi olarak iletir. Bu noktadan sonra cpufreq sürücü modülü struct cpufreq_driver doğrudan değiştirmemelidir çünkü cpufreq_register_driver() işlevinin çağrılması struct cpufreq_driver çekirdeğe görünür olmasını sağlar.

  • Veri yapısı modülünüz tarafından başlatılmadı. Örneğin, regulator_register() tarafından döndürülen struct regulator_dev .

Çekirdek çekirdek veri yapılarına yalnızca çekirdek tarafından dışa aktarılan işlevler veya satıcı kancalarına açıkça girdi olarak iletilen parametreler aracılığıyla erişin. Çekirdek çekirdek veri yapısının bazı kısımlarını değiştirmek için bir API'niz veya satıcı kancanız yoksa, bu muhtemelen kasıtlıdır ve veri yapısını modüllerden değiştirmemelisiniz. Örneğin, struct device veya struct device.links içindeki hiçbir alanı değiştirmeyin.

  • device.devres_head değiştirmek için devm_clk_get() , devm_regulator_get() veya devm_kzalloc() gibi bir devm_*() işlevini kullanın.

  • struct device.links içindeki alanları değiştirmek için, device_link_add() veya device_link_del() gibi bir Device Link API'sini kullanın.

Uyumlu özelliğe sahip cihaz ağacı düğümlerini ayrıştırmayın

Bir aygıt ağacı (DT) düğümünün compatible bir özelliği varsa, bunun için otomatik olarak veya ana DT düğümünde of_platform_populate() çağrıldığında (genellikle ana aygıtın aygıt sürücüsü tarafından) bir struct device tahsis edilir. Varsayılan beklenti (zamanlayıcı için erken başlatılan bazı cihazlar hariç), compatible bir özelliğe sahip bir DT düğümünün bir struct device ve eşleşen bir cihaz sürücüsüne sahip olmasıdır. Diğer tüm istisnalar zaten yukarı akış kodu tarafından işleniyor.

Ek olarak, fw_devlink (daha önce of_devlink olarak adlandırılıyordu), compatible özelliğe sahip DT düğümlerini, bir sürücü tarafından incelenen tahsis edilmiş bir struct device sahip aygıtlar olarak değerlendirir. Bir DT düğümünün compatible bir özelliği varsa ancak tahsis edilen struct device incelenmiyorsa, fw_devlink tüketici aygıtlarının incelemesini engelleyebilir veya tedarikçi aygıtları için sync_state() çağrılarının çağrılmasını engelleyebilir.

Sürücünüz, compatible bir özelliğe sahip bir DT düğümünü doğrudan bulmak ve ardından bu DT düğümünü ayrıştırmak için of_find_*() işlevini ( of_find_node_by_name() veya of_find_compatible_node() gibi) kullanıyorsa, inceleyebilecek bir aygıt sürücüsü yazarak modülü düzeltin. veya compatible özelliği kaldırın (yalnızca yukarı akışa aktarılmamışsa mümkündür). Alternatifleri tartışmak için kernel-team@android.com adresinden Android Çekirdek Ekibine ulaşın ve kullanım durumlarınızı gerekçelendirmeye hazır olun.

Tedarikçileri aramak için DT kollarını kullanın

Mümkün olduğunda DT'de bir sap (bir DT düğümüne referans/işaretçi) kullanan bir tedarikçiye başvurun. Tedarikçilere başvurmak için standart DT bağlamalarını ve phandle'ları kullanmak, fw_devlink (önceden of_devlink ) çalışma zamanında DT'yi ayrıştırarak cihazlar arası bağımlılıkları otomatik olarak belirlemesine olanak tanır. Çekirdek daha sonra cihazları otomatik olarak doğru sırayla inceleyerek modül yükleme sıralamasına veya MODULE_SOFTDEP() ihtiyacını ortadan kaldırır.

Eski senaryo (ARM çekirdeğinde DT desteği yok)

Daha önce, ARM çekirdeklerine DT desteği eklenmeden önce, dokunmatik cihazlar gibi tüketiciler, global olarak benzersiz dizeler kullanan düzenleyiciler gibi tedarikçilere bakıyordu. Örneğin, ACME PMIC sürücüsü birden fazla düzenleyiciyi ( acme-pmic-ldo1 ila acme-pmic-ldo10 gibi) kaydedebilir veya tanıtabilir ve dokunmatik sürücü regulator_get(dev, "acme-pmic-ldo10") kullanarak bir düzenleyiciyi arayabilir . Bununla birlikte, farklı bir kartta LDO8, dokunmatik cihazı besleyerek, aynı dokunmatik sürücünün, dokunmatik cihazın kullanıldığı her kart için regülatör için doğru arama dizesini belirlemesi gereken hantal bir sistem oluşturabilir.

Mevcut senaryo (ARM çekirdeğinde DT desteği)

ARM çekirdeklerine DT desteği eklendikten sonra tüketiciler, bir phandle kullanarak tedarikçinin cihaz ağacı düğümüne başvurarak DT'deki tedarikçileri tanımlayabilir. Tüketiciler ayrıca kaynağı kimin sağladığından ziyade ne için kullanıldığına göre adlandırabilirler. Örneğin, önceki örnekteki dokunmatik sürücü, dokunmatik cihazın çekirdeğini ve sensörünü çalıştıran tedarikçileri almak için regulator_get(dev, "core") ve regulator_get(dev, "sensor") kullanabilir. Böyle bir cihaz için ilişkili CE aşağıdaki kod örneğine benzer:

touch-device {
    compatible = "fizz,touch";
    ...
    core-supply = <&acme_pmic_ldo4>;
    sensor-supply = <&acme_pmic_ldo10>;
};

acme-pmic {
    compatible = "acme,super-pmic";
    ...
    acme_pmic_ldo4: ldo4 {
        ...
    };
    ...
    acme_pmic_ldo10: ldo10 {
        ...
    };
};

Her iki dünyanın da en kötüsü senaryosu

Eski çekirdeklerden taşınan bazı sürücüler, DT'de eski planın en kötü kısmını alan ve işleri kolaylaştıracak yeni şemaya zorlayan eski davranışı içerir. Bu tür sürücülerde, tüketici sürücüsü, cihaza özgü bir CE özelliğini kullanarak arama için kullanılacak dizeyi okur, tedarikçi, tedarikçi kaynağını kaydetmek için kullanılacak adı tanımlamak için tedarikçiye özgü başka bir özelliği kullanır, ardından tüketici ve tedarikçi kullanmaya devam eder. tedarikçiyi aramak için dizeleri kullanmanın aynı eski şeması. Her iki dünyanın da en kötüsü olan bu senaryoda:

  • Dokunmatik sürücü aşağıdaki koda benzer bir kod kullanır:

    str = of_property_read(np, "fizz,core-regulator");
    core_reg = regulator_get(dev, str);
    str = of_property_read(np, "fizz,sensor-regulator");
    sensor_reg = regulator_get(dev, str);
    
  • DT aşağıdakine benzer bir kod kullanır:

    touch-device {
      compatible = "fizz,touch";
      ...
      fizz,core-regulator = "acme-pmic-ldo4";
      fizz,sensor-regulator = "acme-pmic-ldo4";
    };
    acme-pmic {
      compatible = "acme,super-pmic";
      ...
      ldo4 {
        regulator-name = "acme-pmic-ldo4"
        ...
      };
      ...
      acme_pmic_ldo10: ldo10 {
        ...
        regulator-name = "acme-pmic-ldo10"
      };
    };
    

Çerçeve API hatalarını değiştirmeyin

regulator , clocks , irq , gpio , phys ve extcon gibi çerçeve API'leri, bir aygıtın araştırma yapmaya çalıştığını ancak şu anda yapamadığını ve çekirdeğin araştırmayı yeniden denemesi gerektiğini belirtmek için bir hata dönüş değeri olarak -EPROBE_DEFER değerini döndürür. Daha sonra. Bu gibi durumlarda cihazınızın .probe() işlevinin beklendiği gibi başarısız olmasını sağlamak için hata değerini değiştirmeyin veya yeniden eşlemeyin. Hata değerinin değiştirilmesi veya yeniden eşlenmesi, -EPROBE_DEFER değerinin düşürülmesine ve cihazınızın hiçbir zaman incelenmemesine neden olabilir.

devm_*() API değişkenlerini kullanın

Cihaz, devm_*() API'sini kullanarak bir kaynak aldığında, cihazın araştırma yapması veya başarılı bir şekilde araştırma yapması ve daha sonra bağlantısının kesilmesi durumunda kaynak, çekirdek tarafından otomatik olarak serbest bırakılır. Bu işlevsellik, probe() işlevindeki hata işleme kodunu daha temiz hale getirir çünkü devm_*() tarafından elde edilen kaynakları serbest bırakmak için goto atlamalarına gerek duymaz ve sürücü bağlantısını kaldırma işlemlerini basitleştirir.

Aygıt sürücüsü bağlantısını kaldırma işlemini gerçekleştirin

Aygıt sürücülerinin bağlantısını kaldırma konusunda dikkatli olun ve ayırmayı tanımsız bırakmayın çünkü tanımsız, izin verilmediği anlamına gelmez. Aygıt sürücüsü bağlantısını kesmeyi tam olarak uygulamanız veya aygıt sürücüsü bağlantısını kesmeyi açıkça devre dışı bırakmanız gerekir.

Aygıt sürücüsü bağlantısını kaldırmanın uygulanması

Aygıt sürücüsü bağlantısını kesmeyi tam olarak uygulamayı seçtiğinizde, bellek veya kaynak sızıntılarını ve güvenlik sorunlarını önlemek için aygıt sürücülerinin bağlantısını temiz bir şekilde kaldırın. Bir sürücünün probe() işlevini çağırarak bir aygıtı sürücüye bağlayabilir ve sürücünün remove() işlevini çağırarak bir aygıtın bağlantısını kaldırabilirsiniz. remove() işlevi yoksa çekirdek yine de aygıtın bağlantısını kaldırabilir; sürücü çekirdeği, sürücünün aygıtla bağlantısını kestiğinde herhangi bir temizleme işlemine gerek olmadığını varsayar. Aşağıdakilerin her ikisi de doğru olduğunda, bir aygıtla ilişkisi olmayan bir sürücünün açık bir temizleme çalışması yapmasına gerek yoktur:

  • Bir sürücünün probe() işlevi tarafından elde edilen tüm kaynaklar devm_*() API'leri aracılığıyla sağlanır.

  • Donanım aygıtının bir kapatma veya susturma işlemine ihtiyacı yoktur.

Bu durumda sürücü çekirdeği, devm_*() API'leri aracılığıyla edinilen tüm kaynakların serbest bırakılmasını yönetir. Önceki ifadelerden herhangi biri doğru değilse, sürücünün bir aygıtla bağlantısını kestiğinde temizleme işlemi yapması (kaynakları serbest bırakması ve donanımı kapatması veya sessize alması) gerekir. Bir aygıtın sürücü modülünün bağlantısını temiz bir şekilde kaldırabildiğinden emin olmak için aşağıdaki seçeneklerden birini kullanın:

  • Donanımın bir kapatma veya susturma sırasına ihtiyacı yoksa devm_*() API'lerini kullanarak kaynakları elde etmek için cihaz modülünü değiştirin.

  • remove() sürücü işlemini probe() işleviyle aynı yapıda uygulayın, ardından remove() işlevini kullanarak temizleme adımlarını gerçekleştirin.

Aygıt sürücüsü bağlantısını kaldırmanın açıkça devre dışı bırakılması (önerilmez)

Aygıt sürücüsü bağlantısını kaldırmayı açık bir şekilde devre dışı bırakmayı seçtiğinizde, bağlantıyı kaldırmaya ve modül boşaltma işlemine izin vermemeniz gerekir.

  • Bağlantıyı kaldırmaya izin vermemek için sürücünün suppress_bind_attrs struct device_driver dosyasındapress_bind_attrs bayrağını true olarak ayarlayın; bu ayar, bind ve unbind dosyalarının sürücünün sysfs dizininde gösterilmesini engeller. Bağlantıyı unbind dosyası, kullanıcı alanının bir sürücünün aygıtıyla bağlantısının kaldırılmasını tetiklemesine olanak tanıyan dosyadır.

  • Modül boşaltma işlemine izin vermemek için modülün lsmod [permanent] olduğundan emin olun. module_exit() veya module_XXX_driver() kullanılmadığında modül [permanent] olarak işaretlenir.

Firmware'i prob fonksiyonu içinden yüklemeyin

Sürücü, flash veya kalıcı depolama tabanlı dosya sistemi takılmadan önce sürücü yazılımına erişim sağlayamayabileceğinden, sürücü .probe() işlevi içinden ürün yazılımını yüklememelidir. Bu gibi durumlarda, request_firmware*() API'si uzun süre bloke edebilir ve ardından başarısız olabilir, bu da önyükleme işlemini gereksiz yere yavaşlatabilir. Bunun yerine, bellenimin yüklenmesini istemcinin cihazı kullanmaya başladığı zamana erteleyin. Örneğin, bir ekran sürücüsü, ekran aygıtı açıldığında ürün yazılımını yükleyebilir.

Aygıt yazılımını yüklemek için .probe() işlevinin kullanılması bazı durumlarda uygun olabilir; örneğin, çalışması için aygıt yazılımına ihtiyaç duyan ancak aygıtın kullanıcı alanına açık olmayan bir saat sürücüsünde. Diğer uygun kullanım durumları da mümkündür.

Eşzamansız araştırmayı uygulama

Gelecekteki sürümlerde Android'e eklenebilecek paralel modül yükleme veya önyükleme süresini hızlandırmak için cihaz inceleme gibi gelecekteki geliştirmelerden yararlanmak için eşzamansız incelemeyi destekleyin ve kullanın. Eşzamansız araştırma kullanmayan sürücü modülleri bu tür optimizasyonların etkinliğini azaltabilir.

Bir sürücüyü eşzamansız incelemeyi destekleyen ve tercih eden olarak işaretlemek için sürücünün struct device_driver üyesindeki probe_type alanını ayarlayın. Aşağıdaki örnek, bir platform sürücüsü için etkinleştirilmiş bu tür bir desteği göstermektedir:

static struct platform_driver acme_driver = {
        .probe          = acme_probe,
        ...
        .driver         = {
                .name   = "acme",
                ...
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
};

Bir sürücünün eşzamansız araştırmayla çalışmasını sağlamak özel kod gerektirmez. Ancak eşzamansız araştırma desteği eklerken aşağıdakileri aklınızda bulundurun.

  • Daha önce incelenen bağımlılıklar hakkında varsayımlarda bulunmayın. Doğrudan veya dolaylı olarak kontrol edin (çoğu çerçeve çağrısı) ve bir veya daha fazla tedarikçi henüz hazır değilse -EPROBE_DEFER değerini döndürün.

  • Bir ana cihazın araştırma işlevine alt cihazlar eklerseniz alt cihazların hemen araştırıldığını varsaymayın.

  • Bir araştırma başarısız olursa, uygun hata işleme işlemini gerçekleştirin ve temizleyin (bkz. devm_*() API değişkenlerini kullanma ).

Cihaz problarını sipariş etmek için MODULE_SOFTDEP kullanmayın

MODULE_SOFTDEP() işlevi, aygıt araştırmalarının sırasını garanti etmek için güvenilir bir çözüm değildir ve aşağıdaki nedenlerden dolayı kullanılmamalıdır.

  • Ertelenmiş sonda. Bir modül yüklendiğinde, tedarikçilerinden birinin hazır olmaması nedeniyle cihaz araştırması ertelenebilir. Bu, modül yükleme sırası ile aygıt araştırma sırası arasında uyumsuzluğa yol açabilir.

  • Tek sürücü, birçok cihaz. Bir sürücü modülü belirli bir cihaz tipini yönetebilir. Sistem bir cihaz türünün birden fazla örneğini içeriyorsa ve bu cihazların her birinin farklı bir araştırma sırası gereksinimi varsa, modül yük sıralamasını kullanarak bu gereksinimlere uyamazsınız.

  • Asenkron araştırma. Eşzamansız araştırma gerçekleştiren sürücü modülleri, modül yüklendiğinde cihazı hemen araştırmaz. Bunun yerine, paralel bir iş parçacığı aygıt araştırmasını yönetir ve bu da modül yükleme sırası ile aygıt araştırma sırası arasında bir uyumsuzluğa yol açabilir. Örneğin, bir I2C ana sürücü modülü eşzamansız tarama gerçekleştirdiğinde ve bir dokunmatik sürücü modülü I2C veriyolu üzerindeki PMIC'ye bağlı olduğunda, dokunmatik sürücü ve PMIC sürücüsü doğru sırada yüklense bile dokunmatik sürücünün probu daha önce denenebilir. PMIC sürücü probu.

MODULE_SOFTDEP() işlevini kullanan sürücü modülleriniz varsa, bu işlevi kullanmamaları için bunları düzeltin. Size yardımcı olmak için Android ekibi, çekirdeğin MODULE_SOFTDEP() kullanmadan sıralama sorunlarını çözebilmesini sağlayan yukarı akışlı değişiklikler yaptı. Spesifik olarak, araştırma sırasını sağlamak için fw_devlink kullanabilir ve (bir cihazın tüm tüketicileri araştırma yaptıktan sonra) gerekli görevleri gerçekleştirmek için sync_state() geri çağrısını kullanabilirsiniz.

Yapılandırmalar için #ifdef yerine #if IS_ENABLED() kullanın

Yapılandırmanın gelecekte üç durumlu bir yapılandırmaya değişmesi durumunda #if bloğu içindeki kodun derlenmeye devam etmesini sağlamak için #ifdef CONFIG_XXX yerine #if IS_ENABLED(CONFIG_XXX) kullanın. Farklılıklar aşağıdaki gibidir:

  • #if IS_ENABLED(CONFIG_XXX) CONFIG_XXX modül ( =m ) veya yerleşik ( =y ) olarak ayarlandığında true olarak değerlendirilir.

  • #ifdef CONFIG_XXX CONFIG_XXX yerleşik ( =y ) olarak ayarlandığında true olarak değerlendirilir, ancak CONFIG_XXX modül ( =m ) olarak ayarlandığında değerlendirmez. Bunu yalnızca yapılandırma modül olarak ayarlandığında veya devre dışı bırakıldığında aynı şeyi yapmak istediğinizden emin olduğunuzda kullanın.

Koşullu derlemeler için doğru makroyu kullanın

Bir CONFIG_XXX modüle ( =m ) ayarlanmışsa, yapı sistemi otomatik olarak CONFIG_XXX_MODULE tanımlar. Sürücünüz CONFIG_XXX tarafından kontrol ediliyorsa ve sürücünüzün modül olarak derlenip derlenmediğini kontrol etmek istiyorsanız aşağıdaki yönergeleri kullanın:

  • Sürücünüzün C dosyasında (veya başlık dosyası olmayan herhangi bir kaynak dosyasında), #ifdef CONFIG_XXX_MODULE kullanmayın, çünkü gereksiz derecede kısıtlayıcıdır ve yapılandırma CONFIG_XYZ olarak yeniden adlandırılırsa bozulur. Bir modülde derlenen, başlık olmayan herhangi bir kaynak dosya için derleme sistemi, o dosyanın kapsamı için MODULE otomatik olarak tanımlar. Bu nedenle, bir C dosyasının (veya başlık olmayan herhangi bir kaynak dosyasının) bir modülün parçası olarak derlenip derlenmediğini kontrol etmek için #ifdef MODULE ( CONFIG_ öneki olmadan) kullanın.

  • Başlık dosyalarında aynı kontrol yanıltıcıdır çünkü başlık dosyaları doğrudan bir ikili dosyada derlenmez, bunun yerine bir C dosyasının (veya diğer kaynak dosyalarının) bir parçası olarak derlenir. Başlık dosyaları için aşağıdaki kuralları kullanın:

    • #ifdef MODULE kullanan bir başlık dosyası için sonuç, onu kullanan kaynak dosyaya göre değişir. Bu, aynı yapıdaki aynı başlık dosyasının, kodunun farklı bölümlerinin farklı kaynak dosyalar için derlenebileceği anlamına gelir (modül yerine yerleşik veya devre dışı). Bu, yerleşik kod için bir yönde, bir modül için ise farklı bir şekilde genişlemesi gereken bir makro tanımlamak istediğinizde yararlı olabilir.

    • Belirli bir CONFIG_XXX modüle ayarlandığında bir kod parçası halinde derlenmesi gereken bir başlık dosyası için (onu içeren kaynak dosyanın bir modül olup olmadığına bakılmaksızın), başlık dosyasının #ifdef CONFIG_XXX_MODULE kullanması gerekir.