linux --- iwevent事件上报机制
来源:互联网 发布:xp添加网络win7打印机 编辑:程序博客网 时间:2024/04/30 09:48
最近工作涉及到了对linux下面的iwevent命令的使用,主要是:通过linux下面的netlink机制将内核的信息发送给用户态程序,这里的用户态程序就是iwevent。
linux 对iwevent命令的帮助信息如下:
IWEVENT(8) Linux Programmer's Manual IWEVENT(8)
NAME
iwevent - Display Wireless Events generated by drivers and setting changes
SYNOPSIS
iwevent
DESCRIPTION
iwevent displays Wireless Events received through the RTNetlink socket. Each line displays the specific Wireless Event which
describes what has happened on the specified wireless interface.
This command doesn't take any arguments.
DISPLAY
There are two classes of Wireless Events.
The first class is events related to a change of wireless settings on the interface (typically done through iwconfig or a script
calling iwconfig). Only settings that could result in a disruption of connectivity are reported. The events currently reported
are changing one of the following setting :
Network ID
ESSID
Frequency
Mode
Encryption
All those events will be generated on all wireless interfaces by the kernel wireless subsystem (but only if the driver has been
converted to the new driver API).
The second class of events are events generated by the hardware, when something happens or a task has been finished. Those events
include :
New Access Point/Cell address
The interface has joined a new Access Point or Ad-Hoc Cell, or lost its association with it. This is the same address that
is reported by iwconfig.
Scan request completed
A scanning request has been completed, results of the scan are available (see iwlist).
Tx packet dropped
A packet directed at this address has been dropped because the interface believes this node doesn't answer anymore (usually
maximum of MAC level retry exceeded). This is usually an early indication that the node may have left the cell or gone out
of range, but it may be due to fading or excessive contention.
Custom driver event
Event specific to the driver. Please check the driver documentation.
Registered node
The interface has successfully registered a new wireless client/peer. Will be generated mostly when the interface acts as
an Access Point (mode Master).
Expired node
The registration of the client/peer on this interface has expired. Will be generated mostly when the interface acts as an
Access Point (mode Master).
Spy threshold crossed
The signal strength for one of the addresses in the spy list went under the low threshold or went above the high threshold.
Most wireless drivers generate only a subset of those events, not all of them, the exact list depends on the specific hard?
ware/driver combination. Please refer to driver documentation for details on when they are generated, and use iwlist(8) to check
what the driver supports.
AUTHOR
Jean Tourrilhes - jt@hpl.hp.com
SEE ALSO
iwconfig(8), iwlist(8), iwspy(8), iwpriv(8), wireless(7).
二:iwevent代码分析
iwevent命令的源代码存在于:wireless_tools.29中,代码重要是通过socket从内核获取信息。
int
main(int argc,
char * argv[])
{
struct rtnl_handle rth;
int opt;
/* Check command line options */
while((opt = getopt_long(argc, argv, "hv", long_opts, NULL)) > 0)
{
switch(opt)
{
case 'h':
iw_usage(0);
break;
case 'v':
return(iw_print_version_info("iwevent"));
break;
default:
iw_usage(1);
break;
}
}
if(optind < argc)
{
fputs("Too many arguments.\n", stderr);
iw_usage(1);
}
/* Open netlink channel */
if(rtnl_open(&rth, RTMGRP_LINK) < 0)
{
perror("Can't initialize rtnetlink socket");
return(1);
}
fprintf(stderr, "Waiting for Wireless Events from interfaces...\n");
/* Do what we have to do */
wait_for_event(&rth);
/* Cleanup - only if you are pedantic */
rtnl_close(&rth);
return(0);
}
下面看一下这三个函数:
static inline int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
{
int addr_len;
memset(rth, 0, sizeof(rth));
rth->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (rth->fd < 0) {
perror("Cannot open netlink socket");
return -1;
}
memset(&rth->local, 0, sizeof(rth->local));
rth->local.nl_family = AF_NETLINK;
rth->local.nl_groups = subscriptions;
if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
perror("Cannot bind netlink socket");
return -1;
}
addr_len = sizeof(rth->local);
if (getsockname(rth->fd, (struct sockaddr*)&rth->local,(socklen_t *) &addr_len) < 0) {
perror("Cannot getsockname");
return -1;
}
if (addr_len != sizeof(rth->local)) {
fprintf(stderr, "Wrong address length %d\n", addr_len);
return -1;
}
if (rth->local.nl_family != AF_NETLINK) {
fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
return -1;
}
rth->seq = time(NULL);
return 0;
}
static inline int wait_for_event(struct rtnl_handle *rth)
{
#if 0
struct timeval tv;/* Select timeout */
#endif
/* Forever */
while(1)
{
fd_set rfds;/* File descriptors for select */
int last_fd;/* Last fd */
int ret;
/* Guess what ? We must re-generate rfds each time */
FD_ZERO(&rfds);
FD_SET(rth->fd, &rfds);
last_fd = rth->fd;
/* Wait until something happens */
ret = select(last_fd + 1, &rfds, NULL, NULL, NULL);
/* Check if there was an error */
if(ret < 0)
{
if(errno == EAGAIN || errno == EINTR)
continue;
fprintf(stderr, "Unhandled signal - exiting...\n");
break;
}
/* Check if there was a timeout */
if(ret == 0)
{
continue;
}
/* Check for interface discovery events. */
if(FD_ISSET(rth->fd, &rfds))
handle_netlink_events(rth);
}
return(0);
}
/*
* We must watch the rtnelink socket for events.
* This routine handles those events (i.e., call this when rth.fd
* is ready to read).
*/
static inline void handle_netlink_events(struct rtnl_handle *rth)
{
while(1)
{
struct sockaddr_nl sanl;
socklen_t sanllen = sizeof(struct sockaddr_nl);
struct nlmsghdr *h;
int amt;
char buf[8192];
amt = recvfrom(rth->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sanl, &sanllen);
if(amt < 0)
{
if(errno != EINTR && errno != EAGAIN)
{
fprintf(stderr, "%s: error reading netlink: %s.\n",
__PRETTY_FUNCTION__, strerror(errno));
}
return;
}
if(amt == 0)
{
fprintf(stderr, "%s: EOF on netlink??\n", __PRETTY_FUNCTION__);
return;
}
h = (struct nlmsghdr*)buf;
while(amt >= (int)sizeof(*h))
{
int len = h->nlmsg_len;
int l = len - sizeof(*h);
if(l < 0 || len > amt)
{
fprintf(stderr, "%s: malformed netlink message: len=%d\n", __PRETTY_FUNCTION__, len);
break;
}
switch(h->nlmsg_type)
{
case RTM_NEWLINK:
case RTM_DELLINK:
LinkCatcher(h);
break;
default:
#if 0
fprintf(stderr, "%s: got nlmsg of type %#x.\n", __PRETTY_FUNCTION__, h->nlmsg_type);
#endif
break;
}
len = NLMSG_ALIGN(len);
amt -= len;
h = (struct nlmsghdr*)((char*)h + len);
}
if(amt > 0)
fprintf(stderr, "%s: remnant of size %d on netlink\n", __PRETTY_FUNCTION__, amt);
}
}
/*------------------------------------------------------------------*/
/*
* Respond to a single RTM_NEWLINK event from the rtnetlink socket.
*/
static int LinkCatcher(struct nlmsghdr *nlh)
{
struct ifinfomsg* ifi;
#if 0
fprintf(stderr, "nlmsg_type = %d.\n", nlh->nlmsg_type);
#endif
ifi = NLMSG_DATA(nlh);
/* Code is ugly, but sort of works - Jean II */
/* If interface is getting destoyed */
if(nlh->nlmsg_type == RTM_DELLINK)
{
/* Remove from cache (if in cache) */
iw_del_interface_data(ifi->ifi_index);
return 0;
}
/* Only keep add/change events */
if(nlh->nlmsg_type != RTM_NEWLINK)
return 0;
/* Check for attributes */
if (nlh->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg)))
{
int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg));
struct rtattr *attr = (void *) ((char *) ifi +NLMSG_ALIGN(sizeof(struct ifinfomsg)));
while (RTA_OK(attr, attrlen))
{
/* Check if the Wireless kind */
if(attr->rta_type == IFLA_WIRELESS)
{
/* Go to display it */
print_event_stream(ifi->ifi_index,
(char *) attr + RTA_ALIGN(sizeof(struct rtattr)),
attr->rta_len - RTA_ALIGN(sizeof(struct rtattr)));
}
attr = RTA_NEXT(attr, attrlen);
}
}
return 0;
}
----------------------------------------------------------------------------------------------
二:对iwevent的测试
~ # iwevent
Waiting for Wireless Events from interfaces...
00:01:30.492550 ath0 Custom driver event:STA ASSOC.indication sta=40:16:9f:01:2f:80 ,sig_strength=31, association time is -52390
00:01:30.510397 ath0 Registered node:40:16:9F:01:2F:80
00:01:30.808654 ath0 Custom driver event:STA ASSOC.indication sta=40:16:9f:01:2f:80 ,sig_strength=31, association time is -52298
00:01:30.808800 ath0 Registered node:40:16:9F:01:2F:80
上面的信息是当无线网卡连接上ap时的打印信息。根据这些打印信息可以分析linux和iwevent的源代码。
- linux --- iwevent事件上报机制
- linux --- iwevent事件上报机制
- Linux Kernel input 上报事件
- 安卓linux uevent内核上报机制实例
- uevent 事件上报demo
- ZWAVE ALARM CLASS -- 过时的sensor告警和事件上报机制
- Android event事件上报方法
- getevent获取input上报事件
- LTE CQI/PMI 上报机制
- Linux网络事件通知机制
- Linux开发--inotify事件机制
- android耳机插入\拔出事件上报流程
- 旋屏事件上报流程分析
- 恶心的“定点上报调度”机制!
- 输入子系统多点协议上报机制实现
- LTE 中的CQI,PMI,RI上报机制
- Android 手机信号强度上报机制1
- 底层状态改变上报上层机制
- Java 的类加载机制
- EL表达式的基本用法
- 把字符串转换成整数 .
- 在gentoo上安装bochs
- popen()
- linux --- iwevent事件上报机制
- Android 动画旋转效果
- MTK面试应该知道的N个问题 .
- Android ApiDemos示例解析(41):App->Service->Messenger Service
- 4月昆山团购报告 人均消费近54.2元
- android Activity切换动画效果
- 同步信号
- HashMap与HashTable
- Android 触屏播放音效与释放