當udev提示如下報錯時案狠,內核配置中選中INOTIFY_USER即可。
udevd[992]: inotify_init failed: Function not implemented
udev規(guī)則文件示例(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"?
要執(zhí)行的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規(guī)則匹配表:
鍵? ? ? ? ? ? ? ? 含義
----------------------------------------
ACTION? ? ? ? ? ? ? 事件 (uevent) 的行為,例如:add( 添加設備 )鹃祖、remove( 刪除設備 ).
KERNEL? ? ? ? ? ? ? 在內核里看到的設備名字,比如sd*表示任意SCSI磁盤設備
DEVPATH? ? ? ? ? ? ? 內核設備錄進,比如/devices/*
SUBSYSTEM? ? ? ? ? ? 子系統(tǒng)名字,例如:sda 的子系統(tǒng)為 block.
BUS? ? ? ? ? ? ? ? ? 總線的名字,比如IDE,USB
DRIVER? ? ? ? ? ? ? 設備驅動的名字,比如ide-cdrom
ID? ? ? ? ? ? ? ? ? 獨立于內核名字的設備名字
SYSFS{ value}? ? ? ? sysfs屬性值,他可以表示任意
ENV{ key}? ? ? ? ? ? 環(huán)境變量,可以表示任意
PROGRAM? ? ? ? ? ? ? 可執(zhí)行的外部程序,如果程序返回0值,該鍵則認為為真(true)
RESULT? ? ? ? ? ? ? 上一個PROGRAM調用返回的標準輸出.
NAME? ? ? ? ? ? ? ? 根據(jù)這個規(guī)則創(chuàng)建的設備文件的文件名.
(注意:僅僅第一行的NAME描述是有效的,后面的均忽略.如果你想使用使用兩個以上的名字來訪問一個設備的話,可以考慮SYMLINK鍵.)
SYMLINK? ? ? ? ? ? ? 為 /dev/下的設備文件產生符號鏈接.由于 udev 只能為某個設備產生一個設備文件,
(所以為了不覆蓋系統(tǒng)默認的 udev 規(guī)則所產生的文件,推薦使用符號鏈接.)
OWNER? ? ? ? ? ? ? ? 設備文件的屬組
GROUP? ? ? ? ? ? ? ? 設備文件所在的組.
MODE? ? ? ? ? ? ? ? 設備文件的權限,采用8進制
RUN? ? ? ? ? ? ? ? ? 為設備而執(zhí)行的程序列表
LABEL? ? ? ? ? ? ? ? 在配置文件里為內部控制而采用的名字標簽(下下面的GOTO服務)
GOTO? ? ? ? ? ? ? ? 跳到匹配的規(guī)則(通過LABEL來標識),有點類似程序語言中的GOTO
IMPORT{ type}? ? ? ? 導入一個文件或者一個程序執(zhí)行后而生成的規(guī)則集到當前文件
WAIT_FOR_SYSFS? ? ? 等待一個特定的設備文件的創(chuàng)建.主要是用作時序和依賴問題.
PTIONS? ? ? ? ? ? ? 特定的選項:
last_rule? ? ? ? ? ? 對這類設備終端規(guī)則執(zhí)行躏吊;
ignore_device? ? ? ? 忽略當前規(guī)則钓猬;
ignore_remove? ? ? ? 忽略接下來的并移走請求.
all_partitions? ? ? 為所有的磁盤分區(qū)創(chuàng)建設備文件.
udev一些特殊的值和替換值:
在鍵值對中的鍵和操作符都介紹完了,最后是值 (value).Linux 用戶可以隨意地定制 udev 規(guī)則文件的值.
例如: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}:? 一個環(huán)境變量的值.
$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 <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;
}