ev_loop_fork函數

?libev監視器介紹:libev監視器用法-CSDN博客

libev loop對象介紹:loop對象-CSDN博客

libev ev_loop_fork函數介紹:ev_loop_fork函數-CSDN博客

libev API吐血整理:https://download.csdn.net/download/qq_39466755/90794251?spm=1001.2014.3001.5503

用于解決fork函數導致子進程集成的fd集合失效問題

#include <stdio.h>
#include <unistd.h>
#include <sys/event.h>
#include <fcntl.h>void child_process(int kq) {printf("Child: Attempting to use inherited kqueue...\n");struct kevent events[1];int n = kevent(kq, NULL, 0, events, 1, NULL); // 無超時等待printf("Child: kevent returned %d events (expected: 1)\n", n);
}int main() {int kq = kqueue();int pipe_fd[2];pipe(pipe_fd);// 監控管道讀端struct kevent ev;EV_SET(&ev, pipe_fd[0], EVFILT_READ, EV_ADD, 0, 0, NULL);kevent(kq, &ev, 1, NULL, 0, NULL);// 觸發事件write(pipe_fd[1], "test", 5);pid_t pid = fork();if (pid == 0) {child_process(kq); // 子進程直接使用繼承的 kqueue_exit(0);} else {struct kevent events[1];int n = kevent(kq, NULL, 0, events, 1, NULL);printf("Parent: kevent returned %d events\n", n);}return 0;
}

運行結果

Child: Attempting to use inherited kqueue...
Child: kevent returned 0 events (expected: 1)  # 子進程事件丟失!
Parent: kevent returned 1 events               # 父進程正常

修改代碼子進程可以正常接收父進程的fd集合

#include <ev.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>// 管道讀端回調
static void pipe_cb(struct ev_loop *loop, ev_io *w, int revents) {char buf[256];ssize_t n = read(w->fd, buf, sizeof(buf));printf("[%s] Received data: %.*s\n", getpid() == getppid() ? "Parent" : "Child", (int)n, buf);
}int main() {// 忽略 SIGPIPE(防止寫入關閉的管道導致進程退出)signal(SIGPIPE, SIG_IGN);struct ev_loop *loop = EV_DEFAULT;int pipe_fd[2];pipe(pipe_fd);// 監控管道讀端ev_io pipe_watcher;ev_io_init(&pipe_watcher, pipe_cb, pipe_fd[0], EV_READ);ev_io_start(loop, &pipe_watcher);// 寫入數據(觸發事件)write(pipe_fd[1], "hello", 6);pid_t pid = fork();if (pid == 0) {// ---------- 關鍵修復 ----------ev_loop_fork(loop);  // 重置內核狀態// ------------------------------printf("Child: Started event loop\n");ev_run(loop, 0);  // 子進程現在能正常接收事件_exit(0);} else {printf("Parent: Started event loop\n");ev_run(loop, 0);}return 0;
}

運行結果

Parent: Started event loop
[Parent] Received data: hello  # 父進程正常接收
Child: Started event loop
[Child] Received data: hello   # 子進程修復后也能接收

結合libev接口,父子進程共享循環時的正確用法

struct ev_loop *loop = EV_DEFAULT;
ev_io parent_watcher;
ev_io_init(&parent_watcher, parent_cb, pipe_fd[0], EV_READ);
ev_io_start(loop, &parent_watcher);pid_t pid = fork();
if (pid == 0) {// 子進程ev_loop_fork(loop);  // 先重置后端// 添加子進程獨有的監視器ev_io child_watcher;ev_io_init(&child_watcher, child_cb, another_fd, EV_WRITE);ev_io_start(loop, &child_watcher);ev_run(loop, 0);  // 現在能正確處理父/子監視器的事件
} else {// 父進程繼續原邏輯ev_run(loop, 0);
}

代碼解析:

????????libev 使用底層機制(如 epoll/kqueue)來監聽文件描述符。當調用 fork() 時,子進程會繼承父進程的 epoll 實例,但該實例可能已失效(內核狀態與用戶態不一致)。ev_loop_fork() 會重建后端(如重新創建 epoll 實例),確保事件循環在子進程中能正常工作。因為struct ev_loop *loop = EV_DEFAULT;已經創建了底層的事件監聽機制(如 epoll、kqueue 或 select 等,具體取決于系統支持)。

????????即使子進程不直接使用 pipe_fd[0],事件循環本身仍需正確的后端支持。

????????雖然子進程沒有主動使用 parent_watcher(監視 pipe_fd[0]),但該監視器仍存在于 loop 中(因為它是父進程注冊的)。未重置的事件循環可能會錯誤地嘗試處理這些繼承的監視器,導致未定義行為。

????????一般情況下都是搭配libev開源庫的API函數(ev_fork_init,ev_fork_start等)一起使用:

