Linux C编程:如何获取设备的分区信息?

8

我是Linux C编程的新手,有没有可以获取设备分区信息的API?


你想获取给定块设备(可能是物理磁盘)上可用分区的列表吗? - Brian Cain
可能是 https://dev59.com/mlXTa4cB1Zd3GeqPzCoL 的重复问题。 - Sangeeth Saravanaraj
5个回答

15

Akash Rawal的回答非常接近。一个好的方法是使用libblkid。

以下是获取分区UUID的示例:使用 libblkid 查找分区的 UUID

我将上面展示的代码与libblkid参考菜单中的示例结合起来,生成了下面的工作程序:

#include <stdio.h>
#include <string.h>
#include <err.h>
#include <blkid/blkid.h>


int main (int argc, char *argv[]) {
   blkid_probe pr = blkid_new_probe_from_filename(argv[1]);
   if (!pr) {
      err(1, "Failed to open %s", argv[1]);
   }

   // Get number of partitions
   blkid_partlist ls;
   int nparts, i;

   ls = blkid_probe_get_partitions(pr);
   nparts = blkid_partlist_numof_partitions(ls);
   printf("Number of partitions:%d\n", nparts);

   if (nparts <= 0){
      printf("Please enter correct device name! e.g. \"/dev/sdc\"\n");
      return;
   }

   // Get UUID, label and type
   const char *uuid;
   const char *label;
   const char *type;

   for (i = 0; i < nparts; i++) {
      char dev_name[20];

      sprintf(dev_name, "%s%d", argv[1], (i+1));

      pr = blkid_new_probe_from_filename(dev_name);
      blkid_do_probe(pr);

      blkid_probe_lookup_value(pr, "UUID", &uuid, NULL);

      blkid_probe_lookup_value(pr, "LABEL", &label, NULL);

      blkid_probe_lookup_value(pr, "TYPE", &type, NULL);

      printf("Name=%s, UUID=%s, LABEL=%s, TYPE=%s\n", dev_name, uuid, label, type);

   }

   blkid_free_probe(pr);

   return 0;
}

使用:

gcc -o getuuid getuuid.c -lblkid
sudo ./getuuid /dev/sdc
Number of partitions:1
Name=/dev/sdc1, UUID=754A-CE25, LABEL=KINGSTON, TYPE=vfat

3
你可以查看 /sys/block/sd?/,那里有许多伪文件告诉你一些分区参数。

2

libblkid是一个很好的API。blkid(包含在util-linux软件包中)使用了它。

blkid列出所有分区以及标签、文件系统类型和UUID。下面是我系统上的输出:

# blkid
/dev/sda1: LABEL="grub" UUID="a760119d-916a-492c-8ec1-50f81dbf4e26" TYPE="ext2" 
/dev/sda3: LABEL="Library" UUID="248D72BD2E5CF009" TYPE="ntfs" 
/dev/sda5: LABEL="WinXP" UUID="545CC7085CC6E438" TYPE="ntfs" 
/dev/sda6: LABEL="Win7" UUID="22F009B2F0098CEB" TYPE="ntfs" 
/dev/sda7: LABEL="Puppy" UUID="fe1dc425-ad17-4773-971a-435d91690883" SEC_TYPE="ext2" TYPE="ext3" 
/dev/sda8: LABEL="Linux Mint" UUID="0c61a114-9353-499b-a1cd-ba19722b1e43" TYPE="ext4" 
/dev/sda9: LABEL="Ubuntu L" UUID="5f6923e1-92f4-4b3f-b613-9e78839e1987" TYPE="ext4" 
/dev/loop0: TYPE="squashfs" 
/dev/loop1: UUID="16e3a75d-74dc-4391-a9e2-4305c08c5707" TYPE="ext3" 
/dev/loop4: TYPE="squashfs" 
# 

这是参考手册:http://www.kernel.org/pub/linux/utils/util-linux/v2.21/libblkid-docs/。我刚刚找到这个库,自己也在寻找同样的答案。

1

(伪)文件“/proc/partitions”至少包含了物理设备上找到的分区列表。不幸的是,它并没有提供有关分区类型的任何信息(特别是,没有简单的方法来猜测一个分区是否实际上是扩展分区)。 以下是我在我的机器的/proc/partitions中发现的内容:

major minor  #blocks  name

   8        0  488386584 sda
   8        1   13631488 sda1
   8        2  237375488 sda2
   8        3          1 sda3
   8        4    3650560 sda4
   8        5    3413781 sda5
   8        6   29294496 sda6
   8        7   14651248 sda7
   8        8    9767488 sda8
   8        9  176586448 sda9
   8       16    7815168 sdb
   8       17    7811136 sdb1

sda是我的硬盘,sdb是一个USB dongle。请注意,sda3是扩展分区,但如果不直接读取磁盘的分区表,则很难猜测它。 您在此文件中找到的信息可能足够或不足,这取决于我们的特定需求。我个人认为更安全的方法是:

1) Create a couple of pipes
2) fork a process an redirect the pipes to child's stdin and sdtout (fd 0 and 1)
3) execl "fdisk /dev/sdXXX"
4) send a "p\n" command to the child process
5) read the lines containg the complete partition information

希望这能对你有所帮助。


0

我不知道有任何相关的API。

我执行了ldd `which fdisk`,但它没有显示任何与读取分区表相关的库,所以我认为它是自己完成的。

快速浏览fdisk程序的源代码进一步证明了我的想法,它没有使用任何外部库。

如果你想自己解决问题并学习,请按照以下建议进行:

  1. 阅读维基百科页面MBR
  2. 获取fdisk的源代码并阅读代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接