Nhận nút thiết bị theo cặp số chính / phụ


12

Mỗi nút thiết bị dưới /devcó cặp số chính / phụ riêng. Tôi biết rằng chúng ta có thể truy xuất cặp số này từ nút thiết bị bằng cách này stat, như thế này:

stat -c 'major: %t minor: %T' <file>

Hoặc, ls -lcũng cho thấy những con số này.

Nhưng làm thế nào chúng ta có thể có được (các) nút thiết bị bằng các số chính và số phụ? Cách duy nhất tôi biết là một số mẹo ls -l+ awk, nhưng tôi thực sự hy vọng có giải pháp tốt hơn.


@mikeerv, vâng Tôi biết rằng một số thiết bị có thể chia sẻ những con số này, vì vậy trong câu hỏi ban đầu của tôi, tôi đã đề cập: "lấy (các) nút thiết bị". Lý tưởng nhất là tôi muốn có một danh sách với tất cả các nút thiết bị có số chính / số phụ khớp nhau, một nút trên mỗi dòng. Thật kỳ lạ, chúng tôi không có một công cụ sẵn sàng cho việc đó. Cảm ơn câu trả lời btw!
Dmitry Frank

Câu trả lời:


7

Tôi đã tìm thấy một cách tiếp cận đơn giản hơn bằng cách sử dụng hệ thống pseudofilesystem, tại / sys / dev bạn có các thiết bị được sắp xếp theo loại rồi theo chính / phụ, tệp uevent chứa tên thiết bị và một loạt thông tin khác.

Ví dụ,

  for file in $(find /sys/dev/ -name 7:0); do  
      source ${file}/uevent; echo $DEVNAME;
  done;

Tiếng vang,

loop0
vcs

Lưu ý: Điều này đã được thử nghiệm trong Debian Wheezy


để tìm ngược từ tên nhà phát triển:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
BBK

5

Không chắc chắn những gì bạn có ý nghĩa.

mknod foo b 8 0

Sẽ tạo tệp thiết bị được gọi foolà thiết bị khối có 8 chính và phụ 0. Nếu bạn muốn tìm một hoặc bất kỳ tệp /devnào có cùng loại, chính và phụ, bạn có thể thực hiện (với zsh):

  • Đối với thiết bị khối 8:0:

    $ zmodload zsh/stat
    $ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
    lrwxrwxrwx 1 root root    6 Aug 23 05:28 /dev/block/8:0 -> ../sda
    lrwxrwxrwx 1 root root    9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
    brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda
    
  • cho thiết bị char 226:0:

    $ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
    lrwxrwxrwx  1 root root      12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
    crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0
    

Lưu ý rằng bất cứ điều gì có thể tạo tập tin trong /dev. Ngày xưa, nó là một tập lệnh tạo các tệp tĩnh trong đó. Tại một số điểm, bạn thậm chí đã có một hệ thống tập tin đặc biệt à la /proc.

Trên các phiên bản Linux hiện đại, nó thường udevdựa trên đầu vào từ kernel.

Tên nó chọn cho tệp thiết bị cơ sở dựa trên tên DEVNAMEđược cung cấp bởi kernel. udevcác quy tắc có thể thay đổi điều đó nhưng thường thì không, và một số udevquy tắc sẽ thêm một số liên kết tượng trưng cho thuận tiện (như các quy /dev/disk/by...tắc).

Bạn có thể đi từ chính: nhỏ đến kernel DEVNAMEbằng cách xem:

$ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
sda
$ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
dri/card0

Bạn cũng có thể lấy thông tin đó từ udevcơ sở dữ liệu như mikeerv đã hiển thị.


5

Rõ ràng nó có thể được thực hiện đơn giản hơn với udevadm, và tôi đã tìm ra cách.

Để có được DEVNAMEtừ udevadmbạn chỉ cần làm:

udevadm info -rq name $PATH

Chẳng hạn, nếu bạn muốn biết /devtên cho /sys/dev/char/5:1bạn:

udevadm info -rq name /sys/dev/char/5:1

ĐẦU RA

/dev/console

Các -rtùy chọn là để xác định một --rootcon đường ed - mà không có nó kết quả trên sẽ chỉ đọc console. Các -qtùy chọn chỉ định một cơ sở dữ liệu --queryvà phải mất các toán hạng nameở đây - bởi vì chúng tôi muốn DEVNAME.

Một phương tiện rất đơn giản để tìm đường dẫn đến thiết bị char và / hoặc khối chỉ được cung cấp chính: số phụ có thể trông như sau:

mmdev() for d in /sys/dev/[cb]*/$1:$2
        do  [ -e "$d" ] || return
            printf %c:%s: "${d#/*/*/}" "${d##*/}"
            udevadm info -rq name "$d"
        done

Vì vậy, chạy:

mmdev 8 0

in ...

b:8:0:/dev/sda

