Tedarikçi modüllerinizin sağlamlığını ve güvenilirliğini artırmak için aşağıdaki yönergeleri kullanın. Birçok kurala uyulduğunda doğru modül yükleme sırasını ve sürücülerin cihazları taraması gereken sırayı belirlemek kolaylaşabilir.
Modül, kitaplık veya sürücü olabilir.
Kitaplık modülleri, diğer modüllerin kullanabileceği API'ler sağlayan kitaplıklardır. Bu tür modüller genellikle donanıma özel değildir. Kitaplık modüllerine örnek olarak AES şifreleme modülü, modül olarak derlenen
remoteproc
çerçevesi ve günlük arabelleği 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 kod çalışmaz.Sürücü modülleri, belirli bir cihaz türünü arayan veya bu cihaz türüne bağlanan sürücülerdir. Bu tür 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 ilişkili cihaz sistemde bulunduğunda etkinleştirilir.
Cihaz mevcut değilse çalışan tek modül kodu, sürücüyü sürücü çekirdek çerçevesine kaydeden
module_init()
kodudur.Cihaz mevcutsa ve sürücü bu cihazı başarıyla araştırırsa veya ona bağlanırsa diğer modül kodu çalışabilir.
Modül başlatma ve sonlandırma işlevlerini doğru şekilde kullanma
Sürücü modülleri, sürücüleri module_init()
'e kaydetmeli ve module_exit()
'ten kaydını silmelidir. Bu kısıtlamaları uygulamanın bir yolu, module_init()
, *_initcall()
veya module_exit()
makrolarının doğrudan kullanımını önleyen sarmalayıcı makroları kullanmaktır.
Yükün kaldırılabileceği modüller için
module_subsystem_driver()
simgesini kullanın. Örnekler:module_platform_driver()
,module_i2c_driver()
vemodule_pci_driver()
.Boşaltılamayacak modüller için
builtin_subsystem_driver()
örnekleri kullanın:builtin_platform_driver()
,builtin_i2c_driver()
vebuiltin_pci_driver()
.
Bazı sürücü modülleri, birden fazla sürücü kaydettikleri için module_init()
ve module_exit()
kullanır. Birden fazla sürücüyü kaydettirmek için module_init()
ve module_exit()
kullanan bir sürücü modülünde sürücüleri tek bir sürücüde birleştirmeyi deneyin. Örneğin, ayrı sürücüler kaydettirmek yerine compatible
dizesini veya cihazın yardımcı verilerini kullanarak farklılaştırabilirsiniz.
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ı, iş sıraları veya çekirdek iş parçacıklarını ayarlamak için bu işlevlere ihtiyaç duyabileceğinden module_init()
ve module_exit()
ile ilgili kısıtlamalardan muaftır.
MODULE_DEVICE_TABLE makrosunu kullanma
Sürücü modülleri, kullanıcı alanının modülü yüklemeden önce sürücü modülü tarafından desteklenen cihazları belirlemesine olanak tanıyan MODULE_DEVICE_TABLE
makrosunu içermelidir. Android, modül yüklemeyi optimize etmek için bu verileri kullanabilir (ör. sistemde bulunmayan cihazlar için modül yüklemekten kaçınmak). Makroyu kullanmayla ilgili örnekler için yayın öncesi koda bakın.
Önceden tanımlanmış veri türleri nedeniyle CRC uyuşmazlıklarından kaçının
Önceden tanımlanmış veri türlerini görmek için üstbilgi dosyalarını eklemeyin.
Bir başlık dosyasında (header-A.h
) tanımlanan bazı yapıların, birliklerin ve diğer veri türlerinin, genellikle bu veri türlerine işaretçiler kullanan farklı bir başlık dosyasında (header-B.h
) ileriye dönük olarak tanımlanması mümkündür. Bu kod kalıbı, çekirdeğin veri yapısını header-B.h
kullanıcılarına karşı kasıtlı olarak gizli tutmaya çalıştığı anlamına gelir.
header-B.h
kullanıcıları, önceden bildirilmiş bu veri yapılarının iç kısımlarına doğrudan erişmek için header-A.h
eklememelidir. Bu işlem, farklı bir çekirdek (ör. GKI çekirdeği) modülü yüklemeye çalıştığında CONFIG_MODVERSIONS
CRC uyuşmazlığı sorunlarına (ABI uyumluluğu sorunlarına neden olur) yol açar.
Örneğin, struct fwnode_handle
include/linux/fwnode.h
içinde tanımlanır ancak çekirdek, struct fwnode_handle
ayrıntılarını include/linux/device.h
kullanıcılarından gizli tutmaya çalıştığı için include/linux/device.h
içinde struct fwnode_handle;
olarak ileriye dönük olarak bildirilir. Bu senaryoda, struct fwnode_handle
üyelerine erişmek için bir modüle #include <linux/fwnode.h>
eklemeyin. Bu tür üstbilgi dosyalarını eklemeniz gereken tüm tasarımlar kötü bir tasarım kalıbını gösterir.
Temel çekirdek yapılarına doğrudan erişmeyin
Çekirdek çekirdek veri yapılarına doğrudan erişmek veya bu yapıları değiştirmek, bellek sızıntısı, kilitlenme ve gelecekteki çekirdek sürümleriyle uyumluluğun bozulması gibi istenmeyen davranışlara neden olabilir. Aşağıdaki koşullardan herhangi birini karşılayan veri yapıları, temel çekirdek veri yapısıdır:
Veri yapısı
KERNEL-DIR/include/
altında tanımlanır. Örneğin,struct device
vestruct dev_links_info
.include/linux/soc
içinde tanımlanan veri yapıları bu kapsamda değildir.Veri yapısı modül tarafından ayrılır veya başlatılır ancak çekirdek tarafından dışa aktarılan bir işleve giriş olarak dolaylı olarak (bir yapıdaki işaretçi aracılığıyla) veya doğrudan aktarılarak çekirdek tarafından görünür hale getirilir. Örneğin, bir
cpufreq
sürücü modülüstruct cpufreq_driver
öğesini başlatır ve ardındancpufreq_register_driver()
öğesine giriş olarak iletir. Bu noktadan sonracpufreq
sürücü modülü,cpufreq_register_driver()
çağrıldığındastruct cpufreq_driver
çekirdeğe görünür hale geldiği içinstruct cpufreq_driver
'yi doğrudan değiştirmemelidir.Veri yapısı, modülünüz tarafından başlatılmamıştır. Örneğin,
regulator_register()
tarafından döndürülenstruct regulator_dev
.
Temel çekirdek veri yapılarına yalnızca çekirdek tarafından dışa aktarılan işlevler veya tedarikçi kancalarına giriş olarak açıkça iletilen parametreler aracılığıyla erişin. Temel çekirdek veri yapısının bölümlerini değiştirmek için bir API'niz veya tedarikçi kancanız yoksa bu durum muhtemelen bilinçli olarak yapılmış demektir ve veri yapısını modüllerden değiştirmemeniz gerekir. Örneğin, struct device
veya struct device.links
içindeki alanları değiştirmeyin.
device.devres_head
değerini değiştirmek içindevm_clk_get()
,devm_regulator_get()
veyadevm_kzalloc()
gibi birdevm_*()
işlevi kullanın.struct device.links
içindeki alanları değiştirmek içindevice_link_add()
veyadevice_link_del()
gibi bir cihaz bağlantısı API'si kullanın.
Uyumlu mülkü olan cihaz ağacı düğümlerini ayrıştırmayın
Bir cihaz ağacı (DT) düğümünde compatible
mülkü varsa struct device
otomatik olarak veya üst DT düğümünde of_platform_populate()
çağrıldığında (genellikle üst cihazın cihaz sürücüsü tarafından) atanır. Varsayılan beklenti (planlayıcı için erken başlatılan bazı cihazlar hariç), compatible
mülküne sahip bir DT düğümünün struct device
ve eşleşen bir cihaz sürücüsüne sahip olmasıdır. Diğer tüm istisnalar, yayın öncesi kod tarafından zaten ele alınmıştır.
Ayrıca fw_devlink
(eski adıyla of_devlink
), compatible
mülküne sahip DT düğümlerini, sürücü tarafından taranan ayrılmış bir struct device
içeren cihazlar olarak kabul eder. Bir DT düğümünde compatible
mülkü varsa ancak ayrılan struct device
taranmıyorsa fw_devlink
, tüketici cihazlarının taranmasını veya tedarikçi cihazları için sync_state()
çağrılarının yapılmasını engelleyebilir.
Sürücünüzde, compatible
mülkü olan bir DT düğümünü doğrudan bulup ardından bu DT düğümünü ayrıştırmak için bir of_find_*()
işlevi (of_find_node_by_name()
veya of_find_compatible_node()
gibi) kullanılıyorsa cihazı kontrol edebilecek veya compatible
mülkünü kaldırabilecek (yalnızca yayına aktarılmamışsa mümkündür) bir cihaz sürücüsü yazarak modülü düzeltin. Alternatifleri görüşmek için kernel-team@android.com adresinden Android Çekirdek Ekibi ile iletişime geçin ve kullanım alanlarınızı gerekçelendirmeye hazır olun.
Tedarikçi firmaları aramak için DT phandle'lerini kullanma
Mümkün olduğunda DT'de phandle (DT düğümüne referans veya işaretçi) kullanarak tedarikçiye atıfta bulunun. Tedarikçilere atıfta bulunmak için standart DT bağlamaları ve phandle'leri kullanmak, fw_devlink
'ün (eski adıyla of_devlink
) çalışma zamanında DT'yi ayrıştırarak cihazlar arası bağımlılıkları otomatik olarak belirlemesini sağlar. Böylece çekirdek, modül yükleme sırası veya MODULE_SOFTDEP()
'ye gerek kalmadan cihazları otomatik olarak doğru sırada tarayabilir.
Eski senaryo (ARM çekirdeğinde DT desteği yok)
Daha önce, DT desteği ARM çekirdeklerine eklenmeden önce dokunmatik cihazlar gibi tüketiciler, dünya genelinde benzersiz dizeler kullanarak düzenleyiciler gibi tedarikçileri aradı.
Örneğin, ACME PMIC sürücüsü birden fazla regülatörü (acme-pmic-ldo1
ila acme-pmic-ldo10
gibi) kaydedebilir veya tanıtabilir ve bir dokunmatik sürücü regulator_get(dev, "acme-pmic-ldo10")
kullanarak bir regülatörü arayabilir.
Ancak farklı bir kartta LDO8, dokunmatik cihazı besleyebilir. Bu durumda, aynı dokunmatik sürücünün, dokunmatik cihazın kullanıldığı her kart için regülatöre ait doğru arama dizesini belirlemesi gereken hantal bir sistem oluşturulur.
Mevcut senaryo (ARM çekirdeğinde DT desteği)
DT desteği ARM çekirdeklerine eklendikten sonra tüketiciler, phandle kullanarak tedarikçinin cihaz ağacı düğümüne başvurarak DT'deki tedarikçileri tanımlayabilir.
Tüketiciler, kaynağın adını tedarik edene göre değil, kaynağın ne için kullanıldığına göre de adlandırabilir. Örneğin, önceki örnekteki dokunmatik sürücü, dokunmatik cihazın çekirdeğini ve sensörünü destekleyen tedarikçileri almak için regulator_get(dev, "core")
ve regulator_get(dev, "sensor")
kullanabilir. Bu tür bir cihaz için ilişkili DT, 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ünü içeren senaryo
Eski çekirdeklerden aktarılan bazı sürücüler, DT'de eski şemanın en kötü bölümünü alıp işleri kolaylaştırmak için yeni şemaya zorlayan eski davranışı içerir. Bu tür sürücülerde, tüketici sürücüsü cihaza özgü bir DT mülkünü kullanarak arama için kullanılacak dizeyi okur, tedarikçi, tedarikçi kaynağını kaydettirmek için kullanılacak adı tanımlamak üzere tedarikçiye özgü başka bir mülkü kullanır. Ardından tüketici ve tedarikçi, tedarikçiyi aramak için dizeleri kullanmaya devam eder. Her iki dünyanın da en kötüsünü içeren 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 cihazın deneme yapmaya çalıştığını ancak şu anda yapamadığını ve çekirdeğin denemeyi daha sonra tekrar denemesi gerektiğini belirtmek için hata döndürme değeri olarak -EPROBE_DEFER
döndürür. Cihazınızın .probe()
işlevinin bu gibi durumlarda beklendiği gibi başarısız olmasını sağlamak için hata değerini değiştirmeyin veya yeniden haritalandırmayın.
Hata değerinin değiştirilmesi veya yeniden eşlenmesi, -EPROBE_DEFER
değerinin atlanmasına ve cihazınızın hiçbir zaman taranmasına neden olabilir.
devm_*() API varyantlarını kullanma
Cihaz bir devm_*()
API'sini kullanarak kaynak edindiğinde, cihaz keşif yapamazsa veya başarılı bir şekilde keşif yapıp daha sonra bağ bağlamazsa kaynak çekirdek tarafından otomatik olarak serbest bırakılır. Bu özellik, devm_*()
tarafından edinilen kaynakları serbest bırakmak için goto
atlamaları gerektirmediğinden ve sürücü bağlama işlemlerini basitleştirdiğinden probe()
işlevindeki hata işleme kodunu daha temiz hale getirir.
Cihaz sürücüsünün bağlantısını kaldırma işlemini yönetme
Cihaz sürücülerinin bağlamasını kaldırma konusunda dikkatli olun ve bağlama kaldırma işlemini tanımlı olmayan olarak bırakmayın. Tanımlı olmayan, izin verilmediği anlamına gelmez. Cihaz sürücüsünün bağlantısını kaldırma özelliğini tam olarak uygulamanız veya cihaz sürücüsünün bağlantısını kaldırma özelliğini açıkça devre dışı bırakmanız gerekir.
Cihaz sürücüsünün bağlantısını kaldırma işlemini uygulama
Cihaz sürücüsünün bağlantısını kaldırma özelliğini tam olarak uygulamayı seçtiğinizde, bellek veya kaynak sızıntılarını ve güvenlik sorunlarını önlemek için cihaz 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 cihazı sürücüye bağlayabilir ve sürücünün remove()
işlevini çağırarak cihazın sürücüyle olan bağlantısını kaldırabilirsiniz. remove()
işlevi yoksa çekirdek yine de cihazın bağlamasını kaldırabilir. Sürücü çekirdeği, sürücü cihazla bağlantısını kaldırırken temizleme çalışması gerekmediğini varsayar. Bir cihazdan ayrılan sürücünün, aşağıdakilerin her ikisi de doğru olduğunda herhangi bir temizleme çalışması yapması gerekmez:
Sürücülerin
probe()
işlevi tarafından edinilen tüm kaynaklardevm_*()
API'leri aracılığıyla elde edilir.Donanım cihazının kapatılması veya bekleme durumuna geçirilmesi gerekmez.
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. Yukarıdaki ifadelerden herhangi biri doğru değilse sürücünün, bir cihazla bağlantısını kaldırırken temizleme işlemi yapması (kaynakları serbest bırakma ve donanımı kapatma ya da beklemeye alma) gerekir. Bir cihazın sürücü modülünün bağlamasını düzgün bir şekilde kaldırabilmesini sağlamak için aşağıdaki seçeneklerden birini kullanın:
Donanımın kapatılması veya bekleme durumuna geçirilmesi gerekmiyorsa cihaz modülünü,
devm_*()
API'lerini kullanarak kaynak edinecek şekilde değiştirin.remove()
sürücü işleminiprobe()
işleviyle aynı yapıda uygulayın, ardındanremove()
işlevini kullanarak temizleme adımlarını uygulayın.
Cihaz sürücüsünün bağlamasını açıkça devre dışı bırakma (önerilmez)
Cihaz sürücüsünün bağlantısını kaldırma özelliğini açıkça devre dışı bırakmayı seçtiğinizde, bağlantı kaldırma işlemine ve modül boşaltma işlemine izin vermemeniz gerekir.
Bağlantıyı kaldırmaya izin vermemek için sürücünün
struct device_driver
dosyasındasuppress_bind_attrs
işaretinitrue
olarak ayarlayın. Bu ayar,bind
veunbind
dosyalarının sürücününsysfs
dizininde gösterilmesini engeller.unbind
dosyası, kullanıcı alanının bir sürücünün cihazıyla olan bağlamasını kaldırmayı tetiklemesine olanak tanır.Modülün kaldırılmasına izin vermemek için modülün
lsmod
içinde[permanent]
değerine sahip olduğundan emin olun.module_exit()
veyamodule_XXX_driver()
kullanılmadığında modül[permanent]
olarak işaretlenir.
Donanım yazılımını prob işlevi içinden yüklemeyin
Sürücü, .probe()
işlevinden donanım yazılımı yüklememelidir. Aksi takdirde, sürücü flaştan veya kalıcı depolama alanına dayalı dosya sisteminden önce algılama yaparsa donanım yazılımına erişemeyebilir. Bu gibi durumlarda request_firmware*()
API uzun süre boyunca engellendikten sonra başarısız olabilir. Bu da önyükleme sürecini gereksiz yere yavaşlatabilir. Bunun yerine, donanım yazılımının yüklenmesini istemcinin cihazı kullanmaya başladığı zamana erteleyin. Örneğin, ekran sürücüsü, ekran cihazı açıldığında donanım yazılımını yükleyebilir.
Donanım yazılımını yüklemek için .probe()
kullanılması bazı durumlarda uygun olabilir. Örneğin, çalışması için donanım yazılımına ihtiyaç duyan ancak cihazın kullanıcı alanına maruz kalmadığı bir saat sürücüsü. Uygun diğer kullanım alanları da mümkündür.
Eşzamansız problamayı uygulama
Gelecekteki sürümlerde Android'e eklenebilecek paralel modül yükleme veya cihazı tarama gibi gelecekteki geliştirmelerden yararlanmak için asenkron tarama özelliğini destekleyin ve kullanın. Bu sayede, önyükleme süresini kısaltabilirsiniz. Asenkron problama kullanmayan sürücü modülleri, bu tür optimizasyonların etkinliğini azaltabilir.
Bir sürücüyü, asenkron problamayı desteklediği ve tercih ettiği şekilde işaretlemek için sürücünün struct device_driver
üyesindeki probe_type
alanını ayarlayın. Aşağıdaki örnekte, platform sürücüsü için bu tür desteğin etkinleştirildiği gösterilmektedir:
static struct platform_driver acme_driver = {
.probe = acme_probe,
...
.driver = {
.name = "acme",
...
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};
Bir sürücünün zaman uyumsuz problamayla çalışmasını sağlamak için özel kod gerekmez. Ancak, asenkron problama desteği eklerken aşağıdakileri göz önünde bulundurun.
Daha önce taranan bağımlılıklarla ilgili varsayımda bulunmayın. Bir veya daha fazla tedarikçi henüz hazır değilse doğrudan veya dolaylı olarak (çoğu çerçeve çağrısı) kontrol edin ve
-EPROBE_DEFER
döndürün.Ebeveyn cihazın tarama işlevine çocuk cihazlar eklerseniz çocuk cihazların hemen tarandığını varsaymayın.
Bir sonda başarısız olursa uygun hata işleme ve temizleme işlemini gerçekleştirin (devm_*() API varyantlarını kullanma bölümüne bakın).
Cihaz problarını sipariş etmek için MODULE_SOFTDEP kullanmayın
MODULE_SOFTDEP()
işlevi, cihaz problarının sırasını garanti etmek için güvenilir bir çözüm değildir ve aşağıdaki nedenlerle kullanılmamalıdır.
Ertelenen prob. Bir modül yüklendiğinde, tedarikçilerinden biri hazır olmadığı için cihaz probu ertelenebilir. Bu durum, modül yükleme sırası ile cihaz probu sırası arasında uyuşmazlığa neden olabilir.
Tek sürücü, birçok cihaz. Sürücü modülü belirli bir cihaz türünü yönetebilir. Sistemde bir cihaz türünün birden fazla örneği varsa ve bu cihazların her birinin farklı bir prob siparişi koşulu varsa modül yükleme sırasını kullanarak bu koşullara uyamazsınız.
Eşzamansız problama. Asenkron problama gerçekleştiren sürücü modülleri, modül yüklendiğinde cihazı hemen taramamaktadır. Bunun yerine, cihaz araştırması paralel bir iş parçacığı tarafından yönetilir. Bu da modül yükleme sırası ile cihaz araştırma sırası arasında uyuşmazlığa neden olabilir. Örneğin, bir I2C ana sürücü modülü asenkron problama gerçekleştirdiğinde ve bir dokunmatik sürücü modülü I2C veri yolunda bulunan PMIC'ye bağlı olduğunda, dokunmatik sürücü ve PMIC sürücüsü doğru sırada yüklenirse bile dokunmatik sürücünün problaması PMIC sürücü problamasından önce denenebilir.
MODULE_SOFTDEP()
işlevini kullanan sürücü modülleriniz varsa bu işlevi kullanmamaları için düzeltin. Android ekibi, size yardımcı olmak için çekirdeğin MODULE_SOFTDEP()
kullanmadan sıralama sorunlarını ele almasını sağlayan değişiklikleri yayına aldı. Daha açık belirtmek gerekirse, prob sıralamasını sağlamak için fw_devlink
'ü ve (bir cihazın tüm tüketicileri prob yaptıktan sonra) gerekli görevleri gerçekleştirmek için sync_state()
geri çağırma işlevini kullanabilirsiniz.
Yapılandırmalar için #ifdef yerine #if IS_ENABLED() kullanın
Gelecekte yapılandırma üç değerli bir yapılandırmaya değişirse #if
bloğundaki kodun derlenmeye devam etmesini sağlamak için #ifdef CONFIG_XXX
yerine #if IS_ENABLED(CONFIG_XXX)
kullanın. Farklar aşağıda belirtilmiştir:
CONFIG_XXX
modül (=m
) veya yerleşik (=y
) olarak ayarlandığında#if IS_ENABLED(CONFIG_XXX)
true
değerini alır.CONFIG_XXX
yerleşik (=y
) olarak ayarlandığında#ifdef CONFIG_XXX
true
değerini alır ancakCONFIG_XXX
modül (=m
) olarak ayarlandığında bu değere ulaşmaz. Bu işlevi yalnızca yapılandırma modül olarak ayarlandığında veya devre dışı bırakıldığında aynı işlemi yapmak istediğinizden emin olduğunuzda kullanın.
Koşullu derlemeler için doğru makroyu kullanma
Bir CONFIG_XXX
modül (=m
) olarak ayarlanırsa derleme sistemi CONFIG_XXX_MODULE
'yi otomatik olarak 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 uygulayın:
Sürücünüzün C dosyasında (veya üstbilgi dosyası olmayan herhangi bir kaynak dosyada)
#ifdef CONFIG_XXX_MODULE
kullanmayın. Bu karakter gereksiz yere kısıtlayıcıdır ve yapılandırmaCONFIG_XYZ
olarak yeniden adlandırılırsa çalışmaz. Bir modüle derlenen başlık olmayan tüm kaynak dosyalar için derleme sistemi, söz konusu dosyanın kapsamı içinMODULE
değerini otomatik olarak tanımlar. Bu nedenle, bir C dosyasının (veya üstbilgi olmayan herhangi bir kaynak dosyanın) bir modülün parçası olarak derlenip derlenmediğini kontrol etmek için#ifdef MODULE
(CONFIG_
ön ekiyle değil) kullanın.Başlık dosyaları doğrudan ikili program dosyası olarak derlenmediğinden, bu dosyalar için aynı kontrolü yapmak daha zordur. Başlık dosyaları, C dosyası (veya diğer kaynak dosyalar) kapsamında derlenir. Başlık dosyaları için aşağıdaki kuralları kullanın:
#ifdef MODULE
kullanan bir başlık dosyası için sonuç, hangi kaynak dosyanın bunu kullandığına bağlı olarak değişir. Bu, aynı derlemedeki aynı başlık dosyasının kodunun farklı bölümlerinin farklı kaynak dosyaları için derlenmiş olabileceği anlamına gelir (modül ve yerleşik veya devre dışı). Bu, yerleşik kod için bir şekilde, modül için farklı bir şekilde genişletilmesi gereken bir makro tanımlamak istediğinizde yararlı olabilir.Belirli bir
CONFIG_XXX
modül olarak ayarlandığında bir kod parçasında derlenmesi gereken bir üstbilgi dosyası için (bu üstbilgiyi içeren kaynak dosyanın modül olup olmadığına bakılmaksızın), üstbilgi dosyası#ifdef CONFIG_XXX_MODULE
kullanmalıdır.