0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

詳解linux內(nèi)核的uevent機(jī)制

嵌入式小生 ? 來源:嵌入式小生 ? 2024-09-29 17:01 ? 次閱讀

一、kobject_uevent簡(jiǎn)介

linux內(nèi)核中,uevent機(jī)制是一種內(nèi)核和用戶空間通信的機(jī)制,用于通知用戶空間應(yīng)用程序各種硬件更改或其他事件,比如插入或移除硬件設(shè)備(如USB驅(qū)動(dòng)器網(wǎng)絡(luò)接口)。uevent表示“用戶空間事件”,當(dāng)硬件事件發(fā)生時(shí),內(nèi)核會(huì)生成一個(gè) uevent,并通過 netlink 套接字將其發(fā)送到用戶空間。用戶空間應(yīng)用程序(例如 udev、mdev),可以監(jiān)聽這些事件并采取相應(yīng)的操作,例如加載適當(dāng)?shù)尿?qū)動(dòng)程序或執(zhí)行其他配置任務(wù)。

kobject_uevent()函數(shù)可通過發(fā)送一個(gè)uevent通知用戶空間:

intkobject_uevent(structkobject*kobj,enumkobject_actionaction)
{
returnkobject_uevent_env(kobj,action,NULL);
}

從上述代碼可知,kobject_uevent()調(diào)用kobject_uevent_env()實(shí)現(xiàn)核心操作,但是kobject_uevent()沒有傳輸環(huán)境變量,故而設(shè)置kobject_uevent_env()的第三個(gè)參數(shù)為NULL。

enum kobject_action用于描述內(nèi)核對(duì)象的操作,內(nèi)核中定義了以下幾種操作:

enumkobject_action{
KOBJ_ADD,//對(duì)象添加。表示向系統(tǒng)中添加了一個(gè)新的kobject對(duì)象。
KOBJ_REMOVE,//對(duì)象移除。表示從系統(tǒng)中移除了一個(gè)kobject對(duì)象。
KOBJ_CHANGE,//對(duì)象修改。表示kobject對(duì)象的屬性或狀態(tài)發(fā)生了變化。
KOBJ_MOVE,//對(duì)象移動(dòng)。表示kobject對(duì)象被移動(dòng)到了另一個(gè)位置。
KOBJ_ONLINE,//對(duì)象上線。表示kobject對(duì)象已經(jīng)準(zhǔn)備好在線工作。
KOBJ_OFFLINE,//對(duì)象離線。表示kobject對(duì)象已經(jīng)離線,不再處于工作狀態(tài)。
KOBJ_MAX//動(dòng)作類型的最大值,用于邊界檢查。
};

在用戶空間可使用udevadm monitor查看uevent事件:

udevadmmonitor--udev

二、重要數(shù)據(jù)結(jié)構(gòu)

1、struct kobj_uevent_env

struct kobj_uevent_env結(jié)構(gòu)的目的是在內(nèi)核中傳遞事件相關(guān)的參數(shù)、環(huán)境變量和數(shù)據(jù)。通過使用這個(gè)結(jié)構(gòu)體,內(nèi)核可以輕松地傳遞事件相關(guān)的信息和數(shù)據(jù)給相關(guān)的處理程序或模塊。

structkobj_uevent_env{
char*argv[3];//用于存儲(chǔ)傳遞給事件的參數(shù)。通常情況下,用于表示事件的命令行參數(shù)。
char*envp[UEVENT_NUM_ENVP];//這是一個(gè)包含UEVENT_NUM_ENVP個(gè)指針的數(shù)組,用于存儲(chǔ)傳遞給事件的環(huán)境變量。在Linux內(nèi)核中,環(huán)境變量通常以鍵值對(duì)的形式傳遞。
intenvp_idx;//用于跟蹤環(huán)境變量數(shù)組中的當(dāng)前索引。它指示下一個(gè)環(huán)境變量應(yīng)該存儲(chǔ)在數(shù)組的哪個(gè)位置。
charbuf[UEVENT_BUFFER_SIZE];//用于存儲(chǔ)事件的文本數(shù)據(jù)。在內(nèi)核中,事件通常以文本形式表示。
intbuflen;//用于跟蹤事件數(shù)據(jù)緩沖區(qū)中的當(dāng)前有效數(shù)據(jù)長度。它指示緩沖區(qū)中包含的事件數(shù)據(jù)量。
};

