How can enable udev sync successfully in docker?

本文介绍了解决 Docker 中 devicemapper 存储类型下 udevsync 功能不支持的问题。针对不同版本的 Docker 提供了详细的解决步骤,并验证了 udevsync 功能的正确启用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

问题:

1、How can enable udev sync successfully in docker? #13179

2、Dynamically linked docker binary reports devicemapper and Udev not supported #12925

3、devicemapper: set flags based on udev sync support #10203

4、Docker APT repository binary has devicemapper "Udev Sync Supported: false" #10705

5、docker不支持在使用devicemapper存储类型下打开Udev Sync功能?

 

 

解决方案:

 

对docker1.7.1版本的解决方法:
1、先检查是否为devicemapper没有支持udev_sync功能:dmsetup udevcookies。如果没有支持会提示要求以--enable-udev_sync方式重新编译devicemapper,可按2,3步骤重新编译devicemapper。
2、安装最新版本的libudev: apt-get install libudev-dev
3、下载lvm2源码:git clone -b v2_02_103 
https://git.fedorahosted.org/git/lvm2.git /usr/local/lvm2
指定--enable-udev_sync参数,重新编译安装devicemapper:./configure --enable-udev_sync & make device-mapper & make install_device-mapper
3、编译动态链接的docker程序:AUTO_GOPATH=1 ./hack/make.sh dynbinary
4、启动docker daemon时指定存储驱动器类型为devicemapper:./docker -d -D --storage-driver=devicemapper -b=my_br -H tcp://0.0.0.0:1234 -H unix:///var/run/docker.sock &
(-s 选项(storage-driver)是关键,其他按自己的情况来)
5、docker info查看结果中的Udev Sync Supported。

 

对最新版本的docker1.11:

编译出来后检查:

root@dev:/home/code/docker/docker/bundles/1.11.0-dev/dynbinary# ldd docker
        linux-vdso.so.1 =>  (0x00007ffe3997c000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f8dbc497000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f8dbc293000)
        libdevmapper.so.1.02 => /lib/libdevmapper.so.1.02 (0x00007f8dbc057000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8dbbcca000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f8dbc6b3000)
        libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f8dbbaaa000)
        libsepol.so.1 => /lib/x86_64-linux-gnu/libsepol.so.1 (0x00007f8dbb86a000)
        libudev.so.0 => /lib/x86_64-linux-gnu/libudev.so.0 (0x00007f8dbb65b000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f8dbb453000)

已经依赖libudev.so。


root@dev:/home/code/docker/docker/bundles/1.11.0-dev/dynbinary# dmsetup udevcookies
Cookie       Semid      Value      Last semop time           Last change time
0xd4dbe47    0          1          Fri Mar 25 21:09:29 2016  Fri Mar 25 21:09:29 2016
0xd4d1f0e    32769      1          Fri Mar 25 21:14:00 2016  Fri Mar 25 21:14:00 2016

已经有支持udev_sync的device-mapper。


root@dev:/home/code/docker/docker/bundles/1.11.0-dev/dynbinary# ./docker -d -D --storage-driver=devicemapper -b=my_br -H tcp://0.0.0.0:1234 -H unix:///var/run/docker.sock

root@dev:/home/code/docker/docker/bundles/1.11.0-dev/dynbinary# docker info
DEBU[0005] Calling GET /v1.19/info                     
DEBU[0005] Client and server don't have the same version (client: 1.7.1, server: 1.11.0-dev)
Containers: 0
Images: 0
Storage Driver: devicemapper
 Udev Sync Supported: true

(其他信息省略)

已经支持udev_sync了。(也可能和我之前重编译了device-mapper有关了)。

 

总结下来就一句话:只要device-mapper支持udev_sync,docker为动态链接依赖库即可。

 

 

 

Reference:

http://icarobichir.com.br/posts/building-a-dynamically-linked-docker-v-1-6-2/

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/udev_commands_interfaces.html

 

 

