รับโหนดอุปกรณ์โดยการจับคู่หมายเลขหลัก / รอง


12

แต่ละโหนดอุปกรณ์ภายใต้/devมีคู่หลัก / รองหมายเลขของตัวเอง ฉันรู้ว่าเราสามารถดึงหมายเลขคู่นี้จากโหนดอุปกรณ์โดยวิธีstatดังนี้:

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

หรือls -lแสดงตัวเลขเหล่านี้ด้วย

แต่เราจะได้รับโหนดอุปกรณ์โดยการระบุหมายเลขหลักและรองได้อย่างไร วิธีเดียวที่ฉันรู้คือเคล็ดลับls -l+ บางอย่างawkแต่ฉันหวังว่าจะมีวิธีแก้ปัญหาที่ดีกว่า


@mikeserv ใช่ฉันรู้ว่าอุปกรณ์บางอย่างสามารถแบ่งปันตัวเลขเหล่านี้ได้ดังนั้นในคำถามแรกที่ฉันได้กล่าวถึง: "get node 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
    
  • สำหรับอุปกรณ์ถ่าน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กฎจะเพิ่ม symlink เพิ่มเติมเพื่อความสะดวก (เช่นเดียวกับกฎ/dev/disk/by...)

คุณสามารถเปลี่ยนจากหลัก: รองลงมาเป็นเคอร์เนลได้DEVNAMEโดยดูที่:

$ 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

นอกจากนี้คุณยังสามารถรับข้อมูลจากudevฐานข้อมูลตามที่ mikeserv แสดง


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 และ / หรือ block ที่กำหนดเฉพาะหลัก: ตัวเลขเล็กน้อยอาจมีลักษณะดังนี้:

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บรรทัดอินพุตเข้ากับพื้นที่รูปแบบ

  • หากมี 2 บรรทัดในพื้นที่รูปแบบที่ตรงกัน=$1\n.*=$2$จากนั้นคัดลอกhพื้นที่เก่าบนพื้นที่รูปแบบและพิมพ์อัตโนมัติ อื่นลบพื้นที่รูปแบบ

ดังนั้นถ้าฉันทำ:

majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1

เอาท์พุท

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

แต่ตามที่ @xae ชี้ให้เห็นว่าอุปกรณ์ประเภท block / char สามารถแชร์ maj: min ชุดค่าผสมและดังนั้นสิ่งนี้อาจพิมพ์มากกว่าหนึ่งเส้นทางต่อการโทร


1
น่าเสียดายที่มันไม่ง่ายเลยบล็อกและอุปกรณ์ตัวอักษรสามารถแบ่งปันหมายเลขหลักเดียวกันได้ ลองดูที่ไฟล์ / proc / อุปกรณ์
xae

ฉันต้องตรวจสอบระบบย่อย - ใช่แล้ว ขอบคุณ @xae
mikeserv

1

อนิจจาที่/sys/devลำดับชั้นถูกเพิ่มเข้ามาเท่านั้นที่จะเคอร์เนลเป็นปลาย 2.6.27 ( cf เลยที่เกี่ยวข้องกระทำผิด codebase kernel) ดังนั้นเราจึงจำเป็นต้องมี“bifurcated” วิธีการ

อนุญาต$Mและ$mตามลำดับเป็นไฟล์อุปกรณ์หลักของเราและไฟล์รอง

โพสต์ 2.6.27 เมล็ด

ตามที่ผู้อื่นแนะนำวิธีที่ง่ายที่สุดจะปลดปล่อยพลังของsysfsระบบไฟล์ "เสมือน" โดยการไล่ตามไฟล์ที่มีชื่อ$M:$mภายใต้โฟลเดอร์/sys/dev(จะต้องมีมากกว่าหนึ่งไฟล์ถ้าเราไม่รู้ว่าอุปกรณ์ของเราเป็นตัวอักษรหรือไม่ - หรือบล็อกที่ใช้บล็อก) จากนั้นทำการจัดหาueventไฟล์ (ใน subshell เพื่อป้องกันมลภาวะในเนมสเปซ):

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

Pre 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

รูปแบบที่เรียบง่ายของรูปแบบให้ข้อมูลเกี่ยวกับอุปกรณ์ที่ต้องการในการส่งออกแล้วอย่างไรก็ตามการกรองเพิ่มเติมเพื่อแยกเพียงหนึ่งสตริงโดยเฉพาะก็สามารถทำได้เช่นกัน


0

มีฟังก์ชั่นห้องสมุด: makedev()

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

รับรหัสอุปกรณ์หลักและรอง makedev () รวมเหล่านี้เพื่อสร้างรหัสอุปกรณ์ส่งกลับเป็นผลการทำงาน

สำหรับรายละเอียดเพิ่มเติมเยี่ยมชม: http://man7.org/linux/man-pages/man3/major.3.html

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.