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 kullanması için 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 modüller donanıma özgüdür. 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 çıkış işlevlerini doğru şekilde kullanma
Sürücü modülleri, module_init()
ürününde bir sürücüyü kaydetmeli ve module_exit()
ürününde bir sürücünün kaydını iptal etmelidir. 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ı oluşturmak 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, sistemde bulunmayan cihazların modüllerini yüklemekten kaçınmak gibi yöntemlerle modül yüklemeyi optimize etmek için bu verileri kullanabilir. 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
içermemelidir. 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 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()
cihazına 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ülke sahip devicetree düğümlerini ayrıştırma
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
özelliğine 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, bir sürücü tarafından taranan ayrılmış 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 bir phandle (DT düğümüne referans veya işaretçi) kullanarak tedarikçiye referans verin. Tedarikçilere referans vermek için standart DT bağlamaları ve p elleri kullanmak, fw_devlink
(eski adıyla of_devlink
), DT'yi çalışma zamanında 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 {
...
};
};
İkisi için de en kötü senaryo
Eski çekirdeklerden aktarılan bazı sürücülerde, eski şemanın en kötü bölümünü alıp işleri kolaylaştırmak amacıyla yeni şemaya zorlayan eski davranış DT'de yer alır. 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 başka bir tedarikçiye özgü 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 yoklama yapmaya çalıştığını ancak şu anda olmadığını ve çekirdeğin yoklamayı daha sonra tekrar denemesi gerektiğini belirten hata döndürme değeri olarak -EPROBE_DEFER
döndürür. Bu gibi durumlarda cihazınızın .probe()
işlevinin beklendiği gibi çalışmaması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 atlanmasına ve cihazınızın hiçbir zaman taranmasına neden olabilir.
devm_*() API varyantlarını kullanma
Cihaz bir devm_*()
API'yi kullanarak kaynak edindiğinde, cihaz sondalama işlemini yapamazsa veya başarılı bir şekilde sondalama yapar ve daha sonra bağ bağlama işlemi iptal edilirse 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ü bağlantısını kaldırmayı tam olarak uygulamanız veya cihaz sürücüsü bağlantısını kaldırmayı 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ı 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 veya 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ü bağlantısını kaldırmayı açık bir şekilde devre dışı bırakın (önerilmez)
Cihaz-sürücü bağlantısını kaldırma özelliğini açık bir şekilde devre dışı bırakmayı seçtiğinizde, bağlantı kaldırma işlemine izin vermemeniz ve modül kaldırma 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 kaldırılmasına izin vermemek için modülün
lsmod
içinde[permanent]
bulunduğundan emin olun.module_exit()
veyamodule_XXX_driver()
kullanılmadığında modül[permanent]
olarak işaretlenir.
Donanım yazılımını yoklama işlevi içinden yüklemeyin
Sürücü, flaş veya kalıcı depolama tabanlı dosya sistemi monte edilmeden önce durum kontrolü yaparsa donanım yazılımına erişemeyebilir. Bu nedenle sürücü, .probe()
işlevi içinden donanım yazılımını yüklememelidir. Bu tür durumlarda request_firmware*()
API uzun süre engelleme yapıp daha sonra başarısız olabilir. Bu da başlatma işlemini gereksiz biçimde yavaşlatabilir. Bunun yerine, donanım yazılımının yüklenmesini istemcinin
cihazı kullanmaya başlayacağı zamana erteleyin. Örneğin, ekran sürücüsü, donanım yazılımını
ekran cihazı açıldığında yükleyebilir.
Donanım yazılımının çalışması için donanım yazılımına ihtiyacı olan ancak cihazın kullanıcı alanına maruz kalmadığı bir saat sürücüsünde olduğu gibi bazı durumlarda donanım yazılımını yüklemek için .probe()
kullanılması uygun olabilir. Uygun diğer kullanım alanları 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 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ın yoklama işlevine çocuk cihazları eklerseniz alt cihazların hemen kontrol edileceğini varsaymayın.
Bir kontrol başarısız olursa hata işlemeyi uygun şekilde gerçekleştirin ve hataları temizleyin (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 kontrol. Bir modül yüklenirken cihaz yoklamasının tedarikçilerinden biri hazır olmadığı için cihaz yoklaması ertelenebilir. Bu durum, modül yükleme sırası ile cihaz probu sırası arasında uyuşmazlığa neden olabilir.
Tek bir 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 durum kontrolü. Asenkron problama gerçekleştiren sürücü modülleri, modül yüklendiğinde cihazı hemen taramamaktadır. Bunun yerine, cihaz problaması paralel bir iş parçacığı tarafından yönetilir. Bu da modül yükleme sırası ile cihaz problama 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 veriyolundaki 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 bunları kullanmamaları için düzeltin. Size yardımcı olmak için Android ekibi, çekirdeğin MODULE_SOFTDEP()
kullanmadan sipariş sorunlarını ele almasını sağlayan değişiklikler yayınladı. Özellikle, durum kontrolü sağlamak için fw_devlink
kullanabilir ve (cihazın tüm tüketicileri kontrol edildikten sonra) gerekli görevleri gerçekleştirmek için sync_state()
geri çağırma özelliğinden yararlanabilirsiniz.
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 kullanın
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, 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 başlık dışı herhangi bir kaynak dosyanın) modülün parçası olarak derlenip derlenmediğini kontrol etmek için#ifdef MODULE
(CONFIG_
öneki olmadan) işlevini kullanın.Başlık dosyaları doğrudan ikili program dosyası olarak derlenmediğinden, bu tür dosyalarda 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.