2、struct kset_uevent_ops

struct kset_uevent_ops結(jié)構(gòu)體定義了 kset 的事件操作接口,使得用戶可以通過提供相應(yīng)的函數(shù)指針來自定義 kset 中 kobject 的事件處理行為:

structkset_uevent_ops{
int(*constfilter)(structkset*kset,structkobject*kobj);
constchar*(*constname)(structkset*kset,structkobject*kobj);
int(*constuevent)(structkset*kset,structkobject*kobj,
structkobj_uevent_env*env);
};

int (_ const filter)(struct kset _kset, struct kobject *kobj);:這是一個(gè)指向函數(shù)的指針,該函數(shù)用于過濾 kset 中的 kobject(內(nèi)核對(duì)象)。它接受兩個(gè)參數(shù),分別是指向 kset 和 kobject 的指針,返回一個(gè)整數(shù)值,通常表示過濾操作的結(jié)果。

const char ( const name)(struct kset _kset, struct kobject _kobj);:這是一個(gè)指向函數(shù)的指針,該函數(shù)用于獲取 kobject 的名稱。它接受兩個(gè)參數(shù),分別是指向 kset 和 kobject 的指針,返回一個(gè)指向字符常量的指針,通常是 kobject 的名稱字符串。

int (_ const uevent)(struct kset _kset, struct kobject _kobj, struct kobj_uevent_env _env);:這是一個(gè)指向函數(shù)的指針,該函數(shù)用于生成 kobject 的事件。它接受三個(gè)參數(shù),分別是指向 kset、kobject 和 kobj_uevent_env 結(jié)構(gòu)體的指針。該函數(shù)負(fù)責(zé)將 kobject 的事件信息填充到給定的環(huán)境中,并返回一個(gè)整數(shù)值,通常表示操作的成功或失敗。

三、kobject_uevent_env()詳細(xì)剖析

kobject_uevent_env()用于在給定的 kobject 上觸發(fā)一個(gè)事件,并且傳遞一個(gè)額外的環(huán)境變量數(shù)組:

intkobject_uevent_env(structkobject*kobj,enumkobject_actionaction,char*envp_ext[])

struct kobject *kobj:表示要觸發(fā)事件的內(nèi)核對(duì)象。

enum kobject_action action:表示要執(zhí)行的動(dòng)作,通常是一個(gè)枚舉類型,定義了可能的動(dòng)作列表。這可能包括添加、刪除或修改對(duì)象等操作。

char *envp_ext[]:是一個(gè)字符指針數(shù)組,用于傳遞額外的環(huán)境變量給事件處理程序。這些環(huán)境變量以 key=value 的形式表示,其中 key 是環(huán)境變量的名稱,value 是其對(duì)應(yīng)的值。

該函數(shù)將會(huì)觸發(fā)一個(gè)事件,并將指定的動(dòng)作和環(huán)境變量信息傳遞給與該對(duì)象相關(guān)聯(lián)的事件處理程序。事件處理程序通常會(huì)根據(jù)傳入的動(dòng)作和環(huán)境變量來執(zhí)行相應(yīng)的操作,例如更新內(nèi)核狀態(tài)、通知用戶空間進(jìn)程等。kobject_uevent_env()實(shí)現(xiàn)如下(具體執(zhí)行步驟見注釋):