<think>我们要解决两个问题:1.如何通过udev规则为串口设备分配固定的设备名称2.如何在C程序中动态读取该名称(即从用户输入获取,或者从某个配置文件读取)首先,我们解决第一个问题:使用udev规则固定串口设备名称。###步骤1:创建udev规则在Linux系统中,udev规则可以用来管理设备的命名。我们可以通过设备的属性(如供应商ID、产品ID、序列号等)来为设备分配一个固定的名称。假设我们有一个USB转串口设备,通常被系统识别为`/dev/ttyACM0`或`/dev/ttyUSB0`等,我们希望给它一个固定的名称,比如`/dev/my_custom_serial`。####操作步骤:1.首先,连接设备,使用`lsusb`命令找到设备的供应商ID和产品ID。例如:```$lsusb...Bus001Device004:ID0403:6001FutureTechnologyDevicesInternational,LtdFT232Serial(UART)IC...```这里,ID后面的`0403:6001`就是供应商ID和产品ID。2.使用`udevadminfo`命令获取更多设备信息(需要知道设备当前路径,假设为`/dev/ttyUSB0`):```$udevadminfo-a-p$(udevadminfo-qpath-n/dev/ttyUSB0)```在输出中,我们可以找到一些属性,比如`ATTRS{idVendor}`,`ATTRS{idProduct}`,`ATTRS{serial}`等。3.在`/etc/udev/rules.d/`目录下创建一个新的规则文件,例如`99-usb-serial.rules`:```$sudonano/etc/udev/rules.d/99-usb-serial.rules```4.在文件中添加规则,例如:```SUBSYSTEM=="tty",ATTRS{idVendor}=="0403",ATTRS{idProduct}=="6001",ATTRS{serial}=="A101D7VD",SYMLINK+="my_custom_serial"```这里:-`SUBSYSTEM=="tty"`表示设备属于tty子系统。-`ATTRS{idVendor}=="0403"`和`ATTRS{idProduct}=="6001"`分别对应供应商ID和产品ID。-`ATTRS{serial}=="A101D7VD"`是设备的序列号(可选,但如果有多个相同型号的设备,用序列号可以区分)。-`SYMLINK+="my_custom_serial"`表示创建一个符号链接`/dev/my_custom_serial`指向实际的设备文件(比如`/dev/ttyUSB0`)。注意:如果没有序列号,可以省略,但这样如果有多个相同厂商和产品的设备插入时,规则可能会同时匹配多个设备,导致不可预知的行为。5.重新加载udev规则并触发:```$sudoudevadmcontrol--reload-rules$sudoudevadmtrigger```6.重新插拔设备,然后检查`/dev/my_custom_serial`是否存在:```$ls-l/dev/my_custom_serial```这样,无论设备被系统分配为`ttyUSB0`还是`ttyACM0`,我们都可以通过`/dev/my_custom_serial`访问。###步骤2:在C程序中动态读取设备名称在程序中,我们可以让用户输入这个固定的设备名称(如`my_custom_serial`),或者我们也可以直接在程序中使用这个固定的名称。但是注意,由于我们创建的是符号链接,所以在程序中我们可以直接使用`/dev/my_custom_serial`。但是,为了灵活性,我们可以让程序从命令行参数读取设备路径。####修改原始程序:原始程序中使用宏定义`MODEMDEVICE`固定为`"/dev/ttyACM13"`,现在我们要修改为从命令行参数获取。修改后的主函数如下(简化示例):```cintmain(intargc,char*argv[]){intfd,res;structtermiosoldtio,newtio;char*command="smartconfig1\r\n";//检查命令行参数if(argc<2){fprintf(stderr,"Usage:%s<serial_port>\n",argv[0]);exit(EXIT_FAILURE);}constchar*device=argv[1];//从命令行参数获取设备名fd=open(device,O_RDWR|O_NOCTTY|O_NDELAY);if(fd<0){perror(device);exit(EXIT_FAILURE);}//...后续代码不变...return0;}```这样,在运行程序时,我们只需要传递固定好的设备名称即可:```bash./program/dev/my_custom_serial```或者,如果我们不想每次运行都输入设备名,也可以将设备名写入配置文件,程序从配置文件读取。###示例:从配置文件读取我们可以创建一个简单的配置文件(如`config.ini`),内容为:```SERIAL_PORT=/dev/my_custom_serial```然后在程序中读取这个文件,解析出设备名。这里我们可以使用简单的文件读取和字符串处理,或者使用现成的库(如`iniparser`)。但考虑到简单性,这里采用命令行参数的方式更直接。###总结1.通过udev规则为串口设备创建固定名称的符号链接。2.修改C程序,从命令行参数获取设备路径(或从配置文件读取)。这样,即使系统分配的原始设备名发生变化(比如不同的USB端口插入后分配的编号不同),我们仍可以通过固定名称访问设备,而程序只需要使用这个固定名称即可。###相关问题1.如何调试udev规则?2.如果多个相同型号的USB串口设备同时插入,如何为每个设备分别指定不同的固定名称?3.在C程序中如何优雅地处理串口连接失败的情况?</think> ### 如何通过udev规则固定串口设备名称并在C程序中动态读取 以下是完整的实现方案,分为两个核心部分: #### 第一部分:创建udev规则固定设备名 1. **获取设备识别信息** ```bash udevadm info -a -n /dev/ttyACM0 | grep -E '({idVendor}|{idProduct}|{serial})' # 输出示例: # ATTRS{idVendor}=="0403" # ATTRS{idProduct}=="6010" # ATTRS{serial}=="A101D7VD" ``` 2. **创建udev规则文件** ```bash sudo nano /etc/udev/rules.d/99-usb-serial.rules ``` 添加规则(替换为你的实际参数): ```bash SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ATTRS{serial}=="A101D7VD", SYMLINK+="my_custom_serial" ``` 3. **应用规则** ```bash sudo udevadm control --reload-rules sudo udevadm trigger ``` 4. **验证结果** ```bash ls -l /dev/my_custom_serial # 输出示例:/dev/my_custom_serial -> ttyACM0 ``` #### 第二部分:修改C程序动态读取设备名 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <time.h> #define BAUDRATE B9600 #define FALSE 0 #define TRUE 1 volatile int STOP = FALSE; int wait_for_ok(int fd) { /* 原有实现保持不变 */ } void listen_for_data(int fd) { /* 原有实现保持不变 */ } int main(int argc, char *argv[]) { // 修改1:添加命令行参数处理 int fd, res; struct termios oldtio, newtio; char *command = "smartconfig 1\r\n"; // 修改2:命令行参数校验 if(argc != 2) { fprintf(stderr, "用法: %s <串口设备路径>\n", argv[0]); fprintf(stderr, "示例: %s /dev/ttyACM0\n", argv[0]); fprintf(stderr, "或使用固定名称: %s /dev/my_custom_serial\n", argv[0]); exit(EXIT_FAILURE); } // 修改3:使用动态设备路径 char *device_path = argv[1]; printf("正在打开串口: %s\n", device_path); fd = open(device_path, O_RDWR | O_NOCTTY | O_NDELAY); if (fd < 0) { perror(device_path); exit(EXIT_FAILURE); } /* 后续原有代码保持不变... */ tcgetattr(fd, &oldtio); /* ... */ } ``` #### 使用示例 1. **编译程序** ```bash gcc serial_program.c -o serial_program ``` 2. **使用固定设备名运行** ```bash ./serial_program /dev/my_custom_serial ``` 3. **使用动态设备名运行** ```bash ./serial_program /dev/ttyACM0 ``` ### 关键原理说明 1. **udev规则工作原理** - 当检测到符合`ATTRS`标准的设备时,创建`SYMLINK`符号链接 - 符号链接名称在规则中定义(示例:`my_custom_serial`) - 匹配条件基于设备的唯一标识:$ \text{idVendor} \times \text{idProduct} \times \text{serial} $ 2. **程序动态路径处理** - 通过`main(int argc, char *argv[])`获取命令行参数 - `argv[1]`存储用户输入的设备路径 - 使用前校验参数数量:$ \text{argc} == 2 $ ### 相关问题 1. 当多个相同型号的串口设备同时连接时,如何为每个设备分别创建唯一标识的udev规则?[^1] 2. 如何让C程序在udev设备插入时自动启动并连接串口?[^2] 3. 在Linux系统中,$ \text{/dev/ttyACM} $ 和 $ \text{/dev/ttyUSB} $ 设备节点有何区别?[^3] 4. 当使用固定设备名时,如何确保程序在设备未插入时优雅地处理错误?[^4] [^1]: 基于 udev 的设备序列号匹配机制 [^2]: 结合 udev 规则与 systemd 服务 [^3]: Linux 内核的 USB 串行设备驱动架构 [^4]: POSIX 文件操作错误处理规范
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值