当udev提示如下报错时,内核配置中选中INOTIFY_USER即可。
udevd[992]: inotify_init failed: Function not implemented
udev规则文件示例(tf卡插拔自动挂载与卸载):
/etc/udev/rules.d/10-tf.rules
#KERNEL=="mmcblk[0-9]p[0-9]", RUN+="/etc/udev/hotplug-tf.sh %k $env{ACTION}"
ACTION=="add", KERNEL=="mmc0:*", RUN+="/etc/udev/hotplug-tf.sh %k $env{ACTION}"
ACTION=="remove", KERNEL=="mmc0:*", RUN+="/etc/udev/hotplug-tf.sh %k $env{ACTION}"
/etc/udev/udev.conf
udev_root="/dev/"
udev_rules="/etc/udev/rules.d/"
udev_log="err"
要执行的shell脚本中记得开头要加入一行 #!/bin/sh,否则udev会报format err.
/etc/udev/hotplug-tf.sh
#!/bin/sh
echo "==============hotplug tf $(date)=============" #>> /run/udev.log
echo "[$#] $0, $1 ,$2" #>> /run/udev.log
if [ "$#" != "2" ];then
echo " !! param err." #>> /run/udev.log
exit 1
fi
if [ "$2" == "remove" ];then
echo " <==umount" #>> /run/udev.log
umount /mnt/extsd
fi
if [ "$2" == "add" ];then
echo " ==>mount" #>> /run/udev.log
mkdir /mnt/extsd
mount -t vfat /dev/mmcblk0p1 /mnt/extsd
fi
exit 0
udev规则匹配表:
键 含义
----------------------------------------
ACTION 事件 (uevent) 的行为,例如:add( 添加设备 )、remove( 删除设备 ).
KERNEL 在内核里看到的设备名字,比如sd*表示任意SCSI磁盘设备
DEVPATH 内核设备录进,比如/devices/*
SUBSYSTEM 子系统名字,例如:sda 的子系统为 block.
BUS 总线的名字,比如IDE,USB
DRIVER 设备驱动的名字,比如ide-cdrom
ID 独立于内核名字的设备名字
SYSFS{ value} sysfs属性值,他可以表示任意
ENV{ key} 环境变量,可以表示任意
PROGRAM 可执行的外部程序,如果程序返回0值,该键则认为为真(true)
RESULT 上一个PROGRAM调用返回的标准输出.
NAME 根据这个规则创建的设备文件的文件名.
(注意:仅仅第一行的NAME描述是有效的,后面的均忽略.如果你想使用使用两个以上的名字来访问一个设备的话,可以考虑SYMLINK键.)
SYMLINK 为 /dev/下的设备文件产生符号链接.由于 udev 只能为某个设备产生一个设备文件,
(所以为了不覆盖系统默认的 udev 规则所产生的文件,推荐使用符号链接.)
OWNER 设备文件的属组
GROUP 设备文件所在的组.
MODE 设备文件的权限,采用8进制
RUN 为设备而执行的程序列表
LABEL 在配置文件里为内部控制而采用的名字标签(下下面的GOTO服务)
GOTO 跳到匹配的规则(通过LABEL来标识),有点类似程序语言中的GOTO
IMPORT{ type} 导入一个文件或者一个程序执行后而生成的规则集到当前文件
WAIT_FOR_SYSFS 等待一个特定的设备文件的创建.主要是用作时序和依赖问题.
PTIONS 特定的选项:
last_rule 对这类设备终端规则执行;
ignore_device 忽略当前规则;
ignore_remove 忽略接下来的并移走请求.
all_partitions 为所有的磁盘分区创建设备文件.
udev一些特殊的值和替换值:
在键值对中的键和操作符都介绍完了,最后是值 (value).Linux 用户可以随意地定制 udev 规则文件的值.
例如:my_root_disk, my_printer.同时也可以引用下面的替换操作符:
----------------------------------------
$kernel, %k: 设备的内核设备名称,例如:sda、cdrom.
$number, %n: 设备的内核号码,例如:sda3 的内核号码是 3.
$devpath, %p: 设备的 devpath路径.
$id, %b: 设备在 devpath里的 ID 号.
$sysfs{file}, %s{file}: 设备的 sysfs里 file 的内容.其实就是设备的属性值.
$env{key}, %E{key}: 一个环境变量的值.
$major, %M: 设备的 major 号.
$minor, %m: 设备的 minor 号.
$result, %c: PROGRAM 返回的结果
$parent, %P: 父设备的设备文件名.
$root, %r: udev_root的值,默认是 /dev/.
$tempnode, %N: 临时设备名.
%%: 符号 % 本身.
$$: 符号 $ 本身.
————————————————
原文链接:https://blog.csdn.net/xiaoliu5396/article/details/46531893
以下源码用来读取net link消息
#include
#include
#include
#include
#include
#include
//该头文件需要放在netlink.h前面防止编译出现__kernel_sa_family未定义
#include
#include
void MonitorNetlinkUevent()
{
int sockfd;
struct sockaddr_nl sa;
int len;
char buf[4096];
struct iovec iov;
struct msghdr msg;
int i;
memset(&sa,0,sizeof(sa));
sa.nl_family=AF_NETLINK;
sa.nl_groups=NETLINK_KOBJECT_UEVENT;
sa.nl_pid = 0;//getpid(); both is ok
memset(&msg,0,sizeof(msg));
iov.iov_base=(void *)buf;
iov.iov_len=sizeof(buf);
msg.msg_name=(void *)&sa;
msg.msg_namelen=sizeof(sa);
msg.msg_iov=&iov;
msg.msg_iovlen=1;
sockfd=socket(AF_NETLINK,SOCK_RAW,NETLINK_KOBJECT_UEVENT);
if(sockfd==-1)
printf("socket creating failed:%s\n",strerror(errno));
if(bind(sockfd,(struct sockaddr *)&sa,sizeof(sa))==-1)
printf("bind error:%s\n",strerror(errno));
while(1){
len=recvmsg(sockfd,&msg,0);
if(len<0)
printf("receive error\n");
else if(len<32||len>sizeof(buf))
printf("invalid message");
for(i=0;i if(*(buf+i)=='\0') buf[i]='\n'; printf("received %d bytes\n%s\n",len,buf); } } int main(int argc,char **argv) { MonitorNetlinkUevent(); return 0; }