Linux Kernel Lecture Hall (1) cornerstone Driver Model for device drivers (2)

Source: Internet
Author: User

For more information, see http://blog.csdn.net/z2007b. do not use this document for commercial purposes. The copyright is owned by the Wuwei monk.

In the previous section, we analyzed the kobject_add_internal (& K-> kobj) in the int kset_register (struct kset * k) function. Next, we will analyze it to arouse your memory, the kset_register function is defined as follows:
Int kset_register (struct kset * K)
{
Int err;

If (! K)
Return-einval;

Kset_init (k );
Err = kobject_add_internal (& K-> kobj );
If (ERR)
Return err;
Kobject_uevent (& K-> kobj, kobj_add );
Return 0;
}
Next we need to analyze kobject_uevent (& K-> kobj, kobj_add), which is used to tell the user space that a new friend is coming and what is his name. Let's see how it works.
Int kobject_uevent (struct kobject * kobj, Enum kobject_action action)
{
Return kobject_uevent_env (kobj, action, null );
}
There is a function in it:
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;
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 */
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 = 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"
"Event to drop! /N ", kobject_name (kobj), kobj,
_ FUNC __);
Return 0;
}

/* Environment buffer */
ENV = kzarloc (sizeof (struct kobj_uevent_env), gfp_kernel );
If (! ENV)
Return-enomem;

/* Complete object path */
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
* 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) SEQ );
If (retval)
Goto exit;

# 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, "% s @ % 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 shoshould 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;
}
After initialization, we finally called the call_usermodehelper function.
Static inline int
Call_usermodehelper (char * path, char ** argv, char ** envp, Enum umh_wait wait)
{
Struct subprocess_info * Info;
Gfp_t gfp_mask = (wait = umh_no_wait )? Gfp_atomic: gfp_kernel;

Info = call_usermodehelper_setup (path, argv, envp, gfp_mask );
If (Info = NULL)
Return-enomem;
Return call_usermodehelper_exec (Info, wait );
}
Based on the programming experience on Linux, we all know that this program is executed according to the input parameters.
Yes, this is an important role used for interaction with the user space. Later, we will detail it in the appropriate chapters.

 

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/z2007b/archive/2011/05/04/6395333.aspx

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.