Rumah > Artikel > Tutorial sistem > Model peranti Linux (3)_Uevent
Uevent ialah sebahagian daripada Kobject dan digunakan untuk memberitahu program ruang pengguna apabila status Kobject berubah (seperti penambahan, pengalihan keluar, dsb.). Selepas menerima acara sedemikian, program ruang pengguna akan mengendalikannya dengan sewajarnya.
Biasanya, mekanisme ini digunakan untuk menyokong peranti boleh pasang panas. Sebagai contoh, apabila pemacu denyar USB dimasukkan, pemacu yang berkaitan dengan USB akan mencipta struktur peranti secara dinamik (termasuk kobjek yang sepadan) yang digunakan untuk mewakili pemacu denyar USB dan memaklumkan program ruang pengguna. Ini akan membolehkan nod peranti dicipta secara dinamik dalam direktori /dev/. Tambahan pula, mekanisme ini juga boleh memberitahu aplikasi lain untuk memasang peranti pemacu kilat USB ke dalam sistem, dengan itu merealisasikan sokongan dinamik untuk peranti tersebut.
Gambar berikut menerangkan lokasi modul Uevent dalam kernel:
Dapat dilihat bahawa mekanisme Uevent adalah agak mudah Apabila mana-mana peranti dalam model peranti mempunyai peristiwa yang perlu dilaporkan, antara muka yang disediakan oleh Uevent akan dicetuskan. Selepas modul Uevent menyediakan format untuk melaporkan acara, ia boleh melaporkan acara itu kepada ruang pengguna melalui dua cara: satu ialah memanggil terus fail boleh laku ruang pengguna melalui modul kmod; mekanisme untuk memindahkan acara dari ruang Kernel dihantar ke ruang pengguna.
Nota 1: Kmod dan netlink akan diterangkan dalam artikel lain, jadi artikel ini tidak akan menerangkannya secara terperinci.
Kod Uevent agak mudah, terutamanya melibatkan dua fail: kobject.h dan kobject_uevent.c, seperti berikut:
kobject.h mentakrifkan pemalar dan struktur data berkaitan uevent, seperti berikut:
kobject_action mentakrifkan jenis acara, termasuk:
“
TAMBAH/KELUARKAN, Kobject (atau struktur data atas) menambah/mengalih keluar acara.
DALAM TALIAN/LUAR TALIAN, acara dalam talian/luar talian Kobject (atau struktur data lapisan atas), sebenarnya merujuk kepada sama ada ia didayakan atau tidak.
CHANGE, keadaan atau kandungan Kobject (atau struktur data atas) berubah.
MOVE, Kobject (atau struktur data atas) menukar nama atau menukar Induk (bermaksud struktur direktori ditukar dalam sysfs).
TUKAR, jika peristiwa yang pemacu peranti perlu laporkan tidak lagi dalam skop peristiwa di atas, atau merupakan peristiwa tersuai, anda boleh menggunakan acara ini dan membawa parameter yang sepadan.
”
Seperti yang dinyatakan sebelum ini, apabila menggunakan Kmod untuk melaporkan acara kepada ruang pengguna, fail boleh laku ruang pengguna akan dilaksanakan secara langsung. Dalam sistem Linux, pelaksanaan fail boleh laku bergantung pada pembolehubah persekitaran, jadi kobj_uevent_env digunakan untuk mengatur pembolehubah persekitaran semasa melaporkan acara ini.
“
envp,指针数组,用于保存每个环境变量的地址,最多可支持的环境变量数量为UEVENT_NUM_ENVP。
envp_idx,用于访问环境变量指针数组的index。
buf,保存环境变量的buffer,最大为UEVENT_BUFFER_SIZE。
buflen,访问buf的变量。
”
1: /* include/linux/kobject.h, line 123 */ 2: struct kset_uevent_ops { 3: int (* const filter)(struct kset *kset, struct kobject *kobj); 4: const char *(* const name)(struct kset *kset, struct kobject *kobj); 5: int (* const uevent)(struct kset *kset, struct kobject *kobj, 6: struct kobj_uevent_env *env); 7: };
kset_uevent_ops是为kset量身订做的一个数据结构,里面包含filter和uevent两个回调函数,用处如下:
“
filter,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口过滤,阻止不希望上报的event,从而达到从整体上管理的目的。
name,该接口可以返回kset的名称。如果一个kset没有合法的名称,则其下的所有Kobject将不允许上报uvent
uevent,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口统一为这些event添加环境变量。因为很多时候上报uevent时的环境变量都是相同的,因此可以由kset统一处理,就不需要让每个Kobject独自添加了。
”
通过kobject.h,uevent模块提供了如下的API(这些API的实现是在”lib/kobject_uevent.c”文件中):
1: /* include/linux/kobject.h, line 206 */ 2: int kobject_uevent(struct kobject *kobj, enum kobject_action action); 3: int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, 4: char *envp[]); 5: 6: __printf(2, 3) 7: int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...); 8: 9: int kobject_action_type(const char *buf, size_t count, 10: enum kobject_action *type);
“
kobject_uevent_env,以envp为环境变量,上报一个指定action的uevent。环境变量的作用是为执行用户空间程序指定运行环境。具体动作如下:
- Cari sama ada kobj itu sendiri atau induknya tergolong dalam kset Jika tidak, ralat akan dilaporkan (Nota 2: Ini boleh menjelaskan bahawa jika kobj tidak menyertai kset, ia tidak dibenarkan melaporkan uevent)
- Semak sama ada kobj->uevent_suppress ditetapkan Jika ia ditetapkan, abaikan semua laporan uevent dan kembalikan (Nota 3: Dari sini dapat dilihat bahawa pelaporan uevent_suppress Kobject boleh dikawal melalui bendera uevent_suppress Kobject)
- Jika kset yang dimilikinya mempunyai fungsi uevent_ops->filter, panggil fungsi ini untuk menapis laporan (Nota 4: Ini menyokong penerangan antara muka penapis dalam bahagian 3.2. Kset boleh menapis peristiwa yang tidak mahu dilaporkan melalui antara muka penapis, untuk mencapai kesan pengurusan keseluruhan)
- Tentukan sama ada kset yang dimilikinya mempunyai nama yang sah (dipanggil subsistem, yang berbeza daripada versi kernel sebelumnya), jika tidak, ia tidak dibenarkan melaporkan uevent
- Peruntukkan penimbal untuk menyimpan pembolehubah persekitaran untuk laporan ini (hasilnya disimpan dalam penuding env), dan dapatkan maklumat laluan Kobject dalam sysfs (perisian ruang pengguna perlu mengaksesnya dalam sysfs berdasarkan maklumat laluan)
- Panggil add_uevent_var antara muka (diterangkan di bawah) untuk menambah Tindakan, maklumat laluan, subsistem dan maklumat lain pada penuding env
- Jika envp masuk tidak kosong, huraikan pembolehubah persekitaran masuk, panggil juga antara muka add_uevent_var dan tambahkannya pada penuding env
- Jika kset yang dimilikinya mempunyai antara muka uevent_ops->uevent, panggil antara muka ini dan tambahkan pembolehubah persekitaran bersatu kset pada penuding env
- Mengikut jenis TINDAKAN, tetapkan pembolehubah kobj->state_add_uevent_sent dan kobj->state_remove_uevent_sent untuk merekodkan status yang betul
- Panggil antara muka add_uevent_var dan tambah nombor siri dalam format "SEQNUM=%llu"
- Jika "CONFIG_NET" ditakrifkan, gunakan netlink untuk menghantar uevent
- Mengambil uevent_helper, subsistem dan penuding env dengan pembolehubah persekitaran standard (HOME=/, PATH=/sbin:/bin:/usr/sbin:/usr/bin) sebagai parameter, panggil fungsi call_usermodehelper yang disediakan oleh modul kmod dan laporkan uevent .
Kandungan uevent_helper ditentukan oleh item konfigurasi kernel CONFIG_UEVENT_HELPER_PATH (terletak dalam ./drivers/base/Kconfig) (rujuk lib/kobject_uevent.c, baris 32 item konfigurasi ini menentukan program ruang pengguna (atau skrip). Digunakan untuk menghuraikan uevent yang dilaporkan, seperti "/sbin/hotplug".
Fungsi call_usermodehelper adalah untuk menghentikan proses, mengambil uevent sebagai parameter dan melaksanakan uevent_helper.kobject_uevent mempunyai fungsi yang sama seperti kobject_uevent_env, kecuali tiada pembolehubah persekitaran dinyatakan.
add_uevent_var, menyalin pembolehubah persekitaran ke penuding env dalam bentuk aksara pemformatan (serupa dengan printf, printk, dll.).
kobject_action_type, tukarkan Action jenis enum kobject_action kepada rentetan.
”
说明:怎么指定处理uevent的用户空间程序(简称uevent helper)?
上面介绍kobject_uevent_env的内部动作时,有提到,Uevent模块通过Kmod上报Uevent时,会通过call_usermodehelper函数,调用用户空间的可执行文件(或者脚本,简称**uevent helper** )处理该event。而该uevent helper的路径保存在**uevent_helper数组中。
可以在编译内核时,通过CONFIG_UEVENT_HELPER_PATH配置项,静态指定uevent helper。但这种方式会为每个event fork一个进程,随着内核支持的设备数量的增多,这种方式在系统启动时将会是致命的(可以导致内存溢出等)。因此只有在早期的内核版本中会使用这种方式,现在内核不再推荐使用该方式。因此内核编译时,需要把该配置项留空。
在系统启动后,大部分的设备已经ready,可以根据需要,重新指定一个uevent helper,以便检测系统运行过程中的热拔插事件。这可以通过把helper的路径写入到"/sys/kernel/uevent_helper”文件中实现。实际上,内核通过sysfs文件系统的形式,将uevent_helper数组开放到用户空间,供用户空间程序修改访问,具体可参考"****./kernel/ksysfs.c”中相应的代码,这里不再详细描述。
Atas ialah kandungan terperinci Model peranti Linux (3)_Uevent. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!