kobject的容器kset与hotplug

kobject的容器kset与hotplug

PS: linux 无法登录ssh
1.检查linux下sshd 服务 ps -e | grep ssh*
2.重启服务 service /etc/ssh restart
3.ufw disbale 关闭防火墙

struct kset:
struct kset {
    struct list_head list;
    spinlock_t list_lock;
    struct kobject kobj; //kobject 对象容器 
    const struct kset_uevent_ops *uevent_ops; //kobject 对象发生变化通知用户空间
};

struct kset_uevent_ops {
    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); //事件 
};

操作函数
//初始化kset_init
extern void kset_init(struct kset *kset);
//注册kset
int kset_register(struct kset *k)
    kset_init(k); //初始化
    err = kobject_add_internal(&k->kobj);//创建目录
    kobject_uevent(&k->kobj, KOBJ_ADD); // 如果设置 CONFIG_HOTPLUG ,将向内核发送事件通知用户空间

热插拔过程分析
//注意: kobject对象要支持热插拔必须要有它的容器kset,孤立的kobject是无法支持热插拔的
int kobject_uevent(struct kobject *kobj, enum kobject_action action)
    kobject_uevent_env(kobj, action, NULL);
        //找到顶层的kset
        top_kobj = kobj;
        while (!top_kobj->kset && top_kobj->parent)
            top_kobj = top_kobj->parent;
        //获得顶层的kset的uevent_ops
        kset = top_kobj->kset;
        uevent_ops = kset->uevent_ops;
        //事件是否被顶层过滤
        uevent_ops->filter(kset, kobj)
        subsystem = uevent_ops->name(kset, kobj);
        //准备发送用户空间的消息
        env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
        retval = add_uevent_var(env, "ACTION=%s", action_string);
        retval = uevent_ops->uevent(kset, kobj, env);
        #if defined(CONFIG_NET)
        //发送 netlink 
        retval = netlink_broadcast_filtered(uevent_sock, skb,
                                0, 1, GFP_KERNEL,
                                kobj_bcast_filter,
                                kobj);


        #else
            //call_usermodehelper

linux热插拔的例子

内核:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/slab.h>

static struct kobject * parent = NULL;
static struct kobject * child = NULL;
static struct kset * p_kset =NULL;

static struct attribute child_attr = {
    .name = "child_attr",
    .mode = S_IRUSR|S_IWUSR,
};

static ssize_t  attr_show(struct kobject *kobj, struct attribute *attr,char *buf)
{
    printk(KERN_INFO "%s\n",__FUNCTION__);
    printk(KERN_INFO"buf[0] = 0x%x",*buf);
    return 0;
}

static ssize_t attr_store (struct kobject *kobj,struct attribute *attr,const char *buf, size_t count)
{
    unsigned char flag = 0;
    printk(KERN_INFO "%s\n",__FUNCTION__);

    printk(KERN_INFO"buf[0] = 0x%x",*buf);

    flag = *buf-'0';
    printk(KERN_INFO"FLAG= %d",flag);
    switch(flag)
    {
        case 0: kobject_uevent(kobj, KOBJ_ADD);break;
        case 1: kobject_uevent(kobj, KOBJ_REMOVE);break;

    }
    return  count;
}

static struct sysfs_ops attr_ops ={
    .show = attr_show,
    .store = attr_store,
};

static struct kobj_type attr_ktype={
    .sysfs_ops = &attr_ops,
};

static int __init kobject_test_init(void)
{
     printk(KERN_INFO "%s\n",__FUNCTION__);

     parent = kobject_create_and_add("pa_obj",NULL);
     child = kzalloc(sizeof(*child), GFP_KERNEL);
     if (!child)
        return NULL;

     kobject_init_and_add(child ,&attr_ktype, parent, "pb_obj");
     sysfs_create_file(child, &child_attr);

     //为 parent 添加一个 kset
     p_kset = kset_create_and_add("p_kset", NULL, parent);
     //能发生热插拔kobject对象必须属于一个kset
     child->kset = p_kset;
     return 0;
}



static void __exit kobject_test_exit(void)
{
     printk(KERN_INFO "%s\n",__FUNCTION__);

     sysfs_remove_file(child, &child_attr);
     kset_unregister(p_kset);
     kobject_del(child);
     kobject_del(parent);
}

module_init(kobject_test_init); 
module_exit(kobject_test_exit);

MODULE_AUTHOR("derrick email: kjfure@163.com");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Kobject test Module");
MODULE_ALIAS("Kobject test Module");

用户空间:
#include <sys/stat.h>  
#include <unistd.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <sys/socket.h>  
#include <sys/types.h>  
#include <string.h>  
#include <asm/types.h>  
#include <linux/netlink.h>  
#include <linux/socket.h>  
#include <errno.h>  
#include <linux/poll.h> 
#define NETLINK_TEST 21  
#define MAX_PAYLOAD 1024 

int main(int argc, char* argv[])  
{  
    struct sockaddr_nl nls;
    struct pollfd pfd;

    char buf[512];

    memset(&nls,0,sizeof(struct sockaddr_nl));

    nls.nl_family=AF_NETLINK;
    nls.nl_pid = getpid();
    nls.nl_groups=-1;

    pfd.events = POLLIN;
    pfd.fd = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT);
    if(pfd.fd == -1)
    {
        printf("scoket error\r\n");
        return 0;
    }

    bind(pfd.fd,(void *)&nls,sizeof(struct sockaddr_nl));
    while(-1!=poll(&pfd,1,-1))
    {
        int i,len;
        len = recv(pfd.fd,buf,sizeof(buf),MSG_DONTWAIT);
        if(len==-1)
        {

            printf("recv error");
            return -1;
        }

        i=0;
        while(i<len){
            printf("%s\n",buf+i);
            i+=strlen(buf+i)+1;
        }
    }

    printf("poll error\r\n");
    return 0;
}

test: 
#....# echo '1' > /sys/pa_obj/pb_obj/child_attr 
attr_store
buf[0] = 0x31
FLAG= 1remove@/pa_obj/pb_obj
ACTION=remove
DEVPATH=/pa_obj/pb_obj
SUBSYSTEM=p_kset
SEQNUM=1536
# echo '0' > /sys/pa_obj/pb_obj/child_attr 
attr_store
buf[0] = 0x30
FLAG= 0add@/pa_obj/pb_obj
ACTION=add
DEVPATH=/pa_obj/pb_obj
SUBSYSTEM=p_kset
SEQNUM=1537
体会: netlink sys 这两种都可以用户空间和内核空间交换数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值