intkobject_uevent_env(structkobject*kobj,enumkobject_actionaction,
char*envp_ext[])
{
structkobj_uevent_env*env;
constchar*action_string=kobject_actions[action];
constchar*devpath=NULL;
constchar*subsystem;
structkobject*top_kobj;
structkset*kset;
conststructkset_uevent_ops*uevent_ops;
inti=0;
intretval=0;

/*
*Mark"remove"eventdoneregardlessofresult,forsomesubsystems
*donotwanttore-trigger"remove"eventviaautomaticcleanup.
*/
/如果動(dòng)作是KOBJ_REMOVE,則將對(duì)象的state_remove_uevent_sent標(biāo)志設(shè)置為1,表示“remove”事件已發(fā)送。
if(action==KOBJ_REMOVE)
kobj->state_remove_uevent_sent=1;

//打印調(diào)試信息,包括對(duì)象的名稱、指針和函數(shù)名稱。
pr_debug("kobject:'%s'(%p):%s
",
kobject_name(kobj),kobj,__func__);

//找該對(duì)象所屬的kset。
top_kobj=kobj;
while(!top_kobj->kset&&top_kobj->parent)
top_kobj=top_kobj->parent;

//如果對(duì)象不屬于任何kset,則返回錯(cuò)誤。
if(!top_kobj->kset){
pr_debug("kobject:'%s'(%p):%s:attemptedtosenduevent"
"withoutkset!
",kobject_name(kobj),kobj,
__func__);
return-EINVAL;
}

kset=top_kobj->kset;
uevent_ops=kset->uevent_ops;

//檢查對(duì)象的uevent_suppress標(biāo)志是否設(shè)置,如果設(shè)置了則跳過事件發(fā)送。
if(kobj->uevent_suppress){
pr_debug("kobject:'%s'(%p):%s:uevent_suppress"
"causedtheeventtodrop!
",
kobject_name(kobj),kobj,__func__);
return0;
}

//如果uevent_ops和uevent_ops->filter存在且filter函數(shù)返回0,則跳過事件發(fā)送。
if(uevent_ops&&uevent_ops->filter)
if(!uevent_ops->filter(kset,kobj)){
pr_debug("kobject:'%s'(%p):%s:filterfunction"
"causedtheeventtodrop!
",
kobject_name(kobj),kobj,__func__);
return0;
}

//獲取事件的子系統(tǒng)名稱。
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:unsetsubsystemcausedthe"
"eventtodrop!
",kobject_name(kobj),kobj,
__func__);
return0;
}

//分配并初始化一個(gè)kobj_uevent_env結(jié)構(gòu)體
env=kzalloc(sizeof(structkobj_uevent_env),GFP_KERNEL);
if(!env)
return-ENOMEM;

//獲取對(duì)象的路徑。
devpath=kobject_get_path(kobj,GFP_KERNEL);
if(!devpath){
retval=-ENOENT;
gotoexit;
}

//添加默認(rèn)的環(huán)境變量,包括動(dòng)作(ACTION)、設(shè)備路徑(DEVPATH)和子系統(tǒng)(SUBSYSTEM)。
retval=add_uevent_var(env,"ACTION=%s",action_string);
if(retval)
gotoexit;
retval=add_uevent_var(env,"DEVPATH=%s",devpath);
if(retval)
gotoexit;
retval=add_uevent_var(env,"SUBSYSTEM=%s",subsystem);
if(retval)
gotoexit;

//如果有傳入的額外環(huán)境變量,則將它們添加到事件環(huán)境中
if(envp_ext){
for(i=0;envp_ext[i];i++){
retval=add_uevent_var(env,"%s",envp_ext[i]);
if(retval)
gotoexit;
}
}

//調(diào)用uevent_ops->uevent函數(shù),如果存在,以允許kset特定的操作添加額外的環(huán)境變量。
if(uevent_ops&&uevent_ops->uevent){
retval=uevent_ops->uevent(kset,kobj,env);
if(retval){
pr_debug("kobject:'%s'(%p):%s:uevent()returned"
"%d
",kobject_name(kobj),kobj,
__func__,retval);
gotoexit;
}
}

//根據(jù)動(dòng)作執(zhí)行額外的操作。如果是KOBJ_ADD,則標(biāo)記對(duì)象已發(fā)送state_add_uevent_sent為1。
switch(action){
caseKOBJ_ADD:
/*
*Mark"add"eventsowecanmakesurewedeliver"remove"
*eventtouserspaceduringautomaticcleanup.If
*theobjectdidsendan"add"event,"remove"will
*automaticallygeneratedbythecore,ifnotalreadydone
*bythecaller.
*/
kobj->state_add_uevent_sent=1;
break;

caseKOBJ_UNBIND:
zap_modalias_env(env);
break;

default:
break;
}


mutex_lock(&uevent_sock_mutex);
/*wewillsendanevent,sorequestanewsequencenumber*/
//獲取一個(gè)新的序列號(hào)并將其添加到事件環(huán)境中
retval=add_uevent_var(env,"SEQNUM=%llu",++uevent_seqnum);
if(retval){
mutex_unlock(&uevent_sock_mutex);
gotoexit;
}

