Linux ialah sistem pengendalian berkuasa yang menyediakan banyak mekanisme komunikasi antara proses yang cekap, seperti paip, isyarat, baris gilir mesej, memori dikongsi, dsb. Tetapi adakah cara yang lebih mudah, lebih fleksibel dan lebih cekap untuk berkomunikasi? Jawapannya ya, itulah eventfd. eventfd ialah panggilan sistem yang diperkenalkan dalam Linux versi 2.6 Ia boleh digunakan untuk melaksanakan pemberitahuan acara, iaitu, untuk menyampaikan acara melalui deskriptor fail. eventfd mengandungi pembilang integer tidak bertanda 64-bit yang diselenggara oleh kernel Proses ini boleh membaca/menukar nilai pembilang dengan membaca/menulis deskriptor fail ini untuk mencapai komunikasi antara proses. Apakah kelebihan eventfd? Ia mempunyai ciri-ciri berikut:
Jadi, bagaimana eventfd berfungsi? Apakah senario aplikasi yang ada padanya? Artikel ini akan memperkenalkan eventfd artifak dari dua aspek: prinsip dan aplikasi.
Secara umumnya: Terdapat lima penyelesaian utama untuk komunikasi antara proses Linux: paip, baris gilir mesej, semafor, memori dikongsi dan soket.
Saya tidak begitu biasa dengan paip. Saya hanya tahu tentang batasan paip umum dan hubungan antara proses ibu bapa dan anak. Saya menolaknya pada mulanya kerana apa yang saya mahu lakukan adalah komunikasi antara proses yang bebas terhad kepada proses ibu bapa dan anak, tetapi dalam keadaan kernel Tidak pasti cara menggunakannya.
Saya tidak faham Baris Mesej langsung.
Inti semaphore ialah operasi atom pembolehubah kernel, tetapi antara muka hanya dicerminkan dalam keadaan pengguna, dan operasi PV semaphore nampaknya lebih kepada pengecualian bersama, dan bukannya mekanisme bangun pemberitahuan yang saya mahukan. .
Memori yang dikongsi lebih menyusahkan Antara muka hanya dalam mod pengguna Jika anda ingin berkongsi memori antara mod kernel dan mod pengguna, anda perlu menulis fail itu sendiri dan kemudian menyediakan antara muka mmap.
Soket hanya digunakan dengan tcp/udp af_inet dan dgram af_unix sebelum ini. Kernel tidak menyediakan antara muka yang jelas Walaupun anda boleh memanggilnya sendiri menggunakan fungsi seperti sock->ops->recvmsg Lagipun, anda perlu membina sendiri parameter input, yang masih terasa tidak selamat.
Satu-satunya perkara yang tinggal nampaknya ialah netlink Soket ini dengan jelas menyediakan fungsi penghantaran paket kernel, kerana ia mengeksport dengan jelas fungsi netlink_kernel_create, jadi fungsi keadaan kernel boleh menggunakan sock ini untuk menghantar paket. Tetapi satu ialah mod pengguna perlu mendaftarkan fungsi menerima paket, dan satu lagi ialah mod kernel masih perlu memasang skb untuk menghantar paket Ia masih terlalu rumit bagi saya yang hanya mahu bangun dengan pemberitahuan.
Jadi saya mencari lagi dan menemui artifak eventfd Antara komunikasi antara KVM dan Qemu, eventfd digunakan dengan hebat oleh Daniel Selepas menganalisis kod sumber dengan teliti, saya mendapati bahawa perkara ini adalah seperti namanya, semata-mata untuk pemberitahuan .
Sebagai fail (ada apa-apa dalam Linux yang bukan fail~~), struktur data_peribadi eventfd_ctx hanya mempunyai empat pembolehubah yang menyedihkan.
struct eventfd_ctx { struct kref kref; /* 这个就不多说了,file计数用的,用于get/put */ wait_queue_head_t wqh; /* 这个用来存放用户态的进程wait项,有了它通知机制才成为可能 */ /* \* Every time that a write(2) is performed on an eventfd, the \* value of the __u64 being written is added to "count" and a \* wakeup is performed on "wqh". A read(2) will return the "count" \* value to userspace, and will reset "count" to zero. The kernel \* side eventfd_signal() also, adds to the "count" counter and \* issue a wakeup. */ __u64 count; /* 这个就是一个技术器,应用程序可以自己看着办,read就是取出然后清空,write就是把value加上 */ unsigned int flags; /* 所有的file都有的吧,用来存放阻塞/非阻塞标识或是O_CLOEXEC之类的东西 */ }; 我之所以选用它是因为它有 eventfd_signal 这个特地为内核态提供的接口,下面的是注释。 \* This function is supposed to be called by the kernel in paths that do not \* allow sleeping. In this function we allow the counter to reach the ULLONG_MAX \* value, and we signal this as overflow condition by returining a POLLERR to poll(2).
Malah, akan lebih jelas jika anda melihat kod tersebut
int eventfd_signal(struct eventfd_ctx *ctx, int n) { unsigned long flags; if (n return -EINVAL; spin_lock_irqsave(&ctx->wqh.lock, flags); if (ULLONG_MAX - ctx->count count); ctx->count += n; if (waitqueue_active(&ctx->wqh)) wake_up_locked_poll(&ctx->wqh, POLLIN); spin_unlock_irqrestore(&ctx->wqh.lock, flags); return n; }
Intinya bangun sekali, tanpa membaca atau menulis Bezanya eventfd_write ialah tiada blocking
Ini penggunaan khusus saya:
Keadaan kernel ialah modul yang mendaftarkan peranti misc dan mencipta benang kernel untuk berfungsi (parameternya ialah fail modul->private_data). Sediakan antara muka ioctl untuk proses mod pengguna untuk menyampaikan fd yang dicipta oleh eventfdnya sendiri, dan simpan dalam fail->data_pribadi yang boleh diakses oleh utas kernel.
Apabila keadaan kernel ingin memberitahu keadaan pengguna, eventfd_signal digunakan secara langsung Pada masa ini, urutan keadaan pengguna perlu meletakkan dirinya pada eventfd_ctx->wqh Terdapat dua penyelesaian, satu ialah memanggil baca untuk memanggil tinjauan pendapat. Jika ia adalah bacaan, eventfd_ctx->count akan dikosongkan kemudian dan boleh disekat kali seterusnya. Walau bagaimanapun, jika tinjauan pendapat digunakan, kiraan tidak dibersihkan selepas itu, menyebabkan tinjauan pendapat kembali serta-merta walaupun tiada eventfd_signal dalam keadaan kernel semasa mengundi lagi.
Memaklumkan keadaan kernel dari keadaan pengguna adalah sedikit lebih menyusahkan Pertama, anda perlu membuat eventfd dan kemudian menghantarnya ke file->private_data (operasi di sini adalah sama seperti di atas). iotcl dalam modul, yang bertanggungjawab untuk keadaan pengguna untuk memberitahu keadaan kernel , eventfd_signal dilakukan dalam fungsi Benang keadaan kernel perlu diletakkan pada eventfd_ctx->wqh terlebih dahulu dalam keadaan kernel sendiri (nampaknya menyusahkan lagi).
Artikel ini memperkenalkan eventfd, artifak dalam Linux Ia adalah mekanisme komunikasi antara proses yang mudah, fleksibel dan cekap. Kami menganalisis penciptaan, membaca dan menulis, dan membenderakan bit eventfd dari aspek prinsip, dan memberikan contoh kod yang sepadan. Kami juga memperkenalkan penggunaan eventfd dalam senario seperti mod pengguna dan komunikasi mod kernel, pemasa dan pencetus peristiwa dari perspektif aplikasi, dan memberikan contoh kod yang sepadan. Melalui kajian artikel ini, kita boleh menguasai penggunaan asas eventfd, dan boleh menggunakan eventfd secara fleksibel dalam pembangunan sebenar untuk mencapai keperluan komunikasi yang berbeza. Semoga artikel ini dapat membantu anda!
Atas ialah kandungan terperinci Artifak dalam Linux: Prinsip dan Aplikasi eventfd. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!