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,搞定!