http://blog.csdn.net/sepnic/article/details/6799476
前些日子研究如何在Android实现USB-Audio的热插拔,顺带了解了一下netlink机制。netlink在TCP/IP方面用得较多,但根据需要也可用在HDMI/USB等热插拔消息通知。前人已经对这方面有深入的剖析,这里就不累述了。一些典型的资料如下:
linux的配置接口-netlink原理和设计
netlink机制-实现系统调用
netlink机制-总结
PF_NETLINK应用实例NETLINK_KOBJECT_UEVENT具体实现--udev实现原理
linux 内核与用户空间通信之netlink使用方法
如下是我实现的从内核中获取USB热插拔消息的代码,可根据对消息字符串的解析来定义对应的操作。事实上这种方法并不足够好(胜在简便)。比较好的做法是实现点对点,即在内核驱动中用netlink_kernel_create创建一个netlink服务端,发送自定义的消息帧,用户程序就可接收指定netlink服务端的消息。
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <linux/netlink.h> #define UEVENT_BUFFER_SIZE 2048 int thread_net_link() { struct sockaddr_nl client; struct timeval tv; int skfd, rcvlen, ret; fd_set fds; int buffersize = 1024; skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); memset(&client, 0, sizeof(client)); client.nl_family = AF_NETLINK; client.nl_pid = getpid(); client.nl_groups = 1; /* receive broadcast message*/ setsockopt(skfd, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); bind(skfd, (struct sockaddr*)&client, sizeof(client)); while (1) { char buf[UEVENT_BUFFER_SIZE] = { 0 }; FD_ZERO(&fds); FD_SET(skfd, &fds); tv.tv_sec = 0; tv.tv_usec = 100 * 1000; ret = select(skfd + 1, &fds, NULL, NULL, &tv); if(ret < 0) continue; if(!(ret > 0 && FD_ISSET(skfd, &fds))) continue; /* receive data */ rcvlen = recv(skfd, &buf, sizeof(buf), 0); if (rcvlen > 0) { printf("%s\n", buf); // do something here!!! // // // } } close(skfd); return 0; }