A20硬盘格式化

1>fdisk_shell.sh文件需在linux下用vim生成 否则会出很多意想不到的问题,
    若在win下生成该文件在导入linux需用busybox dos2unix fdisk_shell.sh命令转化为linux文件。
2>整体思路:在应用层调用fdisk_shell.sh脚本实现格式化功能。
3>实践中发现,应用层通过system方法调用的. /fdisk_shell.sh语句只能执行fdisk_shell.sh脚本中的简单语句
  像echo命令,但是system/bin下的其他命令及BUSYBOX命令是无法执行的;这行命令的执行需要ROOT权限,其实
  system方法是可以实现ROOT身份的转换,但只能执行具体的命令,或是运行脚本的命令system(". /fdisk_shell.sh");
  但是要想运行脚本中的busybox命令是不成功的,只有另辟蹊径;
  最终思路是在init.rc中开启一个守护进程rootexec,实现脚本的执行工作,应用层通过进程间通信,实现脚本的执行。
  应用层通过JNI调用startRootExec()方法,startRootExec()方法通过bind机制使rootexec实现执行脚本的任务。
  也可以用非正式的方法shocket,这样可以避开JNI层的调用;
4>重要代码分析:
  \root\cmds\rootexec\RootExecService.cpp:
  if (-1 == status)  
    {  
        ALOGD("system error!");
        return 0;  
    }  
    else  
    {  
        ALOGD("exit status value = [0x%x]\n", status);  
 
        if (WIFEXITED(status))  
        {  
            if (0 == WEXITSTATUS(status))  
            {  
                ALOGD("run shell script successfully.\n");
                return 1;  
            }  
            else  
            {  
                ALOGD("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));
                return 0;  
            }  
        }  
        else  
        {  
            ALOGD("exit status = [%d]\n", WEXITSTATUS(status));
               return 0;  
        }  
    }
    此段代码是检测system方法执行脚本完成情况,弱弱的讲讲system方法的返回值的问题:
    system函数对返回值的处理,涉及3个阶段:
        阶段1:创建子进程等准备工作。如果失败,返回-1。
        阶段2:调用/bin/sh拉起shell脚本,如果拉起失败或者shell未正常执行结束(参见备注1),
        原因值被写入到status的低8~15比特位中。system的man中只说明了会写了127这个值,但实测发现还会写126等值。
        阶段3:如果shell脚本正常执行结束,将shell返回值填到status的低8~15比特位中。
        备注1:
        只要能够调用到/bin/sh,并且执行shell过程中没有被其他信号异常中断,都算正常结束。
        比如:不管shell脚本中返回什么原因值,是0还是非0,都算正常执行结束。即使shell脚本不存在或没有执行权限,
        也都算正常执行结束。
        如果shell脚本执行过程中被强制kill掉等情况则算异常结束。

        如何判断阶段2中,shell脚本是否正常执行结束呢?系统提供了宏:WIFEXITED(status)。如果WIFEXITED(status)为真,
        则说明正常结束。
        如何取得阶段3中的shell返回值?你可以直接通过右移8bit来实现,
        但安全的做法是使用系统提供的宏:WEXITSTATUS(status)。


        由于我们一般在shell脚本中会通过返回值判断本脚本是否正常执行,如果成功返回0,失败返回正数。
        所以综上,判断一个system函数调用shell脚本是否正常结束的方法应该是如下3个条件同时成立:
        (1)-1 != status
        (2)WIFEXITED(status)为真
        (3)0 == WEXITSTATUS(status)

        注意:
        根据以上分析,当shell脚本不存在、没有执行权限等场景下时,以上前2个条件仍会成立,
        此时WEXITSTATUS(status)为127,126等数值。
    所以,我们在shell脚本中不能将127,126等数值定义为返回值,否则无法区分中是shell的返回值,
    还是调用shell脚本异常的原因值。shell脚本中的返回值最好多1开始递增。
    脚本执行成功返回0,失败1;
    \myTest\jni\fdisk.cpp:
    static jstring run(JNIEnv *env,jobject obj,jstring comd,jint num)
            {   
                char* tmpstr1 = "successed";
                char* tmpstr2 = "failed";
                
                jstring jstr1 = env->NewStringUTF(tmpstr1);
                jstring jstr2 = env->NewStringUTF(tmpstr2);
                
                ALOGE("fdiskShelljni.so");
                if(startRootExec(2,2))
                {
                     ALOGE("startRootExec success!\n");
                    return jstr1;        
                }else{
                    ALOGE("startRootExec failed!\n");
                    return jstr2;
                }
            }
            此段代码为jni的主体,作用很简单,执行startRootExec()方法,成功返回successed,失败返回failed;
            改文件中还实现了其他方法,应用层调用JNI库所需。
            \myTest\src\com\fdisk\FdiskActivity.java:
            改文件为测试程序。格式化一个500G的硬盘需要很长时间,这么,漫长的等待,花儿会不会谢呢?只有在另外的线程完成,
            主线程只负责启动thread,在thread中实现FLAG状态的改变,
            脚本执行成功JNI会返回successed,此时将FLAG置1,失败返回failed,将FLAG置0,;
            主线程根据值得变化判断格式化是否成功。开始将FLAG置2,处理很好,读者自己琢磨;
            fdisk_shell.sh:
            这个脚本所要完成的工作就是判断目前硬盘(/dev/block/sda)里的分区情况,然后去删除分区,再重新创建一个sda1的
            分区。该脚本花了我很长时间,但功能很完善,除了可以删除主分区还能删除扩展分区,当然这个工作可以在RootExecService.cpp中用删除
            表头的方法实现,我认为这样更好;
            /system/fdisk/1.0保存的是整个硬盘的分区情况,共有几个分区;
            /system/fdisk/1.1保存的是整个硬盘的主分区情况,共有几个主分区;
            /system/fdisk/1.2保存的是整个硬盘的扩展分区情况,共有几个扩展分区;
            这3个文件保存的信息是给后面命令提供参数依据;
            如果你很熟悉FDISK命令的话,就会明白为什么在删除最后一个分区的时候要另外echo?
            也会明白要umount vfat格式自动挂载的8_*目录的原因,否则是mount不上的;
            导致mount命令失败的原因大致为二:1,格式化未成功;2,之前已经mount。
            所以该脚本为了保险用力的umount.
            这脚本花的精力很多,读者若是觉得有更好的方法可以联系:424758702(qq)
5>整个代码的编译:
            myTest文件要放在android4.2/package/app/下,jni库的生成和测试apk的生成只要在myTest文件夹下mm即可。
            生成的so库会出现android/out/target/product/win_k70/system/lib/下,改库需要的librootexec.so,如果你完全按root目录
            下的Read文档做了就会在android/out/target/product/win_k70/system/lib/下生成;librootexec.so这个库和
            android/out/target/product/win_k70/system/bin/下的rootexec二进制文件我是自动打包进固件里的,
            会出现在板子的system/lib和system/bin里的(如果你完全按文档做了);
            我的邮件[email protected]
            文档很粗糙,愿君自琢磨。
            源码不提供,思路很重要(保密,公司要求我不得不服)。
            
            
 

你可能感兴趣的:(A20硬盘格式化)