linux中udev簡單的用法
udev是linux提供的一種在使用者態管理裝置的一種機制,udev的詳細使用方法可參考其他資料,這裡推薦http://blog.csdn.net/fjb2080/article/details/4876314,這裡總結一下我在學習過程中對udev的簡單應用:
我要實現的是在我的u盤插入時,利用udev實現自動掛載至指定目錄,並且實現我想要的相關功能,我的系統是ubuntu14.04:
1.先插入u盤,輸入sudo fdisk -l,觀察到u盤的資訊如下:
裝置 啟動 起點 終點 塊數 Id 系統
/dev/sdb4 * 256 15663103 7831424 b W95 FAT32
2.在/etc/udev/rules.d下建立檔案10-usb.rules,內容如下:
SUBSYSTEM=="block", KERNEL=="sdb4", ACTION=="add", NAME="Myusb", SYMLINK+="Myusb_link", RUN+="/bin/bash /home/usbadd.sh"
SUBSYSTEM=="block", KERNEL=="sdb4", ACTION=="remove", RUN+="/bin/bash /home/usbremove.sh"
udev規則檔案的編寫方法可參考udev官方文件,這裡對上述內容作簡單說明:
當插入裝置(ACTION=="add")在kernel中裝置名為sdb4(KERNEL=="sdb4"),且為塊裝置(SUBSYSTEM=="block"),滿足以上三個條件時,對裝置檔案命名為Myusb(NAME="Myusb"),並建立軟連結Myusb_link(SYMLINK+="Myusb_link"),同時執行/home/usbadd.sh指令碼(RUN+="/bin/bash /home/usbadd.sh")。
其中sdb4就是通過fdisk -l檢視得到的,軟連結會在/dev下建立,名字可以自定義(以後無論插入任何u盤都可以以同一名字來訪問),usbadd.sh指令碼中可以編寫你想實現的任何內容,我的內容是將u盤掛載到/mnt/usb目錄下:
#!/bin/bash
if [ ! -d /mnt/usb ];then
sudo mkdir -p /mnt/usb
fi
sudo mount /dev/Myusb_link /mnt/usb
當裝置拔出時,執行/home/usbremove.sh指令碼解除安裝u盤:
#!/bin/bash
if [ -d /mnt/usb ];then
sudo umount /mnt/usb
sudo rm -r /mnt/usb
fi
3.當規則檔案和執行指令碼編寫完成後即可進行測試,我在測試中發現,當插入u盤時,ls /dev/下檢視發現u盤裝置名依舊為sdb4,Myusb_link軟連結指向sdb4,其中原因還有待研究,但是我在CentOS 6.4系統下測試發現,自定義的裝置檔名Myusb取代了sdb4。
此外,還可以通過udevadm工具來管理udev,udevadm相關用法見:http://blog.csdn.net/yangzhongxuan/article/details/11113431
4.udev本身是通過netlink與核心進行socket通訊的,下面附上一個簡單的捕獲netlink訊息的小程式:
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define UEVENT_BUFFER_SIZE 2048
static int init_hotplug_sock()
{
const int buffersize = 1024;
int ret;
struct sockaddr_nl snl;
bzero(&snl, sizeof(struct sockaddr_nl));
snl.nl_family = AF_NETLINK;
snl.nl_pid = getpid();
snl.nl_groups = 1;
int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if (s == -1)
{
perror("socket");
return -1;
}
setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));
if (ret < 0)
{
perror("bind");
close(s);
return -1;
}
return s;
}
int main(int argc, char* argv[])
{
int hotplug_sock = init_hotplug_sock();
while(1)
{
/* Netlink message buffer */
char buf[UEVENT_BUFFER_SIZE * 2] = {0};
recv(hotplug_sock, &buf, sizeof(buf), 0);
printf("%s\n", buf);
/* USB 裝置的插拔會出現字元資訊,通過比較不同的資訊確定特定裝置的插拔,在這新增比較程式碼 */
}
return 0;
}