#include <ev.h>
#include <unistd.h>
#include <stdio.h>// fork 回調函數
void fork_cb(EV_P_ ev_fork *w, int revents) {printf("Child process (PID: %d) reinitializing event loop...\n", getpid());ev_loop_fork(EV_A); // 必須調用,重新初始化子進程的事件循環
}int main() {struct ev_loop *loop = EV_DEFAULT;struct ev_fork fork_watcher;// 初始化fork監視器ev_fork_init(&fork_watcher, fork_cb);ev_fork_start(loop, &fork_watcher); // 啟動監視器printf("Parent process (PID: %d) started. Forking...\n", getpid());pid_t pid = fork();if (pid == 0) {// 子進程:ev_loop_fork已在回調中調用ev_run(loop, 0); // 子進程事件循環} else if (pid > 0) {// 父進程代碼printf("Parent process continues (child PID: %d)\n", pid);sleep(2); // 模擬父進程工作} else {perror("fork failed");return 1;}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/79608.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/79608.shtml
英文地址,請注明出處:http://en.pswp.cn/web/79608.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【PostgreSQL數據分析實戰:從數據清洗到可視化全流程】金融風控分析案例-10.1 風險數據清洗與特征工程

&#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 文章大綱 PostgreSQL金融風控分析案例&#xff1a;風險數據清洗與特征工程實戰一、案例背景&#xff1a;金融風控數據處理需求二、風險數據清洗實戰&#xff08;一&#xff09;缺失值…

OpenCV 的 CUDA 模塊中用于將一個多通道 GpuMat 圖像拆分成多個單通道圖像的函數split()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 cv::cuda::split 是 OpenCV CUDA 模塊中的一個函數&#xff0c;用于將一個多通道的 GpuMat 圖像拆分成多個單通道的 GpuMat 圖像。這個函數是 CP…

【WebRTC-13】是在哪,什么時候,創建編解碼器?

Android-RTC系列軟重啟&#xff0c;改變以往細讀源代碼的方式 改為 帶上實際問題分析代碼。增加實用性&#xff0c;方便形成肌肉記憶。同時不分種類、不分難易程度&#xff0c;在線征集問題切入點。 問題&#xff1a;編解碼器的關鍵實體類是什么&#xff1f;在哪里&什么時候…

c語言第一個小游戲:貪吃蛇小游戲03

我們為貪吃蛇的節點設置為一個結構體&#xff0c;構成貪吃蛇的身子的話我們使用鏈表&#xff0c;鏈表的每一個節點是一個結構體 顯示貪吃蛇身子的一個節點 我們這邊node就表示一個蛇的身體 就是一小節 輸出結果如下 顯示貪吃蛇完整身子 效果如下 代碼實現 這個hasSnakeNode(…

架構思維:通用架構模式_系統監控的設計

文章目錄 引言什么是監控三大常見監控類型1. 次數監控2. 性能監控3. 可用率監控 落地監控1. 服務入口2. 服務內部3. 服務依賴 監控時間間隔的取舍小結 引言 架構思維&#xff1a;通用架構模式_從設計到代碼構建穩如磐石的系統 架構思維&#xff1a;通用架構模式_穩如老狗的SDK…

精益數據分析(46/126):深入剖析用戶生成內容(UGC)商業模式

精益數據分析&#xff08;46/126&#xff09;&#xff1a;深入剖析用戶生成內容&#xff08;UGC&#xff09;商業模式 在創業與數據分析的征程中&#xff0c;每一種商業模式都蘊含著獨特的價值與挑戰。今天&#xff0c;我們依舊懷揣著共同進步的信念&#xff0c;深入研讀《精益…

QMK鍵盤固件中LED鎖定指示燈的配置與使用詳解(實操部分+拓展)

QMK鍵盤固件中LED鎖定指示燈的配置與使用詳解 大家好!今天就跟大家一起探索QMK固件中LED鎖定指示燈的配置與使用。無論你是鍵盤DIY新手還是老司機,相信這篇教程都能幫你解鎖新技能! 一、基礎配置:定義LED引腳 在QMK固件中配置LED鎖定指示燈非常簡單,只需在config.h文件…

CVE體系若消亡將如何影響網絡安全防御格局

CVE體系的核心價值與當前危機 由MITRE運營的通用漏洞披露&#xff08;CVE&#xff09;項目的重要性不容低估。25年來&#xff0c;它始終是網絡安全專業人員理解和緩解安全漏洞的基準參照系。通過提供標準化的漏洞命名與分類方法&#xff0c;這套體系為防御者建立了理解、優先級…

一周學完計算機網絡之三:1、數據鏈路層概述

簡單的概述 數據鏈路層是計算機網絡體系結構中的第二層&#xff0c;它在物理層提供的基本服務基礎上&#xff0c;負責將數據從一個節點可靠地傳輸到相鄰節點。可以將其想象成一個負責在兩個相鄰的網絡設備之間進行數據 “搬運” 和 “整理” 的 “快遞中轉站”。 幾個重要概念…

?WordToCard使用分享?

https://www.wordtocard.com 家人們&#xff0c;今天發現了一個超好用的工具——WordToCard&#xff01;&#x1f61c; 它可以把WordToCard文檔轉換成漂亮的知識卡片&#xff0c;學習筆記、知識整理和內容分享都變得超輕松&#xff5e;&#x1f917; 支持各種WordToCard語法…

擴展:React 項目執行 yarn eject 后的 package.json 變化詳解及參數解析

擴展&#xff1a;React 項目執行 yarn eject 后的 package.json 變化詳解及參數解析 什么是 yarn eject&#xff1f;React 項目執行 yarn eject 后的 package.json 變化詳解1. 腳本部分 Scripts 被替換2. 新增構建依賴 dependencies&#xff08;部分&#xff09;3. 新增 Babel …

[Java實戰]Spring Boot 整合 Redis(十八)

[Java實戰]Spring Boot 整合 Redis&#xff08;十八&#xff09; 在現代的分布式應用開發中&#xff0c;Redis 作為一種高性能的鍵值存儲數據庫&#xff0c;被廣泛用于緩存、消息隊列、排行榜等多種場景。Spring Boot 提供了強大的支持&#xff0c;使得整合 Redis 變得非常簡單…

【氮化鎵】GaN在不同電子能量損失的SHI輻射下的損傷

該文的主要發現和結論如下: GaN的再結晶特性 :GaN在離子撞擊區域具有較高的再結晶傾向,這導致其形成永久損傷的閾值較高。在所有研究的電子能量損失 regime 下,GaN都表現出這種傾向,但在電子能量損失增加時,其效率會降低,尤其是在材料發生解離并形成N?氣泡時。 能量損失…

R語言實戰第5章(1)

第一部分&#xff1a;數學、統計和字符處理函數 數學和統計函數&#xff1a;R提供了豐富的數學和統計函數&#xff0c;用于執行各種計算和分析。這些函數可以幫助用戶快速完成復雜的數學運算、統計分析等任務&#xff0c;例如計算均值、方差、相關系數、進行假設檢驗等。字符處…

k8s術語之Horizontal Pod Autoscaling

應用的資源使用率通常都有高峰和低谷的時候&#xff0c;如何削峰填谷&#xff0c;提高整體的整體資源利用率&#xff0c;讓service中的Pod個數自動調整呢&#xff1f;Horizontal Pod Autoscaling:使pod水平自動縮放。這個Object也是最能體現kubernetes之于傳統運維價值的地方&a…

Linux復習筆記(三) 網絡服務配置(web)

遇到的問題&#xff0c;都有解決方案&#xff0c;希望我的博客能為你提供一點幫助。 二、網絡服務配置 2.3 web服務配置 2.3.1通信基礎&#xff1a;HTTP協議與C/S架構&#xff08;了解&#xff09; ??HTTP協議的核心作用?? Web服務基于HTTP/HTTPS協議實現客戶端&#xff…

9.1.領域驅動設計

目錄 一、領域驅動設計核心哲學 戰略設計與戰術設計的分野 ? 戰略設計&#xff1a;限界上下文&#xff08;Bounded Context&#xff09;與上下文映射&#xff08;Context Mapping&#xff09; ? 戰術設計&#xff1a;實體、值對象、聚合根、領域服務的構建原則 統一語言&am…

CSS Layer 詳解

CSS Layer 詳解 前言 最近在整理CSS知識體系時&#xff0c;發現Layer這個特性特別有意思。它就像是給樣式規則提供了一個專屬的「VIP通道」&#xff0c;讓我們能更優雅地解決樣式沖突問題。今天我就用最通俗的語言&#xff0c;帶大家全面了解這個CSS新特性。 什么是CSS Laye…

【Dv3Admin】工具視圖配置文件解析

在開發后臺管理系統時,處理復雜的 CRUD 操作是常見的需求。Django Rest Framework(DRF)通過 ModelViewSet 提供了基礎的增刪改查功能,但在實際應用中,往往需要擴展更多的功能,如批量操作、權限控制、查詢優化等。dvadmin/utils/viewset.py 模塊通過繼承并擴展 ModelViewS…

?云原生CAE軟件

?云原生CAE軟件?是一種在設計和實現時就充分考慮了云環境特點的軟件&#xff0c;能夠充分利用云資源&#xff0c;實現高效、可擴展和靈活的仿真分析。 定義和特點 云原生CAE軟件是一種在云端構建和運行的CAE&#xff08;Computer Aided Engineering&#xff0c;計算機輔助工…