1. 程式人生 > >linux中udev簡單的用法

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;
}