주 / 부 숫자 쌍으로 장치 노드 가져 오기


12

아래의 각 장치 노드 /dev에는 고유 한 주 / 부 번호 쌍이 있습니다. 우리는 다음 stat과 같은 방법으로 장치 노드 에서이 숫자 쌍을 검색 할 수 있음을 알고 있습니다 .

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

또는 ls -l이 숫자도 표시합니다.

그러나 주어진 메이저 번호와 마이너 번호로 장치 노드를 어떻게 얻을 수 있습니까? 내가 아는 유일한 방법은 일종의 ls -l+ awk트릭이지만, 더 나은 해결책이 있기를 바랍니다.


@ mikeserv, 그렇습니다. 일부 장치는이 숫자를 공유 할 수 있다는 것을 알고 있으므로 초기 질문에서 "get device node (s)"를 언급했습니다. 이상적으로는 주 / 부 숫자가 일치하는 모든 장치 노드와 줄 당 하나의 노드가있는 목록을 얻고 싶습니다. 우리에게는 그에 대한 준비된 도구가 없다는 것이 이상합니다. 답변 btw 주셔서 감사합니다!
Dmitry Frank

답변:


7

내가 사용하는 간단한 방법을 발견 SYS 에서 pseudofilesystem을 / SYS / dev에 당신이 다음 주 / 단조에 의해, 파일 유형에 따라 정렬 장치가 uevent이 장치의 이름과 기타 정보의 무리가 포함되어 있습니다.

예를 들어

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

메아리,

loop0
vcs

참고 : 이것은 Debian Wheezy에서 테스트되었습니다.


dev 이름에서 거꾸로 찾기 :for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
BBK

5

당신이 무슨 뜻인지 확실하지.

mknod foo b 8 0

foo메이저 8과 마이너 0을 가진 블록 장치 라고하는 장치 파일을 생성합니다 /dev. 메이저와 마이너 유형이 같은 파일에서 하나 또는 하나의 파일을 찾으려는 경우 다음 과 같이 할 수 있습니다 zsh.

  • 블록 장치의 경우 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
    
  • 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
    

모든 파일은에서 파일을 만들 수 있습니다 /dev. 예전에는 정적 파일을 작성하는 스크립트였습니다. 언젠가는 특별한 파일 시스템을 가지고있었습니다 /proc.

최신 버전의 Linux에서는 일반적 udev으로 커널의 입력을 기반으로합니다.

기본 장치 파일에 대해 선택한 이름 DEVNAME은 커널 에서 제공 한 이름을 기반으로합니다 . udev규칙은 변경 될 수 있지만 일반적으로 변경되지는 않으며 일부 udev규칙은 편의를 위해 심볼릭 링크를 추가합니다 (예 : 규칙 /dev/disk/by...).

다음 DEVNAME을보고 major : minor에서 kernel로 이동할 수 있습니다 .

$ 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

udevmikeserv가 표시 한대로 데이터베이스 에서 해당 정보를 얻을 수도 있습니다 .


5

분명히 더 간단하게 할 수 있으며 udevadm방금 방법을 찾았습니다.

DEVNAME에서 udevadm당신 을 얻기 위해 필요한 것만 :

udevadm info -rq name $PATH

예를 들어, /dev이름 을 알고 /sys/dev/char/5:1싶다면 다음을 수행하십시오.

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

산출

/dev/console

-r옵션을 지정하는 것입니다 --root읽기 전용 것 이상없이 결과를 - 에드 경로를 console. 이 -q옵션은 데이터베이스를 지정하고 여기 --query에 피연산자 name가 필요합니다 DEVNAME.

메이저 : 마이너 번호 만 주어진 char 및 / 또는 블록 장치의 경로를 찾는 매우 간단한 방법은 다음과 같습니다.

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

그래서 달리기 :

mmdev 8 0

인쇄물...

b:8:0:/dev/sda

내가 쓴 첫 번째 내용은 다음과 같습니다.

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

udevadm info --export-db일치하는 숫자에 대한 출력 만 스캔 합니다. 결과는 다음과 같습니다.

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

워크 플로우는 다음과 같습니다.

  • [^=]*DEVNAME=각 줄의 머리 에서 끈 을 제거하십시오

  • 행에 첫 번째 문자가 없거나 첫 번째 문자가 이전 /행에 해당 행을 복사 한 경우h

  • 라인이 일치 하면 패턴 공간에 다음 입력 라인을 MAJOR=추가하십시오.N

  • 패턴 공간에 일치하는 두 줄이 있으면 패턴 공간 위에 이전 공간 =$1\n.*=$2$을 복사 h하고 자동 인쇄합니다. 그렇지 않으면 패턴 공간을 삭제하십시오.

그래서 내가하면 :

majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1

산출

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

그러나 @xae가 지적한 것처럼 블록 / 문자 유형 장치는 maj : min 조합을 공유 할 수 있으므로 호출 당 둘 이상의 경로를 인쇄 할 수 있습니다.


1
불행히도 그렇게 쉬운 일이 아닙니다. 블록과 캐릭터 장치는 동일한 주요 숫자를 공유 할 수 있습니다. / proc / devices 파일을 살펴보십시오.
xae

나는 서브 시스템을 점검해야한다-맞다. 감사합니다, @xae.
mikeserv

1

아아 , /sys/dev계층은 2.6.27 ( 커널 코드베이스에 대한 관련 커밋 참조) 까지만 커널에 추가 되었으므로 "분할 된"접근법이 필요합니다.

하자 $M$m각각 우리의 장치 파일의 메이저와 마이너 숫자.

2.6.27 커널 이후

다른 사람들이 제안한 것처럼 가장 간단한 방법 은 폴더 아래에 sysfs이름이 지정된 파일을 바로 추적 하여 "가상"파일 시스템 $M:$m의 성능을 제공합니다 /sys/dev(기기가 문자인지 여부를 알 수없는 경우 하나 이상의 파일이 예상 됨) 또는 블록 기반 uevent파일 ), 그런 다음 파일 을 소싱하여 (네임 스페이스 오염을 방지하기 위해 서브 쉘에서) :

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

2.6.27 이전 커널

간단히하기 위해 파일이 블록 장치 라고 가정 합니다 (유사한 장치에도 비슷한 접근 방식이 적용됨). 우리는 이름이 발생하는 모든 파일의 내용을 (폴더 아래) 검사 $M:$m하여 /sys/block계층 전체 에서 문자열을 검색 합니다 dev. /sys/block/<...>/<DEV>/dev그러한 파일 중 하나 인 경우 DEV장치 이름으로 바인딩됩니다.

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

0

Linux에서는 /proc가상 파일 시스템 의 특정 파일을 활용할 수 있습니다 .

$ 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

패턴의 간단한 형식은 이미 출력에서 ​​원하는 장치에 대한 정보를 제공하지만 하나의 특정 문자열 만 추출하기위한 추가 필터링도 가능합니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.