Đây là bài đầu tiên tôi viết.

majminpath() {
    set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
    udevadm info --export-db |
    sed 's|^[^=]*DEVNAME=||
         \|^[^/]|!h;/MAJOR=/N
         \|='"$1\n.*=${2?}"'$|!d;g'
}

Điều này chỉ quét udevadm info --export-dbđầu ra cho các số phù hợp. Đầu ra trông như sau:

P: /devices/virtual/vc/vcsa4
N: vcsa4
E: DEVNAME=/dev/vcsa4
E: DEVPATH=/devices/virtual/vc/vcsa4
E: MAJOR=7
E: MINOR=132
E: SUBSYSTEM=vc

P: /devices/virtual/vc/vcsa5
N: vcsa5
E: DEVNAME=/dev/vcsa5
E: DEVPATH=/devices/virtual/vc/vcsa5
E: MAJOR=7
E: MINOR=133
E: SUBSYSTEM=vc

#...and so on

Quy trình công việc giống như:

  • cố gắng tước [^=]*DEVNAME=chuỗi từ đầu của mỗi dòng

  • nếu một dòng không có ký tự đầu tiên hoặc ký tự đầu tiên của nó được /sao chép dòng đó trên hkhông gian cũ

  • nếu một dòng khớp với MAJOR=nối thêm Ndòng đầu vào ext vào không gian mẫu

  • nếu có 2 dòng trong không gian mẫu khớp với nhau =$1\n.*=$2$thì sao chép hkhông gian cũ trên không gian mẫu và tự động in; khác xóa không gian mẫu

Vì vậy, nếu tôi làm:

majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1

ĐẦU RA

/dev/vcsa5
/dev/sda
/dev/sda1

Nhưng, như @xae chỉ ra, các thiết bị kiểu khối / char có thể chia sẻ các kết hợp chính: tối thiểu và do đó, điều này có thể có thể in nhiều hơn một đường dẫn cho mỗi cuộc gọi.


1
Thật không may, nó không dễ dàng như vậy, một khối và một thiết bị nhân vật có thể chia sẻ cùng một số chính. Hãy xem tập tin / Proc / thiết bị.
xae

Tôi phải kiểm tra hệ thống con - đúng vậy. Cảm ơn, @xae.
mikeerv

1

Than ôi , /sys/devhierachy chỉ được thêm vào kernel muộn nhất là 2.6,27 ( xem cam kết có liên quan chống lại codebase kernel), vì vậy chúng ta cần một cách tiếp cận bifurcated.

Đặt $M$m, tương ứng, là số chính và số phụ của tệp thiết bị của chúng tôi.

Bài 2.6,27 hạt nhân

Theo đề xuất của những người khác, cách tiếp cận đơn giản nhất sẽ giải phóng sức mạnh của sysfshệ thống tệp ảo ảo, bằng cách truy tìm thẳng các tệp có tên $M:$mtrong thư mục /sys/dev(sẽ có nhiều hơn một tệp nếu chúng ta không biết liệu thiết bị của mình có phải là ký tự không hoặc một khối dựa trên khối), sau đó tìm nguồn của ueventtệp (trong một lớp con để tránh ô nhiễm không gian tên):

for file in $(find /sys/dev/ -name $M:$m)
do
    (
        source ${file}/uevent
        echo $DEVNAME
    )
done

Trước 2.6,27 hạt nhân

Chúng ta hãy giả sử, vì đơn giản, tệp của chúng tôi là một thiết bị khối (một cách tiếp cận tương tự áp dụng cho các thiết bị ký tự). Chúng tôi sẽ tìm kiếm chuỗi $M:$mtrong toàn bộ /sys/blockphân cấp, bằng cách kiểm tra (bên dưới thư mục đó) nội dung của mỗi tệp có tên xảy ra dev. Nếu /sys/block/<...>/<DEV>/devlà một tệp như vậy, thì nhất định DEVlà tên thiết bị của chúng tôi:

dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"

0

Trên Linux, có thể tận dụng một số tệp nhất định trong /prochệ thống tệp ảo.

$ grep '8[[:blank:]]\+1[[:blank:]]\+' /proc/partitions 
   8        1   29309568 sda1

$ grep '8:1[[:blank:]]' /proc/self/mountinfo 
28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered

Dạng đơn giản của mẫu đã cung cấp thông tin về thiết bị mong muốn ở đầu ra, tuy nhiên cũng có thể lọc thêm để trích xuất một chuỗi cụ thể.


0

Có chức năng thư viện: makedev()

#include <sys/sysmacros.h>
dev_t makedev(unsigned int maj, unsigned int min);

Với các ID thiết bị chính và phụ, makenev () kết hợp các ID này để tạo ID thiết bị, được trả về làm kết quả chức năng.

Để biết thêm chi tiết, hãy truy cập: http://man7.org/linux/man-pages/man3/major.3.html

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.