linux核心kobject事件處理詳解
/*所有事件的名稱列表*/ static const char *kobject_actions[] = { [KOBJ_ADD] = "add", [KOBJ_REMOVE] = "remove", [KOBJ_CHANGE] = "change", [KOBJ_MOVE] = "move", [KOBJ_ONLINE] = "online", [KOBJ_OFFLINE] = "offline", }; /*用於事件處理的函式列表*/ struct kset_uevent_ops { /*事件過濾器,返回0表示不用向用戶空間報告事件*/ int (* const filter)(struct kset *kset, struct kobject *kobj); /*返回子系統的名字*/ const char *(* const name)(struct kset *kset, struct kobject *kobj); /*新增子系統特有的環境變數*/ int (* const uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env); } /*核心表示的環境*/ struct kobj_uevent_env { //環境變數/值陣列 char *envp[UEVENT_NUM_ENVP]; //當前環境變數值索引 int envp_idx; //環境資料緩衝區 char buf[UEVENT_BUFFER_SIZE]; //環境資料緩衝區的長度 int buflen; }; /** * kobject_uevent_env - send an uevent with environmental data * * @action: action that is happening * @kobj: struct kobject that the action is happening to * @envp_ext: pointer to environmental data * * Returns 0 if kobject_uevent() is completed with success or the * corresponding error when it fails. */ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp_ext[]) { struct kobj_uevent_env *env; //獲得事件的名稱 const char *action_string = kobject_actions[action]; const char *devpath = NULL; const char *subsystem; struct kobject *top_kobj; struct kset *kset; const struct kset_uevent_ops *uevent_ops; u64 seq; int i = 0; int retval = 0; pr_debug("kobject: '%s' (%p): %s\n", kobject_name(kobj), kobj, __func__); /* search the kset we belong to */ /*向上尋找所屬的kset*/ top_kobj = kobj; while (!top_kobj->kset && top_kobj->parent) top_kobj = top_kobj->parent; if (!top_kobj->kset) { pr_debug("kobject: '%s' (%p): %s: attempted to send uevent " "without kset!\n", kobject_name(kobj), kobj, __func__); return -EINVAL; } /*找到了kset獲得事件處理列表*/ kset = top_kobj->kset; uevent_ops = kset->uevent_ops; /* skip the event, if uevent_suppress is set*/ /*事件被抑制*/ if (kobj->uevent_suppress) { pr_debug("kobject: '%s' (%p): %s: uevent_suppress " "caused the event to drop!\n", kobject_name(kobj), kobj, __func__); return 0; } /* skip the event, if the filter returns zero. */ /*事件被過濾掉*/ if (uevent_ops && uevent_ops->filter) if (!uevent_ops->filter(kset, kobj)) { pr_debug("kobject: '%s' (%p): %s: filter function " "caused the event to drop!\n", kobject_name(kobj), kobj, __func__); return 0; } /* originating subsystem */ /*獲得當前子系統的名字*/ if (uevent_ops && uevent_ops->name) subsystem = uevent_ops->name(kset, kobj); else subsystem = kobject_name(&kset->kobj); /*無法獲得子系統的名字*/ if (!subsystem) { pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the " "event to drop!\n", kobject_name(kobj), kobj, __func__); return 0; } /* environment buffer */ env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); if (!env) return -ENOMEM; /* complete object path */ /*獲得kobject的路徑*/ devpath = kobject_get_path(kobj, GFP_KERNEL); if (!devpath) { retval = -ENOENT; goto exit; } /* default keys */ /*來,開始新增環境變數/值對*/ retval = add_uevent_var(env, "ACTION=%s", action_string); if (retval) goto exit; retval = add_uevent_var(env, "DEVPATH=%s", devpath); if (retval) goto exit; retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem); if (retval) goto exit; /* keys passed in from the caller */ if (envp_ext) { for (i = 0; envp_ext[i]; i++) { retval = add_uevent_var(env, "%s", envp_ext[i]); if (retval) goto exit; } } /* let the kset specific function add its stuff */ /*新增外部環境變數*/ if (uevent_ops && uevent_ops->uevent) { retval = uevent_ops->uevent(kset, kobj, env); if (retval) { pr_debug("kobject: '%s' (%p): %s: uevent() returned " "%d\n", kobject_name(kobj), kobj, __func__, retval); goto exit; } } /* * Mark "add" and "remove" events in the object to ensure proper * events to userspace during automatic cleanup. If the object did * send an "add" event, "remove" will automatically generated by * the core, if not already done by the caller. */ /*新增標記啊*/ if (action == KOBJ_ADD) kobj->state_add_uevent_sent = 1; else if (action == KOBJ_REMOVE) kobj->state_remove_uevent_sent = 1; /* we will send an event, so request a new sequence number */ /*來一個序列號,正版無憂*/ spin_lock(&sequence_lock); seq = ++uevent_seqnum; spin_unlock(&sequence_lock); retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); if (retval) goto exit; //來,使用netlink機制,廣播到到使用者空間 #if defined(CONFIG_NET) /* send netlink message */ if (uevent_sock) { struct sk_buff *skb; size_t len; /* allocate message with the maximum possible size */ len = strlen(action_string) + strlen(devpath) + 2; skb = alloc_skb(len + env->buflen, GFP_KERNEL); if (skb) { char *scratch; /* add header */ scratch = skb_put(skb, len); sprintf(scratch, "%
[email protected]%s", action_string, devpath); /* copy keys to our continuous event payload buffer */ for (i = 0; i < env->envp_idx; i++) { len = strlen(env->envp[i]) + 1; scratch = skb_put(skb, len); strcpy(scratch, env->envp[i]); } NETLINK_CB(skb).dst_group = 1; retval = netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL); /* ENOBUFS should be handled in userspace */ if (retval == -ENOBUFS) retval = 0; } else retval = -ENOMEM; } #endif /* call uevent_helper, usually only enabled during early boot */ if (uevent_helper[0]) { char *argv [3]; argv [0] = uevent_helper; argv [1] = (char *)subsystem; argv [2] = NULL; retval = add_uevent_var(env, "HOME=/"); if (retval) goto exit; retval = add_uevent_var(env, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); if (retval) goto exit; retval = call_usermodehelper(argv[0], argv, env->envp, UMH_WAIT_EXEC); } exit: kfree(devpath); kfree(env); return retval; }
相關推薦
linux核心kobject事件處理詳解
/*所有事件的名稱列表*/ static const char *kobject_actions[] = { [KOBJ_ADD] = "add", [KOBJ_REMOVE] = "remove", [KOBJ_CHANGE] = "change", [KO
可能是最詳細的Android點選事件處理詳解(三)
前兩篇文章: 可能是最詳細的Android點選事件處理詳解 可能是最詳細的Android點選事件處理詳解(二) 這裡再次延伸一下,在ScrollView和RecyclerView巢狀中touch事件的傳遞過程,以及巢狀滑動衝突的問題。 如上圖,外層是一個Neste
可能是最詳細的Android點選事件處理詳解(二)
上一篇我們主要詳細描述了touch事件在各層的傳遞 本篇文章主要是對比touch在不可滾動和可滾動的ViewGroup事件的傳遞過程 如上圖: - 左圖:是ViewGroup巢狀View,不可滑動 - 右圖:也是ViewGroup(RecyclerView)巢
可能是最詳細的Android點選事件處理詳解
面試的時候,很多時候都會問到Touch事件的傳遞,而且問法角度都有所不同,但是還是會遵循基本的事件傳遞規則的,可能他問的你沒處理過,但是根據基本規則慢慢思考來回答,都不會錯。 一,簡介 首先我們知道touch事件 主要是是在三個方法中傳遞和處理的。分別是:
Linux核心Power_Management之suspend詳解
1.Linux核心的suspend狀態 Linux核心支援多種型別睡眠狀態,目前存在四種模式:suspend to idle(freeze)、power-on standby(standb)、suspend to ram(memory;STR)和suspend to dis
Linux核心原始碼目錄結構詳解
3.1 Linux核心原始碼目錄如下: /arch:目錄包括了所有和體系結構相關的核心程式碼。它下面的每一個子目錄都代表一種Linux支援的體系結構,例如i386就是Intel
Linux核心模組(驅動)編譯詳解
本文主要說說如何編譯自己開發的核心模組。由於驅動通常也被編譯成核心模組,因此文章的內容也適用於驅動的編譯。 由於在下能力相當有限,有不當之處,還望大家批評指正^_^ 一、準備工作 準備工作如何做,
Linux核心的Oops問題詳解
參考:Linux: How To Locate An Oops 什麼是Oops?從語言學的角度說,Oops應該是一個擬聲詞。當出了點小事故,或者做了比較尷尬的事之後,你可以說"Oops",翻譯成中國話就叫做“哎呦”。“哎呦,對不起,對不起,我真不是故意打碎
編譯U-boot和Linux核心的步驟和詳解
1、準備材料 linux核心和uboot的原始碼包—- 6818GEC.tar.gz 環境:VMware12.0 Ubuntu16.04(64位) (1)先將 6818GEC.tar.gz 放在Ubuntu的共享目錄下,然後將 68
linux核心之程序管理詳解
1、程序描述符 (1)程序與執行緒 程序是處於執行期的程式以及相關資源的總稱。執行緒在linux上稱為輕量級程序,沒有獨立的地址空間,一個程序下的所有執行緒共享地址空間、檔案系統資源、檔案描述符、訊號處理程式等。 (2)程序描述符task_struct
React-事件處理詳解
對於使用者介面而言,展示只佔整體設計因素的一半,另一半則是相應使用者輸入,即通過JavaScript處理使用者產生的事件。 React通過將事件處理器 繫結到組建上處理事件,事件觸發的同時更新組建的內部狀態,內部狀態更新會觸發元件的重繪。因此,如果檢視層想要渲染出事件出發後
android 開發 View _14 MotionEvent和事件處理詳解,與實踐自定義滑動條View
MotionEvent MotionEvent物件是與使用者觸控相關的時間序列,該序列從使用者首次觸控式螢幕幕開始,經歷手指在螢幕表面的任何移動,直到手指離開螢幕時結束。手指的初次觸控(ACTION_DOWN操作),滑動(ACTION_MOVE操作)和擡起(ACTION
Android熱插拔事件處理詳解
整個過程從Kernel檢測到SD卡插入事件開始,之前的一些硬體中斷的觸發以及driver的載入這裡並不敘述,一直到SD卡掛載訊息更新到“Android——系統設定——儲存”一項中。 1. Kernel發出SD卡插入uevent。 2. Netlink
Linux核心之定時器詳解
static struct pin_desc *irq_pd; /* 鍵值: 按下時, 0x01, 0x02, 0x03, 0x04 */ /* 鍵值: 鬆開時, 0x81, 0x82, 0x83, 0x84 */ static unsigned char key_val; struct pin_desc{u
Linux核心模組程式設計與核心模組LICENSE -《詳解(第3版)》預讀
Linux核心模組簡介Linux核心的整體結構已經非常龐大,而其包含的元件也非常多。我們怎樣把需要的部分都包含在核心中呢?一種方法是把所有需要的功能都編譯到Linux核心。這會導致兩個問題,一是生成的核心會很大,二是如果我們要在現有的核心中新增或刪除功能,將不得不重新編譯核心
Linux kernel核心編譯配置選項詳解
Code maturity level options 程式碼成熟度選項 Prompt for development and/or incomplete code/drivers 顯示尚在開發中或尚未完成的程式碼與驅動.除非你是測試人員或者開發者,否則請勿選擇 G
Elasticsearch基本概念及核心配置文件詳解
last log4j 強烈 內存 文檔 size oca 機制 集群 Elasticsearch5.X,下列的是Elasticsearch2.X系類配置,其實很多配置都是相互兼容的 1. 配置文件 config/elasticsearch.yml 主配置文件
Linux的SOCKET編程詳解(轉)
readv lose 服務 網絡字節序 返回值 quest avi 取數 key Linux的SOCKET編程詳解 1. 網絡中進程之間如何通信 進 程通信的概念最初來源於單機系統。由於每個進程都在自己的地址範圍內運行,為保證兩個相互通信的進 程之間既互不幹擾又
Linux基礎命令(之一)詳解
linux 基礎命令 Linux基礎命令(之一)詳解學習linux的朋友都知道,系統大多數操作都是命令行的操作方式,當然如今也有圖形化界面的操作方式,但是多數情況下仍然使用命令的操作模式,所以命令的作用與用法是成為學好、學會Linux系統的必備前提,也是重點之一,所以今天來聊一聊一些基礎命令的用法與其
springmvc請求處理詳解
控制器 接口 Spring Web MVC 處理的大致過程: 一旦到來,DispatcherSevlet將負責將請求分發。DispatcherServlet可以認為是Spring提供的前端控制器,所有的請求都有經過它來統一分發。 在DispatcherServlet將請求分發給Spring Contr