2011-04-01 39 views
5

我想知道/ dev文件所在的哪個條目。例如,如果/ dev/sdc1掛載在/ media/disk下,並且我要求/ media/disk/foo.txt,我想以/ dev/sdc作爲迴應。Linux編程:文件位於哪個設備

使用stat系統調用該文件我將得到它的分區主要和次要號碼(8和33,對於sdc1)。現在我需要從中獲取「根」設備(sdc)或其主要/次要設備。是否有任何系統調用或庫函數我可以用來將分區鏈接到它的主設備?或者甚至更好,直接從文件中獲取該設備?

brw-rw---- 1 root floppy 8, 32 2011-04-01 20:00 /dev/sdc 
brw-rw---- 1 root floppy 8, 33 2011-04-01 20:00 /dev/sdc1 

在此先感謝!

回答

8

快速和骯髒的版本:df $file | awk 'NR == 2 {print $1}'

以編程方式...好吧,我有一個原因,我開始與快速和骯髒的版本。沒有可移植的方式來以編程方式獲取已安裝文件系統的列表。 (getmntent()得到fstab條目,這是不一樣的事情。)而且,你甚至不能可靠地解析輸出mount(8);在不同的Unix上,掛載點可能是第一個或最後一個項目。最簡單的方法是...解析df輸出結果(即使是這樣,如你注意到的分區號一樣)。因此,您無論如何都要回到快速且骯髒的外殼解決方案,除非您想遍歷/dev並尋找與匹配的major(st_rdev)major()來自sys/types.h)的塊設備。

如果您將其限制爲Linux,則可以使用/proc/mounts來獲取已裝入文件系統的列表。其他特定的Unix可以類似地進行優化:例如,在OS X上,我認爲FreeBSD,您可以在vfs樹上使用sysctl()來獲取掛載點。在最壞的情況下,你可以找到並使用適當的頭文件來解密任何掛載表文件(是的,甚至是不同的:在Solaris上它是/etc/mnttab,在許多其他系統上它是/etc/mtab,有些系統把它放在/var/run而不是/etc,在許多Linux上,它不存在或者符號連接到/proc/mounts)。其幾乎所有類Unix操作系統的格式都不相同。

+0

謝謝,但我想實現這一目標只用系統/庫調用。此外,你的建議是給我的分區號;-) – Grieih 2011-04-01 19:39:25

+0

@Grieih:+1,因爲你從來沒有指定你想要在C代碼中。附:添加'-F'[0-9]''將刪除分區號 – SiegeX 2011-04-01 19:51:28

+1

@Greih:請參閱更新。不幸的是,我出於某種原因去處理這個問題。 – geekosaur 2011-04-01 19:54:28

2

你在尋找什麼是不可能的 - 塊設備文件和它所描述的分區之間沒有1:1的連接。

考慮:

  1. 您可以創建具有不同名稱的多個塊設備文件(但相同的主要和次要號碼),他們是無法區分的(N:1)

  2. 可以使用將設備文件作爲參數掛載以裝入分區,然後刪除塊設備文件,使其離開掛載的分區。 (0:1)

因此,除了少數特定和狹隘的情況外,沒有辦法做到您想要的。

1

主號碼會告訴你它是哪個設備:3 - 第一個控制器上的IDE,22 - 第二個控制器上的IDE,SCSI上的8。

次要編號會告訴你分區號和 - 對於IDE設備 - 如果它是主驅動器或次驅動器。IDE和SCSI的計算方法不同。

對於IDE,它是:X * 64 + P,X是在控制器上驅動器號(0或1)且p是分區

對於SCSI它爲:y * 16 + p,其中y是驅動器數字和p是分區

3

你想要的信息存在於暴露linux設備樹的sysfs中。這樣可以模擬系統中設備之間的關係,並且由於您試圖從分區中確定父級磁盤設備,因此這裏是您需要查看的地方。我不知道是否有任何硬性和快速規則可以用來阻止您的代碼與未來版本的內核打交道,但內核開發人員確實試圖將sysfs作爲穩定的接口來維護。

如果你看看/sys/dev/block/<major>:<minor>,你會發現它是一個符號鏈接,尾部組件是block/<disk-device-name>/<partition-device-name>。如果您要對其執行一個readlink(2)系統調用,則可以解析鏈接目標以獲取磁盤設備名稱。在外殼(因爲它更容易表達這種方式,但在C這樣做將是非常容易的):

$ echo $(basename $(dirname $(readlink /sys/dev/block/8:33))) 
sdc 

或者,你可以採取在磁盤目錄分區目錄中的嵌套的優勢(再次外殼,但是從C,它的open(2)read(2)close(2)):

$ cat /sys/dev/block/8:33/../dev 
8:32 

,它假定您啓動重大:其實是次要的分區,而不是一些其他種類的非嵌套設備。