日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

partprobe源码分析

發(fā)布時(shí)間:2023/11/27 生活经验 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 partprobe源码分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

partprobe工具
操作系統(tǒng)目錄/usr/sbin/partprobe
程序安裝包parted-3.1-17.el7.x86_64.rpm

命令用法:

partprobe是用來告知操作系統(tǒng)內(nèi)核 分區(qū)表發(fā)生變化的工具,告知方式是請(qǐng)求內(nèi)核重讀分區(qū)表
選項(xiàng)如下:
-d 不會(huì)讓內(nèi)核重讀分區(qū)表,分區(qū)表發(fā)生變化后使用該命令partproe -d /dev/sdi不會(huì)告知內(nèi)核分區(qū)發(fā)生了變化
-s 先讓內(nèi)核重讀分區(qū)表,再顯示設(shè)備已擁有的分區(qū)信息

[root@node1 ~]# partprobe -s /dev/hda
/dev/hda: msdos partitions 1 2 3 4 <5 6 7 8 9>   #4分區(qū)為擴(kuò)展分區(qū),符號(hào)<內(nèi)部的分區(qū)為邏輯分區(qū)

-h 顯示幫助選項(xiàng)信息
-v 顯示程序的版本信息

源碼分析

partprobe主要操作是 告知操作系統(tǒng)內(nèi)核 磁盤分區(qū)表發(fā)生了變化,接下來操作由內(nèi)核完成。內(nèi)核會(huì)先刪除當(dāng)前系統(tǒng)緩存中的磁盤分區(qū)表,然后重新從磁盤中讀取分區(qū)表,主要通過io驅(qū)動(dòng)函數(shù)ioctl來完成
執(zhí)行partprobe命令基本代碼流程如下:

  1. 正常的getopt_long函數(shù)的命令行解析
  2. 根據(jù)是否傳入磁盤進(jìn)行判斷,如果傳入磁盤,如partprobe /dev/sdb則進(jìn)行磁盤處理;如未傳入制定磁盤,則先獲取到當(dāng)前設(shè)備所有的磁盤,并加入到鏈表中,然后順序執(zhí)行分區(qū)表處理
    partprobe.c中的主函數(shù)處理如下
    int n_dev = argc - optind; //獲取是否傳入磁盤參數(shù)
    if (n_dev != 0) {//如果傳入則一個(gè)一個(gè)處理int i;for (i = optind; i < argc; i++) { PedDevice *dev = ped_device_get (argv[i]);if (dev == NULL || process_dev (dev) == 0) //process_dev分區(qū)處理的主函數(shù)status = 1;}
    } else {//否則先獲取當(dāng)前設(shè)備所有磁盤ped_device_probe_all ();//將獲取到的磁盤加入到全局鏈表中PedDevice *dev;for (dev = ped_device_get_next (NULL); dev;//遍歷鏈表,一個(gè)一個(gè)順序執(zhí)行分區(qū)檢測(cè)dev = ped_device_get_next (dev))if (process_dev (dev) == 0)status = 1;
    }
    
  3. 從磁盤將分區(qū)表讀到內(nèi)存中,并告知操作系統(tǒng)內(nèi)核分區(qū)表的布局
    static int process_dev (PedDevice* dev)
    {PedDiskType*	disk_type;PedDisk*	disk;disk_type = ped_disk_probe (dev); //獲取分區(qū)類型,gpt?msdos?if (!disk_type || !strcmp (disk_type->name, "loop"))return 1;/*創(chuàng)建一個(gè)新的分區(qū)表,并存放在內(nèi)存中。當(dāng)調(diào)用ped_disk_commit_to_dev函數(shù),由內(nèi)核決定是否寫入磁盤*/disk = ped_disk_new (dev);if (!disk)goto error;/*該參數(shù)為我們的-d參數(shù),即partprobe -d /dev/sdb 表示不會(huì)執(zhí)行告知內(nèi)核磁盤分區(qū)情況的操作,如傳入-d參數(shù),則當(dāng)前數(shù)值為1*/if (!opt_no_inform) { if (!ped_disk_commit_to_os (disk)) //內(nèi)核操作的主函數(shù)goto error_destroy_disk;}/*該參數(shù)表示 partprobe -s參數(shù),執(zhí)行是否打印磁盤分區(qū)信息的操作*/if (opt_summary)/*打印當(dāng)前磁盤分區(qū)的情況*/summary (disk);ped_disk_destroy (disk);return 1;error_destroy_disk:ped_disk_destroy (disk);
    error:return 0;
    }
    
  4. 內(nèi)核操作分區(qū)表版本如下,ped_disk_commit_to_os函數(shù)操作
    • 在內(nèi)核版本為2.4之前,partprobe會(huì)調(diào)用BLKRRPART ioctl函數(shù)讓內(nèi)核重讀分區(qū)表
    • 在2.4.x之后的內(nèi)核已經(jīng)更改為使用新的blkpg接口告訴內(nèi)核每一個(gè)磁盤分區(qū)的起始,結(jié)束地址。所以,在新版本內(nèi)核中,不會(huì)因?yàn)榉謪^(qū)表類型不同而無法讀取磁盤分區(qū)表
    //通過ped_disk_commit_to_os 函數(shù)調(diào)用的回掉函數(shù)disk_commit(disk)進(jìn)行內(nèi)核分區(qū)的處理
    ped_disk_commit_to_os(PedDisk* disk){...if (!ped_architecture->disk_ops->disk_commit (disk))
    }PedDiskArchOps linux_disk_ops =  {partition_get_path:     linux_partition_get_path,partition_is_busy:      linux_partition_is_busy,disk_commit:            linux_disk_commit //通過改數(shù)據(jù)結(jié)構(gòu)調(diào)用linux_disk_commit函數(shù)進(jìn)行處理
    };/*告知內(nèi)核磁盤分區(qū)的布局*/
    static int linux_disk_commit (PedDisk* disk)
    {if (!_has_partitions (disk))return 1;
    /*若系統(tǒng)支持邏輯卷方式管理磁盤,且磁盤分區(qū)類型為支持dm,一般為msdos格式即mbr分區(qū),則重讀分區(qū)表。一半存放在/dev/mapper目錄*/
    #ifdef ENABLE_DEVICE_MAPPER if (disk->dev->type == PED_DEVICE_DM)return _dm_reread_part_table (disk);
    #endif/*如果設(shè)備類型為普通文件類型,即文件形式存放的,一般為我們的gpt分區(qū)類型的磁盤*/if (disk->dev->type != PED_DEVICE_FILE) {/*要求當(dāng)前內(nèi)核支持blkpg的新特性,即使用blkpg接口告知內(nèi)核磁盤分區(qū)表的起始地址,不需要內(nèi)核自己去讀。如果當(dāng)前內(nèi)核不支持該特性,或者這里發(fā)現(xiàn)有斷言退出,可以直接將改行注釋掉*/assert (_have_blkpg ());/*內(nèi)核同步磁盤分區(qū)表的主函數(shù)*/if (!_disk_sync_part_table (disk)) return 0;}return 1;
    }
    
  5. 內(nèi)核同步磁盤分區(qū)表的操作,即我們partprobe的主要操作
    • 通過io設(shè)備驅(qū)動(dòng)程序的通道管理函數(shù)ioctl,先從內(nèi)核移除所有的分區(qū)表。但是當(dāng)ioctl執(zhí)行失敗時(shí),不會(huì)對(duì)此時(shí)失敗的分區(qū)表進(jìn)行移除
    • 從我們遍歷到的磁盤中添加分區(qū)表。如果我們因?yàn)榈谝徊揭瞥謪^(qū)表的失敗無法添加(因?yàn)槭褂玫氖莃lkpg新特性,移除以及添加需要保證分區(qū)表的起始結(jié)束地址一直才能確定執(zhí)行成功),則進(jìn)行告警
      static int _disk_sync_part_table (PedDisk* disk)
      {.../*從/sys/block/dev_name/range文件中獲取當(dāng)前系統(tǒng)支持的單個(gè)磁盤最大分區(qū)數(shù)量,如果獲取不到,則使用默認(rèn)的64*/lpn = _device_get_partition_range(disk->dev);.../*對(duì)當(dāng)前磁盤執(zhí)行分區(qū)刪除操作通過調(diào)用_blkpg_part_command(disk->dev, &linux_part,BLKPG_DEL_PARTITION)函數(shù)執(zhí)行ioctl (arch_specific->fd, BLKPG, &ioctl_arg)的分區(qū)刪除操作*/_blkpg_remove_partition (disk, j + 1);.../*同樣通過_blkpg_part_command (disk->dev, &linux_part,BLKPG_ADD_PARTITION)函數(shù)執(zhí)行ioctl (arch_specific->fd, BLKPG, &ioctl_arg)的分區(qū)添加操作*/_blkpg_add_partition (disk, part);/*根據(jù)執(zhí)行的結(jié)果是否拋出異常進(jìn)行告警*/
      }
      

關(guān)于常見的兩種問題的告警描述如下:

  1. "Error informing the kernel about modifications to "
    "partition %s – %s. This means Linux won’t know "
    "about any changes you made to %s until you reboot "
    "-- so you shouldn’t mount it or use it in any way "
    "before rebooting.
    該問題為內(nèi)核向磁盤添加分區(qū)過程中ioctl程序執(zhí)行失敗,一般為當(dāng)前分區(qū)表x相關(guān)元數(shù)據(jù)信息錯(cuò)誤
  2. Partition(s) %s on %s have been written, but we have "
    "been unable to inform the kernel of the change, "
    "probably because it/they are in use. As a result, "
    "the old partition(s) will remain in use. You "
    "should reboot now before making further changes.
    該問題為內(nèi)核刪除分區(qū)表時(shí)出現(xiàn),因?yàn)榉謪^(qū)仍然被占用,無法從緩存中清除該分區(qū)的起始和結(jié)束地址導(dǎo)致。

總結(jié)

以上是生活随笔為你收集整理的partprobe源码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。