Linux Uevent和Netlink socket
来源:互联网 发布:centos 7 nginx 目录 编辑:程序博客网 时间:2024/06/04 00:58
Uevent是一种在内核空间和用户空间之间通信的机制,主要用于热插拔事件(hotplug)。
编辑获取热插拔事件的源文件get_uevent.c
#define _GNU_SOURCE#include <unistd.h>#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <stddef.h>#include <string.h>#include <fcntl.h>#include <time.h>#include <sys/socket.h>#include <sys/user.h>#include <sys/un.h>#include <linux/types.h>#include <linux/netlink.h>#define HOTPLUG_BUFFER_SIZE 1024#define HOTPLUG_NUM_ENVP 32#define OBJECT_SIZE 512struct uevent { void *next; char buffer[HOTPLUG_BUFFER_SIZE + OBJECT_SIZE]; char *devpath; char *action; char *envp[HOTPLUG_NUM_ENVP];};static struct uevent * alloc_uevent (void){ return (struct uevent *)malloc(sizeof(struct uevent));}int main(int argc, char *argv[]){ int sock; struct sockaddr_nl snl; struct sockaddr_un sun; socklen_t addrlen; int retval; int rcvbufsz = 128*1024; int rcvsz = 0; int rcvszsz = sizeof(rcvsz); unsigned int *prcvszsz = (unsigned int *)&rcvszsz; pthread_attr_t attr; const int feature_on = 1; memset(&snl, 0x00, sizeof(struct sockaddr_nl)); snl.nl_family = AF_NETLINK; snl.nl_pid = getpid(); snl.nl_groups = 0x01; sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (sock == -1) { printf("error getting socket, exit\n"); return 1; } printf("reading events from kernel.\n"); retval = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcvbufsz, sizeof(rcvbufsz)); if (retval < 0) { printf("error setting receive buffer size for socket, exit\n"); exit(1); } retval = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcvsz, prcvszsz); if (retval < 0) { printf("error setting receive buffer size for socket, exit\n"); exit(1); } printf("receive buffer size for socket is %u.\n", rcvsz); /* enable receiving of the sender credentials */ setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on)); retval = bind(sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl)); if (retval < 0) { printf("bind failed, exit\n"); goto exit; } while(1) { int i; char *pos; size_t bufpos; ssize_t buflen; struct uevent *uev; char *buffer; struct msghdr smsg; struct iovec iov; struct cmsghdr *cmsg; struct ucred *cred; char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; static char buf[HOTPLUG_BUFFER_SIZE + OBJECT_SIZE]; memset(buf, 0x00, sizeof(buf)); iov.iov_base = &buf; iov.iov_len = sizeof(buf); memset (&smsg, 0x00, sizeof(struct msghdr)); smsg.msg_iov = &iov; smsg.msg_iovlen = 1; smsg.msg_control = cred_msg; smsg.msg_controllen = sizeof(cred_msg); buflen = recvmsg(sock, &smsg, 0); if (buflen < 0) { if (errno != EINTR) printf("error receiving message.\n"); continue; } cmsg = CMSG_FIRSTHDR(&smsg); if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { printf("no sender credentials received, message ignored\n"); continue; } cred = (struct ucred *)CMSG_DATA(cmsg); if (cred->uid != 0) { printf("sender uid=%d, message ignored\n", cred->uid); continue; } /* skip header */ bufpos = strlen(buf) + 1; if (bufpos < sizeof("a@/d") || bufpos >= sizeof(buf)) { printf("invalid message length\n"); continue; } /* check message header */ if (strstr(buf, "@/") == NULL) { printf("unrecognized message header"); continue; } uev = alloc_uevent(); if (!uev) { printf("lost uevent, oom"); continue; } if ((size_t)buflen > sizeof(buf)-1) buflen = sizeof(buf)-1; /* * Copy the shared receive buffer contents to buffer private * to this uevent so we can immediately reuse the shared buffer. */ memcpy(uev->buffer, buf, HOTPLUG_BUFFER_SIZE + OBJECT_SIZE); buffer = uev->buffer; buffer[buflen] = '\0'; /* save start of payload */ bufpos = strlen(buffer) + 1; /* action string */ uev->action = buffer; pos = strchr(buffer, '@'); if (!pos) { printf("bad action string '%s'", buffer); continue; } pos[0] = '\0'; /* sysfs path */ uev->devpath = &pos[1]; /* hotplug events have the environment attached - reconstruct envp[] */ for (i = 0; (bufpos < (size_t)buflen) && (i < HOTPLUG_NUM_ENVP-1); i++) { int keylen; char *key; key = &buffer[bufpos]; keylen = strlen(key); uev->envp[i] = key; bufpos += keylen + 1; } uev->envp[i] = NULL; printf("uevent '%s' from '%s'.\n", uev->action, uev->devpath); /* print payload environment */ for (i = 0; uev->envp[i] != NULL; i++) printf("%s\n", uev->envp[i]); } return 0;exit: close(sock); return 1;}
以插拔优盘为例从内核中获取具体的事件。
编译运行./get_uevent
,然后插入一个优盘:
reading events from kernel.receive buffer size for socket is 262142.uevent 'add' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5'.ACTION=addDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5SUBSYSTEM=usbMAJOR=189MINOR=387DEVNAME=bus/usb/004/004DEVTYPE=usb_deviceDEVICE=/proc/bus/usb/004/004PRODUCT=781/5590/100TYPE=0/0/0BUSNUM=004DEVNUM=004SEQNUM=1322uevent 'add' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0'.ACTION=addDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0SUBSYSTEM=usbDEVTYPE=usb_interfaceDEVICE=/proc/bus/usb/004/004PRODUCT=781/5590/100TYPE=0/0/0INTERFACE=8/6/80MODALIAS=usb:v0781p5590d0100dc00dsc00dp00ic08isc06ip50SEQNUM=1323uevent 'add' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4'.ACTION=addDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4SUBSYSTEM=scsiDEVTYPE=scsi_hostSEQNUM=1324...uevent 'change' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0'.ACTION=changeDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0SUBSYSTEM=scsiSDEV_MEDIA_CHANGE=1DEVTYPE=scsi_deviceDRIVER=sdMODALIAS=scsi:t-0x00SEQNUM=1331uevent 'add' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/block/sdb'.ACTION=addDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/block/sdbSUBSYSTEM=blockMAJOR=8MINOR=16DEVNAME=sdbDEVTYPE=diskSEQNUM=1332uevent 'add' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/block/sdb/sdb1'.ACTION=addDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/block/sdb/sdb1SUBSYSTEM=blockMAJOR=8MINOR=17DEVNAME=sdb1DEVTYPE=partitionSEQNUM=1333uevent 'add' from '/devices/virtual/bdi/8:16'.ACTION=addDEVPATH=/devices/virtual/bdi/8:16SUBSYSTEM=bdiSEQNUM=1334`
拔出优盘时获取的信息:
uevent 'remove' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0'.ACTION=removeDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0SUBSYSTEM=bsgMAJOR=253MINOR=1DEVNAME=bsg/4:0:0:0SEQNUM=1335uevent 'remove' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0'.ACTION=removeDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0SUBSYSTEM=scsi_deviceSEQNUM=1336uevent 'remove' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0/host4/target4:0:0/4:0:0:0/scsi_disk/4:0:0:0'....uevent 'remove' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0'.ACTION=removeDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5/4-5:1.0SUBSYSTEM=usbDEVTYPE=usb_interfaceDEVICE=/proc/bus/usb/004/004PRODUCT=781/5590/100TYPE=0/0/0INTERFACE=8/6/80MODALIAS=usb:v0781p5590d0100dc00dsc00dp00ic08isc06ip50SEQNUM=1344uevent 'remove' from '/devices/pci0000:00/0000:00:13.2/usb4/4-5'.ACTION=removeDEVPATH=/devices/pci0000:00/0000:00:13.2/usb4/4-5SUBSYSTEM=usbMAJOR=189MINOR=387DEVNAME=bus/usb/004/004DEVTYPE=usb_deviceDEVICE=/proc/bus/usb/004/004PRODUCT=781/5590/100TYPE=0/0/0BUSNUM=004DEVNUM=004SEQNUM=1345uevent 'remove' from '/host4/target4:0:0'.ACTION=removeDEVPATH=/host4/target4:0:0SUBSYSTEM=scsiDEVTYPE=scsi_targetSEQNUM=1346
0 0
- Linux Uevent和Netlink socket
- android 关于 netlink uevent
- socket的内核和上层通信机制(netlink) -- linux内核
- 转贴:Linux Netlink Socket Example
- Linux netlink socket使用总结
- Linux Wireless netlink socket & nl80211
- uevent内核事件与netlink机制的交互 -Linux Kernel实现欣赏
- 析frmware的加载和init通过netlink处理uevent事件的一般流程
- 浅析frmware的加载和init通过netlink处理uevent事件的一般流程
- 浅析frmware的加载和init通过netlink处理uevent事件的一般流程(转)
- 浅析frmware的加载和init通过netlink处理uevent事件的一般流程
- 浅析frmware的加载和init通过netlink处理uevent事件的一般流程
- NetLink socket
- Netlink Socket
- netlink socket
- socket&&netlink
- Netlink Socket
- Netlink Socket
- 如何删除彻底删除FIREFOX插件
- Java的GC机制及算法
- oracle JDBC使用例子
- progress与meter元素
- bootstrap-datepicker
- Linux Uevent和Netlink socket
- 计算器2
- 性能大提速 MyEclipse终极优化四要点
- HTTP协议中PUT和POST使用区别
- 递归回溯
- HDOJ 2082 找单词(母函数模板)、 HDOJ 1028 整数拆分(母函数+打表)
- Tkinter教程之Canvas(2)篇
- ERP需求调研之仓库物料管理十问十答
- 通过广播简单实现sms短信的发送和接收