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

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 necessaryBeQuiet(); // Tell called functions to be less verbose & interactive//加载磁盘分区表if (LoadPartitions((string) device)) { ...//开始进行具体的sgdisk参数解析while ((opt = poptGetNextOpt(poptCon)) > 0) { ...//设置分区边界对齐的短项参数  对应--set-alignment=valuecase 'a'://初始化分区边界对齐参数 ,会为全局变量 sectorAlignment 赋值SetAlignment(alignment);break;...//创建分区参数短项,对应--new=num:start_sector:end_sectorcase '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,失败返回0if (CreatePartition(newPartNum, startSector, endSector)) { saveData = 1;} else { cerr << "Could not create partition " << newPartNum + 1 << " from "<< startSector << " to " << endSector << "
";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 problemsuint64_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
order to align on " << sectorAlignment<< "-sector boundaries.
";} // ifif (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 numberreturn 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} // ifreturn retval;
} // GPTData::Align()

更多相关: