s-sgdisk源码分析 “--set-alignment=value分区对齐参数”

文章目录

        • 边界对齐子命令使用
        • 源码分析
          • sgdisk.cc main函数入口
          • gptcl.cc DoOptions解析并执行具体命令函数
          • gpt.cc CreatePartition创建分区函数,设置起始扇区对齐
            • gpt.cc Align分区对齐函数,设置起始扇区对齐

sgdisk命令是由 gdisk-0.8.6-4.el7.x86_64程序包安装

sgdisk源码路径 https://github.com/Shihta/gdisk

边界对齐子命令使用

本节主要描述sgdisk源码中关于命令-a --set-alignment=value的边界对齐逻辑描述,借此各位可以看到sgdisk命令集的其他参数源码白编写的逻辑
该参数使用方式一般是在创建分区过程中使用
sgdisk --set-alignment=8 --new=1:0:2G --mbrtogpt -- /dev/sdb
这个命令是在/dev/sdb上创建一个编号为1,大小为2G的gpt分区,且start_sector是4K对齐的。sgdisk底层做分区是以扇区为单位,同时设置边界对齐时单位是扇区,默认以1M(2048个扇区)为单位进行对齐,最小只能设置8个扇区对齐

源码分析

sgdisk.cc main函数入口
int main(int argc, char *argv[]) {
   GPTDataCL theGPT;
   #主要执行函数,对参数进行解析以及调用各个执行函数执行具体功能
   return theGPT.DoOptions(argc, argv);
} 
gptcl.cc DoOptions解析并执行具体命令函数
/*
该函数的返回值如下:
0 :执行命令成功
1:执行参数过少
2:读磁盘分区表错误
3:格式化磁盘分区格式为gpt时没有-g参数
4:无法保存sgdisk对磁盘的操作
8:备份磁盘分区表失败,-R参数failed
*/
int GPTDataCL::DoOptions(int argc, char* argv[]) {
	...
	#将参数长项和短项以及对应的描述封装为结构体
	struct poptOption theOptions[] =
   {
      {"attributes", 'A', POPT_ARG_STRING, &attributeOperation, 'A', "operate on partition attributes",
          "list|[partnum:show|or|nand|xor|=|set|clear|toggle|get[:bitnum|hexbitmask]]"},
      {"set-alignment", 'a', POPT_ARG_INT, &alignment, 'a', "set sector alignment", "value"},
      {"backup", 'b', POPT_ARG_STRING, &backupFile, 'b', "backup GPT to file", "file"},
      {"change-name", 'c', POPT_ARG_STRING, &partName, 'c', "change partition's name", "partnum:name"},
      {"recompute-chs", 'C', POPT_ARG_NONE, NULL, 'C', "recompute CHS values in protective/hybrid MBR", ""},
      {"delete", 'd', POPT_ARG_INT, &deletePartNum, 'd', "delete a partition", "partnum"},
      {"display-alignment", 'D', POPT_ARG_NONE, NULL, 'D', "show number of sectors per allocation block", ""},
      {"move-second-header", 'e', POPT_ARG_NONE, NULL, 'e', "move second header to end of disk", ""},
      {"end-of-largest", 'E', POPT_ARG_NONE, NULL, 'E', "show end of largest free block", ""},
      {"first-in-largest", 'f', POPT_ARG_NONE, NULL, 'f', "show start of the largest free block", ""},
      ...
	}
	...
	 // 确保最后一个参数一定是设备名称(之前会做参数筛选)
   device = (char*) poptGetArg(poptCon);
   poptResetContext(poptCon);
   
   //如果设备名称不为空的话开始进行具体的参数解析
   if (device != NULL) {
      JustLooking(); // reset as necessary
      BeQuiet(); // Tell called functions to be less verbose & interactive
      //加载磁盘分区表
      if (LoadPartitions((string) device)) {
      ...
      		//开始进行具体的sgdisk参数解析
     		while ((opt = poptGetNextOpt(poptCon)) > 0) {
     			...
     			//设置分区边界对齐的短项参数  对应--set-alignment=value
     			case 'a':
     				//初始化分区边界对齐参数 ,会为全局变量 sectorAlignment 赋值
                	SetAlignment(alignment);
                	break;
                ...
                //创建分区参数短项,对应--new=num:start_sector:end_sector
                case 'n':
                  JustLooking(0);
                  //获取分区编号
                  newPartNum = (int) GetInt(newPartInfo, 1) - 1;
                  //如果分区编号小于零则选择第一个没有被使用的编号(最小的没有被使用的)
                  if (newPartNum < 0)
                     newPartNum = FindFirstFreePart();
                  //从磁盘的剩余空间中寻找最大的未被分配的块,取该块中的第一个可用的扇区作为起始扇区配置
                  low = FindFirstInLargest();
                  /*将该扇区调整为512字节,因为不通磁盘有自己的扇区大小设置,
                  这里会将这种类型的磁盘扇区大小设置为操作系统识别的512字节*/
                  Align(&low);
                  //依据该块空间的起始扇区位置寻找终止扇区位置
                  high = FindLastInFree(low);
                  //这里做一个转换,将我们创建分区在start和end处输入的IEEE-1541-2002 value(K,M,G,T,P,E)转换为扇区单位
                  startSector = IeeeToInt(GetString(newPartInfo, 2), sSize, low, high, low);
                  endSector = IeeeToInt(GetString(newPartInfo, 3), sSize, startSector, high, high);
                  //创建分区:成功返回1,失败返回0
                  if (CreatePartition(newPartNum, startSector, endSector)) {
                     saveData = 1;
                  } else {
                     cerr << "Could not create partition " << newPartNum + 1 << " from "
                          << startSector << " to " << endSector << "\n";
                     neverSaveData = 1;
                  } // if/else
                  //释放存放参数列表的char *空间
                  free(newPartInfo);
                  break;
               ...
     		}
     		...
      }
gpt.cc CreatePartition创建分区函数,设置起始扇区对齐
uint32_t GPTData::CreatePartition(uint32_t partNum, uint64_t startSector, uint64_t endSector) {
   int retval = 1; // assume there'll be no problems
   uint64_t origSector = startSector;

   if (IsFreePartNum(partNum)) {
   	//确保起始扇区是能够被我们设置的边界对齐参数整除(全局变量sectorAlignment)
   	/*
   	Align(&startSector)函数操作如下 
   	1. 如果startSector % sectorAlignment == 0那么直接返回成功
   	2. 否则 假设startSector=2049,sectorAlignment=8
   	   该函数会定位两个区间[2048,2049]和[2049-2056],先从该第一个区间起始扇区++查看是否未被占用,如未被占用,则用作起始扇区
   	   否则从第二个区间2056扇区--查看是否未被占用,如未被占用,则用作起始扇区
	详细可查看如下Align(&startSector)实现
   	*/
      if (Align(&startSector)) {
         cout << "Information: Moved requested sector from " << origSector << " to "
              << startSector << " in\norder to align on " << sectorAlignment
              << "-sector boundaries.\n";
      } // if
      if (IsFree(startSector) && (startSector <= endSector)) {
         if (FindLastInFree(startSector) >= endSector) {
            partitions[partNum].SetFirstLBA(startSector);
            partitions[partNum].SetLastLBA(endSector);
            partitions[partNum].SetType(DEFAULT_GPT_TYPE);
            partitions[partNum].RandomizeUniqueGUID();
         } else retval = 0; // if free space until endSector
      } else retval = 0; // if startSector is free
   } else retval = 0; // if legal partition number
   return retval;
}
gpt.cc Align分区对齐函数,设置起始扇区对齐
int GPTData::Align(uint64_t* sector) {
   int retval = 0, sectorOK = 0;
   uint64_t earlier, later, testSector;

   if ((*sector % sectorAlignment) != 0) {
      earlier = (*sector / sectorAlignment) * sectorAlignment;
      later = earlier + (uint64_t) sectorAlignment;

      // Check to see that every sector between the earlier one and the
      // requested one is clear, and that it's not too early....
      if (earlier >= mainHeader.firstUsableLBA) {
         sectorOK = 1;
         testSector = earlier;
         do {
            sectorOK = IsFree(testSector++);
         } while ((sectorOK == 1) && (testSector < *sector));
         if (sectorOK == 1) {
            *sector = earlier;
            retval = 1;
         } // if
      } // if firstUsableLBA check

      // If couldn't move the sector earlier, try to move it later instead....
      if ((sectorOK != 1) && (later <= mainHeader.lastUsableLBA)) {
         sectorOK = 1;
         testSector = later;
         do {
            sectorOK = IsFree(testSector--);
         } while ((sectorOK == 1) && (testSector > *sector));
         if (sectorOK == 1) {
            *sector = later;
            retval = 1;
         } // if
      } // if
   } // if
   return retval;
} // GPTData::Align()

你可能感兴趣的:(#,linux操作系统:常用命令,#,linux操作系统:文件系统,linux,操作系统技能树)