當(dāng)udev提示如下報(bào)錯(cuò)時(shí),內(nèi)核配置中選中INOTIFY_USER即可。
udevd[992]: inotify_init failed: Function not implemented
udev規(guī)則文件示例(tf卡插拔自動(dòng)掛載與卸載):
/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"?
要執(zhí)行的shell腳本中記得開頭要加入一行 #!/bin/sh,否則udev會(huì)報(bào)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規(guī)則匹配表:
鍵? ? ? ? ? ? ? ? 含義
----------------------------------------
ACTION? ? ? ? ? ? ? 事件 (uevent) 的行為,例如:add( 添加設(shè)備 )、remove( 刪除設(shè)備 ).
KERNEL? ? ? ? ? ? ? 在內(nèi)核里看到的設(shè)備名字,比如sd*表示任意SCSI磁盤設(shè)備
DEVPATH? ? ? ? ? ? ? 內(nèi)核設(shè)備錄進(jìn),比如/devices/*
SUBSYSTEM? ? ? ? ? ? 子系統(tǒng)名字,例如:sda 的子系統(tǒng)為 block.
BUS? ? ? ? ? ? ? ? ? 總線的名字,比如IDE,USB
DRIVER? ? ? ? ? ? ? 設(shè)備驅(qū)動(dòng)的名字,比如ide-cdrom
ID? ? ? ? ? ? ? ? ? 獨(dú)立于內(nèi)核名字的設(shè)備名字
SYSFS{ value}? ? ? ? sysfs屬性值,他可以表示任意
ENV{ key}? ? ? ? ? ? 環(huán)境變量,可以表示任意
PROGRAM? ? ? ? ? ? ? 可執(zhí)行的外部程序,如果程序返回0值,該鍵則認(rèn)為為真(true)
RESULT? ? ? ? ? ? ? 上一個(gè)PROGRAM調(diào)用返回的標(biāo)準(zhǔn)輸出.
NAME? ? ? ? ? ? ? ? 根據(jù)這個(gè)規(guī)則創(chuàng)建的設(shè)備文件的文件名.
(注意:僅僅第一行的NAME描述是有效的,后面的均忽略.如果你想使用使用兩個(gè)以上的名字來(lái)訪問一個(gè)設(shè)備的話,可以考慮SYMLINK鍵.)
SYMLINK? ? ? ? ? ? ? 為 /dev/下的設(shè)備文件產(chǎn)生符號(hào)鏈接.由于 udev 只能為某個(gè)設(shè)備產(chǎn)生一個(gè)設(shè)備文件,
(所以為了不覆蓋系統(tǒng)默認(rèn)的 udev 規(guī)則所產(chǎn)生的文件,推薦使用符號(hào)鏈接.)
OWNER? ? ? ? ? ? ? ? 設(shè)備文件的屬組
GROUP? ? ? ? ? ? ? ? 設(shè)備文件所在的組.
MODE? ? ? ? ? ? ? ? 設(shè)備文件的權(quán)限,采用8進(jìn)制
RUN? ? ? ? ? ? ? ? ? 為設(shè)備而執(zhí)行的程序列表
LABEL? ? ? ? ? ? ? ? 在配置文件里為內(nèi)部控制而采用的名字標(biāo)簽(下下面的GOTO服務(wù))
GOTO? ? ? ? ? ? ? ? 跳到匹配的規(guī)則(通過(guò)LABEL來(lái)標(biāo)識(shí)),有點(diǎn)類似程序語(yǔ)言中的GOTO
IMPORT{ type}? ? ? ? 導(dǎo)入一個(gè)文件或者一個(gè)程序執(zhí)行后而生成的規(guī)則集到當(dāng)前文件
WAIT_FOR_SYSFS? ? ? 等待一個(gè)特定的設(shè)備文件的創(chuàng)建.主要是用作時(shí)序和依賴問題.
PTIONS? ? ? ? ? ? ? 特定的選項(xiàng):
last_rule? ? ? ? ? ? 對(duì)這類設(shè)備終端規(guī)則執(zhí)行;
ignore_device? ? ? ? 忽略當(dāng)前規(guī)則;
ignore_remove? ? ? ? 忽略接下來(lái)的并移走請(qǐng)求.
all_partitions? ? ? 為所有的磁盤分區(qū)創(chuàng)建設(shè)備文件.
udev一些特殊的值和替換值:
在鍵值對(duì)中的鍵和操作符都介紹完了,最后是值 (value).Linux 用戶可以隨意地定制 udev 規(guī)則文件的值.
例如:my_root_disk, my_printer.同時(shí)也可以引用下面的替換操作符:
----------------------------------------
$kernel,? ? ? %k:? ? ? 設(shè)備的內(nèi)核設(shè)備名稱,例如:sda、cdrom.
$number,? ? ? %n:? ? ? 設(shè)備的內(nèi)核號(hào)碼,例如:sda3 的內(nèi)核號(hào)碼是 3.
$devpath,? ? ? %p:? ? ? 設(shè)備的 devpath路徑.
$id,? ? ? ? ? %b:? ? ? 設(shè)備在 devpath里的 ID 號(hào).
$sysfs{file},? %s{file}: 設(shè)備的 sysfs里 file 的內(nèi)容.其實(shí)就是設(shè)備的屬性值.
$env{key},? ? %E{key}:? 一個(gè)環(huán)境變量的值.
$major,? ? ? ? %M:? ? ? ? 設(shè)備的 major 號(hào).
$minor,? ? ? %m:? ? ? ? 設(shè)備的 minor 號(hào).
$result,? ? ? %c:? ? ? ? PROGRAM 返回的結(jié)果
$parent,? ? ? %P:? ? ? ? 父設(shè)備的設(shè)備文件名.
$root,? ? ? ? %r:? ? ? ? udev_root的值,默認(rèn)是 /dev/.
$tempnode,? ? %N:? ? ? ? 臨時(shí)設(shè)備名.
%%:? ? ? ? ? 符號(hào) % 本身.
$$:? ? ? ? ? 符號(hào) $ 本身.
————————————————
原文鏈接:https://blog.csdn.net/xiaoliu5396/article/details/46531893
以下源碼用來(lái)讀取net link消息
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <asm/types.h>
//該頭文件需要放在netlink.h前面防止編譯出現(xiàn)__kernel_sa_family未定義
#include <sys/socket.h>?
#include <linux/netlink.h>
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<len;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;
}