分享

Linux 分区程序代码实例

 海漩涡 2014-10-22

转自:http://blog.sina.com.cn/s/blog_49db0b7a01013dlf.html

Linux 分区程序代码实例

(2012-09-08 17:24:38)
给Linux分区这个有很多程序可以做到,像Busybox里就提供了简化版的Fdisk.但那是交互形式的,有时候嵌入式开发就需要在应用里加入分区的功能,到时候让用户来打命令就不大像话了。为了方便同行,我这里把自己所学的一点点知识整理一下,希望有助于大家,我也是实践过了,这个程序是可用的。
首先介绍硬盘的第0扇区,系统的主分区信息写在第0扇区上,如果你不知道扇区是什么的话就去查一查硬盘的结构,柱面,扇区,磁头这些概念。主引导扇区的知识其实也查得到,为了节省笔墨,我这里也不讲了,去百度百科搜“硬盘分区表”就能搜到。
我这里把我的主引导扇区的结构体贴一贴,给你省点力吧。
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;

#pragma pack(1)
struct _dpt{
BYTE flag;
BYTE phy_sec_start[3];
BYTE type;
BYTE phy_sec_end[3];
DWORD logic_sec;
DWORD sec_cnt;
}DPT;
struct _mbr_sec{
BYTE code[446];
struct _dpt dpt[4];
WORD tag;
}MBR_SEC;

你可能注意到了我上文有个#pragma pack(1),这个编译指令是用来使结构体里的成员按1字节对其用的,在这里好像不写也没啥,不过对于涉及到结构体,结构体保存到文件以及文件读取结构体的操作,最好都写一下。我当初因为少了这个,读取bitmap始终读不正确。这个你可以搜一下“结构体对齐”,就知道它有什么用了。
给硬盘分区无非就是写一写这个硬盘分区表。linux的很统一,文件当成文件操作(废话),设备也可以当成文件操作,网络用的套接字也能当文件操作,很像爱因斯坦的大统一理论啊。所以你只要像文件操作一样用open,close,write,read,读写第一个扇区,也就是第一个512字节就可以了。
等这些操作完了后,你发现/dev/下什么都没有变。对你少走了一步了,就是通知系统重新读取分区表,在文件打开的前提下,使用ioctl(fd,BLKRRPART,NULL)就行了,然后把这个设备文件关掉,或者在关掉文件之前sync()都可以。提一提,ioctl(fd,BLKGETSIZE,&sec_total);可以得到那个设备的总逻辑扇区数,保存在sec_total这个变量里。你看到上文的dpt结构体里有phy_sec_start,这个东西的3个字节里有磁头号,柱面号,物理扇区号,怎么分部的在百度百科里有,逻辑和物理的转换百度百科“硬盘分区表”里也有。
我这里提供一个转换函数吧,谁叫你懒呢。
void logic2physic(BYTE * physic_sec,DWORD logic_sec)
{
physic_sec[0] = (logic_sec % 16065) / 63;
physic_sec[1] = ((logic_sec % 16065) % 63 + 1) & 0x3F;
physic_sec[1] |= ((logic_sec / 16065) & 0x300) >> 2;
physic_sec[2] = (logic_sec / 16065) & 0xFF;
}

好了,这里写的差不多了,我贴一个自己写的代码你参考一下吧。

#include <cstdio>
#include <cstdlib>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <unistd.h>

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;

#pragma pack(1)

struct _dpt{
BYTE flag;
BYTE phy_sec_start[3];
BYTE type;
BYTE phy_sec_end[3];
DWORD logic_sec;
DWORD sec_cnt;
}DPT;

struct _mbr_sec{
BYTE code[446];
struct _dpt dpt[4];
WORD tag;
}MBR_SEC;

void logic2physic(BYTE * physic_sec,DWORD logic_sec)
{
physic_sec[0] = (logic_sec % 16065) / 63;
physic_sec[1] = ((logic_sec % 16065) % 63 + 1) & 0x3F;
physic_sec[1] |= ((logic_sec / 16065) & 0x300) >> 2;
physic_sec[2] = (logic_sec / 16065) & 0xFF;
}

int main()
{
struct _mbr_sec mbr;
int sec_total;
int sec_start;
int sec_count;
char dev_file[128];
printf("Please type in the device filename which you need to partition(such as '/dev/sda'):\n");
scanf("%s",dev_file);
int fd = open(dev_file, O_RDWR);

if(fd<2)
{
printf("Open /dev/sdb error.\n");
exit(-1);
}
ioctl(fd,BLKGETSIZE,&sec_total);

printf("TotalSize:%d sector.(512bytes/per sec)\n Please type in the logic sector position:",sec_total);
scanf("%d",&sec_start);

printf("Please type in the logic count:");
scanf("%d",&sec_count);

mbr.tag = 0xaa55;
mbr.dpt[0].flag = 0;
mbr.dpt[0].type = 0x83;
mbr.dpt[0].sec_cnt = sec_start;
mbr.dpt[0].logic_sec = sec_count;
memset((BYTE *)&mbr.dpt[1], 0, sizeof(struct _dpt)*3);
logic2physic(mbr.dpt[0].phy_sec_start,mbr.dpt[0].logic_sec);
logic2physic(mbr.dpt[0].phy_sec_end,mbr.dpt[0].logic_sec + mbr.dpt[0].sec_cnt);

int n = write(fd,(BYTE *)&mbr,sizeof(struct _mbr_sec));
if(n < sizeof(struct _mbr_sec))
printf("problem occor!\n");
ioctl(fd,BLKRRPART,NULL);
close(fd);
printf("write sdb partition table succeed.\n");
return 0;
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多