//通過網(wǎng)絡(luò)廣播發(fā)送事件。
retval=kobject_uevent_net_broadcast(kobj,env,action_string,
devpath);
mutex_unlock(&uevent_sock_mutex);

//如果配置了CONFIG_UEVENT_HELPER,則調(diào)用uevent_helper來執(zhí)行額外的操作。
#ifdefCONFIG_UEVENT_HELPER
/*calluevent_helper,usuallyonlyenabledduringearlyboot*/
if(uevent_helper[0]&&!kobj_usermode_filter(kobj)){
structsubprocess_info*info;

retval=add_uevent_var(env,"HOME=/");
if(retval)
gotoexit;
retval=add_uevent_var(env,
"PATH=/sbin:/bin:/usr/sbin:/usr/bin");
if(retval)
gotoexit;
retval=init_uevent_argv(env,subsystem);
if(retval)
gotoexit;

retval=-ENOMEM;
info=call_usermodehelper_setup(env->argv[0],env->argv,
env->envp,GFP_KERNEL,
NULL,cleanup_uevent_env,env);
if(info){
retval=call_usermodehelper_exec(info,UMH_NO_WAIT);
env=NULL;/*freedbycleanup_uevent_env*/
}
}
#endif

exit:
kfree(devpath);
kfree(env);
returnretval;
}

總而言之,kobject_uevent_env()調(diào)用add_uevent_var()構(gòu)建默認(rèn)的信息(包括:ACTION、DEVPATH、SUBSYSTEM和自定義數(shù)據(jù)envp_ext),然后調(diào)用kobject_uevent_net_broadcast()發(fā)送uevent。

1、add_uevent_var()

add_uevent_var()是一個(gè)用于在內(nèi)核中構(gòu)建uevent環(huán)境的輔助函數(shù),它允許向 uevent 環(huán)境中添加一個(gè)鍵值對(duì),表示內(nèi)核對(duì)象事件中的一個(gè)屬性或信息。該函數(shù)實(shí)現(xiàn)如下:

