linux 模拟热插拔工具,linux中用中断模拟热插拔

一、介绍

在linux中,常用的用户层和内核层通信方法有:系统调用(如copy_to_user/copy_from_user)、proc、ioctl和netlink。热插拔模式就是linux基于nelink实现的。netlink的讲解,可以看教程:http://blog.csdn.net/zcabcd123/article/details/8272423。

二、实现步骤

1、填充结构

在Linux系统中,当系统配置发生变化时,如:添加kset到系统;移动kobject, 一个通知会从内核空间发送到用户空间,这就是热插拔事件。热插拔事件会导致用户空间中相应的处理程序(如udev,mdev)被调用, 这些处理程序会通过加载驱动程序, 创建设备节点等来响应热插拔事件。

Struct kset_uevent_ops {

int (*filter)(struct kset *kset, struct kobject *kobj);

const char *(*name)(struct kset *kset, struct kobject *kobj);

int (*uevent)(struct kset *kset, struct kobject *kobj,

struct kobj_uevent_env *env);

}

当该kset所管理的kobject和kset状态发生变化时(如被加入,移动),这三个函数将被调用。

Filter:决定是否将事件传递到用户空间。如果filter返回0,将不传递事件。

Name:负责将相应的字符串传递给用户空间的热插拔处理程序。

Uevent:将用户空间需要的参数添加到环境变量中。

因此我们首先填充kset_uevent_ops这个结构体:

static struct kobj_type ktype =

{

};

static int kset_filter(struct kset *kset,struct kobject *kobj)

{

return 1;

}

static const char *kset_name(struct kset *kset,struct kobject *kobj)

{

static char buf[20];

sprintf(buf,"%s","SmartCover");

return buf;

}

static int kset_uevent(struct kset *kset,struct kobject *kobj, struct kobj_uevent_env *env)

{

return 0;

}

static struct kset_uevent_ops uevent_ops =

{

.filter = kset_filter,

.name = kset_name,

.uevent = kset_uevent,

};

struct kset *kset_p;

struct kset *kset_c;

2、初始化和注销

在probe函数中加入:

kset_p = kset_create_and_add("kset_p", &uevent_ops, NULL);

kset_c = kzalloc(sizeof(*kset_c), GFP_KERNEL); //初始化kset结构体

kobject_set_name(&kset_c->kobj,"kset_c");

kset_c->kobj.kset = kset_p;

kset_c->kobj.ktype = &ktype;

在release函数中加入注销函数(一般来说,系统不会有机会执行到它):

kset_unregister(kset_p);

3、具体模拟

因为添加/删除kset到系统的时候,就会有通知从内核发送到用户层,也就是热插拔。因此我们可以设置在第一次中断的时候是插入,下一次是拔出,以此内推:

if(add){ //插入还是拔出的状态判断

kset_unregister(kset_c); //删除kset模拟热插拔的拔出。注意当删除kset结构时候,kset_unregister函数会free掉kset_c结构体,所以下次需要用到该

结构体时候,要先重新分配并初始化该结构体。

if(!kset_c){

kset_c = kzalloc(sizeof(*kset_c), GFP_KERNEL);

}

kobject_set_name(&kset_c->kobj,"kset_c");

kset_c->kobj.kset = kset_p;

kset_c->kobj.ktype = &ktype;

}else if(!add){ //插入还是拔出的状态判断

kset_register(kset_c); //添加kset,模拟为热插拔的add。

}三、上层测试

在Android上层中使用UEventObserver方法来检测热插拔的发生。大概实现步骤如下:

1、设置要监听的热插拔文件路径。

上文中模拟的热插拔文件位置为/sys/kset_p,所以设置文件路径为/kset_p:

private String ueventTest = "DEVPATH=/kset_p";

2、重写UEventObserver.onUEvent方法

private final UEventObserver mUEventObserver = new UEventObserver() {

@Override

public void onUEvent(UEventObserver.UEvent event){

Log.e("Seven", "yulinghan UEVENT: "+event.toString());

}

};

3

、启动监听

mUEventObserver.startObserving(ueventTest);四、参考资料

1、Android测试监听的apk代码下载:

http://download.csdn.net/detail/u011630458/7364653

2、Android上层测试的教程,可以看blog:http://blog.csdn.net/lushengchu_luis/article/details/9466405

3、测试的完整代码如下:(注意必须在Android源代码下编译)

package com.example.ueventtest;

import android.os.Bundle;

import android.app.Activity;

import android.util.Log;

import android.view.Menu;

import android.widget.TextView;

import android.os.Handler;

import android.os.UEventObserver;

import android.os.Message;

import java.util.Timer;

import java.util.TimerTask;

public class MainActivity extends Activity {

private TextView tv;

private TextView tv2;

private String ueventTest = "DEVPATH=/kset_p";

private String ueventTest2 = "/devices/virtual/android_usb/android0";

private String test;

private String test2;

private Handler myHandler;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

tv = (TextView)findViewById(R.id.test);

tv2 = (TextView)findViewById(R.id.test2);

mUEventObserver.startObserving(ueventTest);

mUEventObserver.startObserving(ueventTest2);

mUEventObserver.startObserving("DEVPATH=/devices/virtual/switch/h2w");

tv.setText("sdcjbdjvkc");

myHandler = new Handler(){

public void handleMessage(Message msg) {

tv.setText(test);

tv2.setText(test2);

}

};

}

private final UEventObserver mUEventObserver = new UEventObserver() {

@Override

public void onUEvent(UEventObserver.UEvent event){

Log.e("Seven", "yulinghan UEVENT: "+event.toString());

test = "ACTION:" + event.get("ACTION");

test2 = "SUBSYSTEM:" + event.get("SUBSYSTEM");

myHandler.sendEmptyMessage(0x01);

}

};

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值