uevent 使用示例

1.内核端


struct device *dev = NULL;
char * s_c[2];

static ssize_t send( struct device *dev, struct device_attribute *attr, const char *buf, size_t count )
{
    s_c[0] = "song_hello";
    s_c[1] = NULL;
    kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, s_c);


    printk(KERN_ERR "count = %d.\r\n", count );
    printk(KERN_ERR "in song_uevent send.\r\n");

    
    return count;
}


static DEVICE_ATTR(S, S_IRUGO|S_IWUSR, NULL, send);


static const struct attribute *song_event_attr[] = {
        &dev_attr_S.attr,
        NULL,
};


static const struct attribute_group song_event_attr_group = {
        .attrs = (struct attribute **) song_event_attr,
};


static struct class song_event_class = {
        .name =         "song_event",
        .owner =        THIS_MODULE,
};


static int __init song_uevent_init( void )        
{                             
    int ret = 0;


    printk(KERN_ERR "in song_uevent_init.\r\n");
    
    ret = class_register(&song_event_class);
    if( ret < 0 ){
        printk(KERN_ERR "song_event: class_register fail\n");
        return ret;
    }
    dev = device_create(&song_event_class, NULL, MKDEV(0, 0), NULL, "song_event");
    if( dev ){
        ret = sysfs_create_group(&dev->kobj, &song_event_attr_group);
        if( ret < 0 ){
            printk(KERN_ERR "song_event:sysfs_create_group fail\r\n");
            return ret;
        }
    }else{
        printk(KERN_ERR "song_event:device_create fail\r\n");
        ret = -1;
        return ret;
    }
    return 0;
}
加载此模块将建立 /sys/devices/virtual/song_event/song_event

如何使用呢?就是怎么让内核发送消息出来?

echo 123 > S 

对此文件进行写操作 即可发送制定消息

 

2.app端

app端如何获取到内核端发送的消息呢?

直接看如下代码:


#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/netlink.h>

#define UEVENT_MSG_LEN 2048
#define USER_COOLING_DEV "/devices/virtual/thermal/cooling_device0"

struct cooling_device {
    const char *name;
    const char *action;
    const char *path;
    int state;
    int temp;    
};

static int open_uevent_socket(void);
static void parse_uevent(const char *msg, struct cooling_device *cdev);

    
int main_uevent( int argc __unused, char **argv __unused ) 
{
    int socket_fd = -1;
    char msg[UEVENT_MSG_LEN+2];
    int n;

    socket_fd = open_uevent_socket();
    //--------------------------------------创建socket。
    debug_msg("socket_fd = %d\n", socket_fd);

    do {
        while((n = recv(socket_fd, msg, UEVENT_MSG_LEN, 0)) > 0) {
            //---------接收uevent信息。
            struct cooling_device cdev;
            memset(&cdev, 0x0, sizeof(cdev));

            if(n == UEVENT_MSG_LEN)
                continue;

            msg[n] = '\0';
            msg[n+1] = '\0';

            parse_uevent(msg, &cdev);
            //---------------------------------------解析收到的uevent字符。
        }
    } while(1);
}

static int open_uevent_socket(void)
{
    struct sockaddr_nl addr;
    int sz = 64*1024;
    int s = 0;

    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_pid = getpid();
    addr.nl_groups = 0xffffffff;

    s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    //-------------地址族是AF_NETLINK类型的socket,协议类型是NETLINK_KOBJECT_UEVENT。
    if (s < 0) {
        return -1;
    }

    setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));

    if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        //-------------将当前socket绑定到AF_NETLINK地址族,并且设置本进程为处理消息的进程。
        close(s);
        return -1;
    }

    return s;
}

static void parse_uevent(const char *msg, struct cooling_device *cdev)
{
    while (*msg) {
        debug_msg("msg = %s\n", msg);
        if (!strncmp(msg, "NAME=", 5)) {
            msg += 5;
            cdev->name = msg;
        } else if (!strncmp(msg, "ACTION=", 7)) {
            msg += 7;
            cdev->action = msg;
        } else if (!strncmp(msg, "DEVPATH=", 8)) {
            msg += 8;
            cdev->path = msg;
        } else if (!strncmp(msg, "STATE=", 6)) {
            msg += 6;
            cdev->state = atoi(msg);
        } else if (!strncmp(msg, "TEMP=", 5)) {
            msg += 5;
            cdev->temp = atoi(msg);
        }

        while(*msg++);
    }

     debug_msg("event { name=%s, action=%s, path=%s, state=%d, temp=%d}\n",
            cdev->name,    cdev->action, cdev->path, cdev->state, cdev->temp);
     

    if(!strncmp(cdev->path, USER_COOLING_DEV, sizeof(USER_COOLING_DEV)) && !strncmp(cdev->action, "change", 5))
        debug_msg("event { name=%s, action=%s, path=%s, state=%d, temp=%d}\n",
            cdev->name,    cdev->action, cdev->path, cdev->state, cdev->temp);
}


void *socket_uevent_test(void *arg)
{     
    char log[4096]; 
    int status;
    int connect_number = 6;
    int fdListen = -1, new_fd = -1;
    int ret;
    struct sockaddr_un peeraddr;
    socklen_t socklen = sizeof (peeraddr);
    int numbytes ;
    char buff[4096];
    char * ret_p;
                                               
    new_fd = *(int *)arg;                                                                                                                                               
    while( 1 ){
      sleep(1);
      main_uevent(0,NULL);
      debug_msg( "exit socket thread.\n");
    }
    return 0;
}

 

ok,搞定!

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值