intadd_uevent_var(structkobj_uevent_env*env,constchar*format,...)
{
va_listargs;
intlen;

if(env->envp_idx>=ARRAY_SIZE(env->envp)){
WARN(1,KERN_ERR"add_uevent_var:toomanykeys
");
return-ENOMEM;
}

va_start(args,format);
len=vsnprintf(&env->buf[env->buflen],
sizeof(env->buf)-env->buflen,
format,args);
va_end(args);

if(len>=(sizeof(env->buf)-env->buflen)){
WARN(1,KERN_ERR"add_uevent_var:buffersizetoosmall
");
return-ENOMEM;
}

env->envp[env->envp_idx++]=&env->buf[env->buflen];
env->buflen+=len+1;
return0;
}

add_uevent_var()函數(shù)的作用是根據(jù)指定的格式將鍵值對(duì)添加到 uevent 環(huán)境中,該函數(shù)使用vsnprintf()函數(shù)將格式化字符串和參數(shù)組合成一個(gè)字符串,并將該字符串添加到 kobj_uevent_env 結(jié)構(gòu)體的緩沖區(qū)中,如果成功添加鍵值對(duì),則返回0;如果緩沖區(qū)空間不足導(dǎo)致添加失敗,則返回-ENOSPC。

使用add_uevent_var()函數(shù)可以方便地構(gòu)建uevent環(huán)境,向用戶空間發(fā)送有關(guān)內(nèi)核對(duì)象事件的信息。通常情況下,該函數(shù)用于在kobject_uevent_env()函數(shù)中構(gòu)建uevent環(huán)境,以向用戶空間發(fā)送內(nèi)核對(duì)象事件。

2、kobject_uevent_net_broadcast()

`kobject_uevent_net_broadcast()用于在網(wǎng)絡(luò)命名空間上廣播內(nèi)核對(duì)象事件:

intkobject_uevent_net_broadcast(structkobject*kobj,
structkobj_uevent_env*env,
constchar*action_string,
constchar*devpath)

(1)首先,它檢查是否啟用了網(wǎng)絡(luò)支持 (CONFIG_NET),因?yàn)檫@個(gè)功能是基于網(wǎng)絡(luò)命名空間的。

(2)它獲取與給定 kobject 相關(guān)聯(lián)的命名空間類型操作 (ops),以確定是否存在網(wǎng)絡(luò)命名空間。

(3)如果 ops 存在,且命名空間類型是網(wǎng)絡(luò)命名空間 (KOBJ_NS_TYPE_NET),則獲取該命名空間。

(4)如果存在網(wǎng)絡(luò)命名空間,它調(diào)用 uevent_net_broadcast_tagged 函數(shù),將事件廣播到指定的網(wǎng)絡(luò)命名空間。

(5)如果沒有找到網(wǎng)絡(luò)命名空間,或者網(wǎng)絡(luò)命名空間不支持事件廣播,它調(diào)用 uevent_net_broadcast_untagged 函數(shù),將事件廣播到所有未標(biāo)記的網(wǎng)絡(luò)命名空間。

(6)最后,它返回廣播函數(shù)的返回值,指示事件廣播的成功或失敗??偟膩碚f,這個(gè)函數(shù)負(fù)責(zé)根據(jù)對(duì)象的網(wǎng)絡(luò)命名空間屬性,將內(nèi)核對(duì)象事件廣播到適當(dāng)?shù)木W(wǎng)絡(luò)命名空間中。uevent_net_broadcast_tagged()和uevent_net_broadcast_untagged()本質(zhì)上都調(diào)用netlink_broadcast()實(shí)現(xiàn)核心功能。

3、call_usermodehelper_setup()

call_usermodehelper_setup 函數(shù)是 Linux 內(nèi)核中的一個(gè)函數(shù),用于設(shè)置和準(zhǔn)備調(diào)用用戶空間輔助程序(usermode helper)。這個(gè)函數(shù)并不直接執(zhí)行用戶空間輔助程序,而是為其設(shè)置參數(shù)和環(huán)境,并返回一個(gè) subprocess_info 結(jié)構(gòu)體,用于后續(xù)的執(zhí)行。

這個(gè)函數(shù)通常在內(nèi)核中的一些子系統(tǒng)中使用,例如 kobject_uevent_net_broadcast 中的調(diào)用。函數(shù)原型如下:

structsubprocess_info*call_usermodehelper_setup(char*path,char**argv,
char**envp,gfp_tgfp_mask,
int(*init)(structsubprocess_info*info,
structcred*new),
void(*cleanup)(structsubprocess_info*info),
void*data);

path:用戶空間輔助程序的路徑。

argv:參數(shù)數(shù)組,用于傳遞給用戶空間輔助程序的命令行參數(shù)。

envp:環(huán)境變量數(shù)組,用于傳遞給用戶空間輔助程序的環(huán)境變量。

gfp_mask:內(nèi)存分配標(biāo)志。

init:一個(gè)可選的初始化函數(shù),用于在用戶空間輔助程序執(zhí)行前進(jìn)行一些初始化操作。

cleanup:一個(gè)可選的清理函數(shù),用于在用戶空間輔助程序執(zhí)行完畢后進(jìn)行清理操作。

data:可選的附加數(shù)據(jù),可以在初始化和清理函數(shù)中使用。

這個(gè)函數(shù)的作用是為用戶空間輔助程序設(shè)置參數(shù)和環(huán)境,以及提供初始化和清理函數(shù)。返回的 subprocess_info 結(jié)構(gòu)體包含了執(zhí)行用戶空間輔助程序所需的所有信息,包括路徑、參數(shù)、環(huán)境等。一旦設(shè)置完成,用戶空間輔助程序就可以通過call_usermodehelper_exec 函數(shù)執(zhí)行。

4、call_usermodehelper_exec()

call_usermodehelper_exec 函數(shù)是 Linux 內(nèi)核中與執(zhí)行用戶空間輔助程序(usermode helper)相關(guān)的一個(gè)函數(shù)。它負(fù)責(zé)實(shí)際執(zhí)行用戶空間輔助程序,并監(jiān)控其執(zhí)行狀態(tài)。通常情況下,它會(huì)在 call_usermodehelper_setup 函數(shù)之后被調(diào)用。

下面是call_usermodehelper_exec 函數(shù)原型:

intcall_usermodehelper_exec(structsubprocess_info*sub_info,enumumh_waitwait);

sub_info:指向 subprocess_info 結(jié)構(gòu)體的指針,該結(jié)構(gòu)體包含了執(zhí)行用戶空間輔助程序所需的所有信息,包括路徑、參數(shù)、環(huán)境等。

wait:指定是否等待用戶空間輔助程序執(zhí)行完成的標(biāo)志,可以是 UMH_WAIT_EXEC(等待執(zhí)行完成)或 UMH_NO_WAIT(不等待執(zhí)行完成)。

call_usermodehelper_exec 函數(shù)的作用是執(zhí)行用戶空間輔助程序,并等待其執(zhí)行完成(如果需要)。在執(zhí)行期間,它會(huì)監(jiān)控用戶空間輔助程序的執(zhí)行狀態(tài),并在適當(dāng)?shù)臅r(shí)候返回執(zhí)行結(jié)果。

這個(gè)函數(shù)通常在 Linux 內(nèi)核中的一些子系統(tǒng)中使用,例如 kobject_uevent_net_broadcast 中的調(diào)用。通過調(diào)用用戶空間輔助程序,內(nèi)核可以執(zhí)行一些需要借助用戶空間程序完成的任務(wù),例如配置、初始化等。

四、uevent_helper機(jī)制

在 Linux 內(nèi)核中,uevent_helper 是一個(gè)用戶空間輔助程序,用于處理內(nèi)核對(duì)象事件(uevent)。它通常在內(nèi)核啟動(dòng)期間使用,負(fù)責(zé)處理設(shè)備管理相關(guān)的事件,例如設(shè)備的插入、拔出、狀態(tài)變化等。下面是一些使用uevent_helper的典型實(shí)踐:

設(shè)備熱插拔管理: 當(dāng)一個(gè)設(shè)備被插入或拔出時(shí),內(nèi)核會(huì)生成相應(yīng)的 uevent,并調(diào)用 uevent_helper 來處理這些事件。uevent_helper 可以根據(jù)事件類型執(zhí)行一些特定的操作,例如加載適當(dāng)?shù)脑O(shè)備驅(qū)動(dòng)、更新設(shè)備管理信息等。

自動(dòng)配置和初始化: 在系統(tǒng)啟動(dòng)期間,內(nèi)核可能需要執(zhí)行一些自動(dòng)配置和初始化任務(wù),例如掛載文件系統(tǒng)、加載網(wǎng)絡(luò)配置、啟動(dòng)服務(wù)等。uevent_helper 可以被用于執(zhí)行這些任務(wù),并根據(jù)事件類型執(zhí)行相應(yīng)的初始化操作。

系統(tǒng)監(jiān)控和管理: uevent_helper 還可以被用于系統(tǒng)監(jiān)控和管理任務(wù),例如記錄事件日志、生成警報(bào)、執(zhí)行故障排除操作等。

用戶空間通知: uevent_helper 還可以與用戶空間的其他程序進(jìn)行通信,例如向用戶空間的監(jiān)控程序發(fā)送通知或觸發(fā)相應(yīng)的操作。

具體使用 uevent_helper 的方式取決于系統(tǒng)的需求和設(shè)計(jì)。通常情況下,它會(huì)被配置為一個(gè)可執(zhí)行文件或腳本,并在系統(tǒng)啟動(dòng)時(shí)由內(nèi)核調(diào)用。在使用uevent_helper時(shí),需要確保其具有足夠的權(quán)限來執(zhí)行所需的操作,并確保其安全性和穩(wěn)定性。

五、mdev

mdev是Linux系統(tǒng)中用于設(shè)備管理的工具,具有以下特征:

mdev 是一個(gè)更輕量級(jí)的設(shè)備管理器,通常用于嵌入式系統(tǒng)和一些輕量級(jí) Linux 發(fā)行版中。

由 BusyBox 提供,并用于在啟動(dòng)時(shí)自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)。

mdev 不支持復(fù)雜的規(guī)則配置,而是基于簡(jiǎn)單的設(shè)備名匹配規(guī)則來創(chuàng)建設(shè)備節(jié)點(diǎn)。

所以綜上所述,mdev 更適用于嵌入式系統(tǒng)或者對(duì)資源有限的系統(tǒng),因?yàn)樗虞p量級(jí),但功能也更加有限。

參考busybox源碼,mdev實(shí)現(xiàn)如下:

intmdev_main(intargcUNUSED_PARAM,char**argv)
{
enum{
MDEV_OPT_SCAN=1<

上述代碼中,具體實(shí)現(xiàn)步驟如下:

使用位掩碼枚舉定義了幾個(gè)選項(xiàng)(MDEV_OPT_SCAN、MDEV_OPT_SYSLOG、MDEV_OPT_DAEMON、MDEV_OPT_FOREGROUND)。

初始化一些配置變量并設(shè)置環(huán)境(INIT_G()、bb_sanitize_stdio()、umask(0)、xchdir("/dev"))。

解析了命令行參數(shù),根據(jù)參數(shù)的不同執(zhí)行不同的操作,比如掃描設(shè)備、啟用系統(tǒng)日志、以守護(hù)進(jìn)程模式運(yùn)行等。

根據(jù)程序運(yùn)行的不同情況,執(zhí)行相應(yīng)的操作,比如進(jìn)行初始掃描、處理動(dòng)作等。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1361

    瀏覽量

    40191
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11213

    瀏覽量

    208736
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4286

    瀏覽量

    62335

原文標(biāo)題:linux設(shè)備驅(qū)動(dòng)模型(uevent)

文章出處:【微信號(hào):嵌入式小生,微信公眾號(hào):嵌入式小生】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    詳解linux內(nèi)核中的mutex同步機(jī)制

    linux內(nèi)核中,互斥量(mutex,即mutual exclusion)是一種保證串行化的睡眠鎖機(jī)制。和spinlock的語義類似,都是允許一個(gè)執(zhí)行線索進(jìn)入臨界區(qū),不同的是當(dāng)無法獲得鎖的時(shí)候
    的頭像 發(fā)表于 05-13 08:56 ?6737次閱讀
    <b class='flag-5'>詳解</b><b class='flag-5'>linux</b><b class='flag-5'>內(nèi)核</b>中的mutex同步<b class='flag-5'>機(jī)制</b>

    Linux內(nèi)核同步機(jī)制mutex詳解

    linux內(nèi)核中,互斥量mutex是一種保證CPU串行運(yùn)行的睡眠鎖機(jī)制。和spinlock類似,都是同一個(gè)時(shí)刻只有一個(gè)線程進(jìn)入臨界資源,不同的是,當(dāng)無法獲取鎖的時(shí)候,spinlock原地自旋,而mutex則是選擇掛起當(dāng)前線程,
    發(fā)表于 06-26 16:05 ?1028次閱讀

    Linux內(nèi)核地址映射模型與Linux內(nèi)核高端內(nèi)存詳解

    Linux 操作系統(tǒng)和驅(qū)動(dòng)程序運(yùn)行在內(nèi)核空間,應(yīng)用程序運(yùn)行在用戶空間,兩者不能簡(jiǎn)單地使用指針傳遞數(shù)據(jù),因?yàn)?b class='flag-5'>Linux使用的虛擬內(nèi)存機(jī)制,用戶空間的數(shù)據(jù)可能被換出,當(dāng)
    發(fā)表于 05-08 10:33 ?3437次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>地址映射模型與<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>高端內(nèi)存<b class='flag-5'>詳解</b>

    Linux內(nèi)核搶占和用戶搶占的概念和區(qū)別

    本文詳解Linux內(nèi)核搶占實(shí)現(xiàn)機(jī)制。首先介紹了內(nèi)核搶占和用戶搶占的概念和區(qū)別,接著分析了不可搶占內(nèi)核
    發(fā)表于 08-05 08:18

    詳解Linux內(nèi)核搶占實(shí)現(xiàn)機(jī)制

    本文詳解Linux內(nèi)核搶占實(shí)現(xiàn)機(jī)制。首先介紹了內(nèi)核搶占和用戶搶占的概念和區(qū)別,接著分析了不可搶占內(nèi)核
    發(fā)表于 08-06 06:16

    Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解:基于最新的Linux 4.0內(nèi)核

    Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解:基于最新的Linux 4.0內(nèi)核
    發(fā)表于 08-31 12:29

    Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解》第4章、Linux內(nèi)核模塊

    Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解》第4章、Linux內(nèi)核模塊
    發(fā)表于 10-27 14:15 ?0次下載
    《<b class='flag-5'>Linux</b>設(shè)備驅(qū)動(dòng)開發(fā)<b class='flag-5'>詳解</b>》第4章、<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>模塊

    linux內(nèi)核rcu機(jī)制詳解

    Linux內(nèi)核源碼當(dāng)中,關(guān)于RCU的文檔比較齊全,你可以在 /Documentation/RCU/ 目錄下找到這些文件。Paul E. McKenney 是內(nèi)核中RCU源碼的主要實(shí)現(xiàn)者,他也寫了很多RCU方面的文章。今天我們而主
    發(fā)表于 11-13 16:47 ?8744次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內(nèi)核</b>rcu<b class='flag-5'>機(jī)制</b><b class='flag-5'>詳解</b>

    linux內(nèi)核oom機(jī)制分析

    Linux 內(nèi)核有個(gè)機(jī)制叫OOM killer(Out-Of-Memory killer),該機(jī)制會(huì)監(jiān)控那些占用內(nèi)存過大,尤其是瞬間很快消耗大量?jī)?nèi)存的進(jìn)程,為了防止內(nèi)存耗盡而
    發(fā)表于 11-13 17:01 ?1278次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內(nèi)核</b>oom<b class='flag-5'>機(jī)制</b>分析

    linux內(nèi)核機(jī)制有哪些

    路徑(進(jìn)程)以交錯(cuò)的方式運(yùn)行。對(duì)于這些交錯(cuò)路徑執(zhí)行的內(nèi)核路徑,如不采取必要的同步措施,將會(huì)對(duì)一些關(guān)鍵數(shù)據(jù)結(jié)構(gòu)進(jìn)行交錯(cuò)訪問和修改,從而導(dǎo)致這些數(shù)據(jù)結(jié)構(gòu)狀態(tài)的不一致,進(jìn)而導(dǎo)致系統(tǒng)崩潰。因此,為了確保系統(tǒng)高效穩(wěn)定有序地運(yùn)行,linux必須要采用同步
    發(fā)表于 11-14 15:25 ?5534次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內(nèi)核</b><b class='flag-5'>機(jī)制</b>有哪些

    你了解過Linux內(nèi)核中的Device Mapper 機(jī)制

    Device mapper 是 Linux 2.6 內(nèi)核中提供的一種從邏輯設(shè)備到物理設(shè)備的映射框架機(jī)制,在該機(jī)制下,用戶可以很方便的根據(jù)自己的需要制定實(shí)現(xiàn)存儲(chǔ)資源的管理策略,當(dāng)前比較流
    發(fā)表于 04-29 15:25 ?736次閱讀

    可以了解并學(xué)習(xí)Linux 內(nèi)核的同步機(jī)制

    Linux內(nèi)核同步機(jī)制,挺復(fù)雜的一個(gè)東西,常用的有自旋鎖,信號(hào)量,互斥體,原子操作,順序鎖,RCU,內(nèi)存屏障等。
    發(fā)表于 05-14 14:10 ?681次閱讀

    Linux內(nèi)核GPIO操作函數(shù)的詳解分析

    本文檔的主要內(nèi)容詳細(xì)介紹的是Linux內(nèi)核GPIO操作函數(shù)的詳解分析免費(fèi)下載。
    發(fā)表于 01-22 16:58 ?28次下載

    Linux內(nèi)核文件Cache機(jī)制

    Linux內(nèi)核文件Cache機(jī)制(開關(guān)電源技術(shù)與設(shè)計(jì) 第二版)-Linux內(nèi)核文件Cache機(jī)制
    發(fā)表于 08-31 16:34 ?4次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>文件Cache<b class='flag-5'>機(jī)制</b>

    Linux內(nèi)核中的頁面分配機(jī)制

    Linux內(nèi)核中是如何分配出頁面的,如果我們站在CPU的角度去看這個(gè)問題,CPU能分配出來的頁面是以物理頁面為單位的。也就是我們計(jì)算機(jī)中常講的分頁機(jī)制。本文就看下Linux
    的頭像 發(fā)表于 08-07 15:51 ?216次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>中的頁面分配<b class='flag-5'>機(jī)制</b>