首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

【移动开发】Android游戏开发SurfaceView应用----手指发动小球(小球碰撞检测例子)

为了复习一下SurfaceView的使用,在此写了一个经典的小球碰撞检测例子程序,希望能够够帮助正在学习游戏的人。 先看一下效果图: 下面我们就来逐一分析一下它的实现过程: 1.启动入口: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import android.os.Bundle; import android.app.Activity; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); //全屏设置 requestWindowFeature(Window.FEATURE_NO_TITLE); this .getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //将画布放进去 GameView gameView = new GameView( this ); setContentView(gameView); } } 2.小球类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; /** * 小球实例 * @author ZHF * */ public class Ball { int x, y; //小球的实时位置 int startX, startY; //小球的初始位置 float vX, vY; //小球的速度 int r; //小球的半径 double startTimeX; //开始时间 double startTimeY; //开始时间 BallThread ballThread; //小球移动线程 Paint paint = new Paint(); //画笔 public Ball( int x, int y, float vX, float vY, int r) { this .x = x; this .y = y; this .startX = x; this .startY = y; this .vX = vX; this .vY = vY; this .r = r; //为每个小球实例化一个独立的线程,在抬手时开启线程 ballThread = new BallThread( this ); paint.setColor(Color.RED); //小球为红色实心 } /**绘画方法**/ public void drawSelf(Canvas canvas) { canvas.drawCircle(x, y, r, paint); } } 3.障碍物类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; /** * 障碍物 * * @author ZHF * */ public class Obstruction { int x, y; int hWeight; //宽度和高度一样 Paint paint = new Paint(); public Obstruction( int x, int y, int hWeight) { this .x = x; this .y = y; this .hWeight = hWeight; paint.setColor(Color.GREEN); //设置画笔颜色 } public void drawSelf(Canvas canvas) { canvas.drawRect(x - hWeight, y - hWeight, x + hWeight, y + hWeight, paint); } } 以上代码比较简单,在此不多做解释,下面主要来看一下两个主要线程类: 4.小球移动线程(碰撞检测): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 /** * 小球移动和碰撞检测线程 * @author ZHF * */ public class BallThread extends Thread { boolean flag; //标记线程是否开启 Ball ball; //小球 double currentTime; //当前时间 public BallThread(Ball ball) { flag = true ; this .ball = ball; } @Override public void run() { while (flag) { //调试:碰撞检测开始时间 long startTime = System.currentTimeMillis(); //计算出小球移动的时间片:将每次刷新分成若干时间小片段,用于计算每次时间小片段小球移动的距离 currentTime = System.nanoTime(); double timeSpanX = (currentTime - ball.startTimeX) / 1000 / 1000 / 1000 ; double timeSpanY = (currentTime - ball.startTimeY) / 1000 / 1000 / 1000 ; int xBackup = ball.x; //保存小球的碰撞前的位置 int yBackup = ball.y; ball.x = ( int ) (ball.startX + ball.vX * timeSpanX); //小球移动的距离 ball.y = ( int ) (ball.startY + ball.vY * timeSpanY); //边界碰撞检测 if ((ball.vX > 0 && (ball.x + ball.r) >= 479 ) || (ball.vX < 0 && (ball.x - ball.r) <= 0 )) { ball.x = xBackup; ball.vX = 0 - ball.vX; //速度反向 ball.startTimeX = System.nanoTime(); //重新记录开始时间 ball.startX = ball.x; //重新记录开始位置 } if ((ball.vY > 0 && (ball.y + ball.r) >= 799 ) || (ball.vY < 0 && (ball.y - ball.r) <= 0 )) { ball.y = yBackup; ball.vY = 0 - ball.vY; //速度反向 ball.startTimeY = System.nanoTime(); //重新记录开始时间 ball.startY = ball.y; //重新记录开始位置 } //障碍物碰撞检测 for ( int i = 0 ; i < GameView.obstructList.size(); i++) { Obstruction o = GameView.obstructList.get(i); if (Math.abs(ball.x - o.x) < (ball.r + o.hWeight) && Math.abs(ball.y - o.y) < (ball.r + o.hWeight)){ if (Math.abs(xBackup - o.x) >= (ball.r + o.hWeight)) { ball.x = xBackup; ball.vX = 0 - ball.vX; ball.startTimeX = System.nanoTime(); ball.startX = ball.x; } if (Math.abs(yBackup - o.y) >= (ball.r + o.hWeight)) { ball.y = yBackup; ball.vY = 0 - ball.vY; ball.startTimeY = System.nanoTime(); ball.startY = ball.y; } break ; //跳出循环 } } //调试:碰撞检测结束时间 实验证明碰撞加测基本不耗时间 long endTime = System.currentTimeMillis(); System.out.println(endTime + "----" + startTime + "= " +(endTime - startTime)); try { Thread.sleep( 10 ); } catch (Exception e) { e.printStackTrace(); } } } } 分析: 1.我们将刷新时间分割成:将每次刷新时间分成若干时间小片段timeSpanX和timeSpanY,用于计算每次时间小片段小球移动的距离. 2.我们在小球与边界碰撞之前,记录一下时间startTime,在其与边界碰撞之后,我们将其x轴、y轴方向上做一系列的操作(方向取反,回到碰撞前位置,重新记录开始时间)其实,我通过调试发现碰撞时间基本可以忽略. 3.我们这里的碰撞检测是边界检测,只考虑小球与障碍物、边界的碰撞,没有考虑小球之间的碰撞,有兴趣的同学可以自行研究一下。 5.绘画线程: 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import android.graphics.Canvas; import android.util.Log; import android.view.SurfaceHolder; /** * 绘画主界面线程 * @author ZHF * */ public class DrawThread extends Thread { boolean flag; //标记线程是否开启 GameView gameView; SurfaceHolder holder; Canvas canvas; public DrawThread(GameView gameView) { flag = true ; this .gameView = gameView; holder = gameView.getHolder(); //获取画布锁 } @Override public void run() { while (flag) { //获取当前绘画开始时间 long startTime = System.currentTimeMillis(); synchronized (holder) { canvas = holder.lockCanvas(); //获取当前被锁住的画布 if (canvas != null ) { gameView.draw(canvas); //对画布进行操作 holder.unlockCanvasAndPost(canvas); //释放画布 } } long endTime = System.currentTimeMillis(); int diffTime = ( int ) (endTime - startTime); Log.d( "DrawTime" , diffTime+ "" ); while (diffTime <= 2 ) { diffTime = ( int ) (System.currentTimeMillis() - startTime); Thread.yield(); //将线程的所有权交给另一个线程 } } } } 分析: 1. 首先,我们将画布锁住之后,对其进行绘画,画完之后自然要释放画布啦 2. 为了优化程序,我们计算出绘画所用时间,当绘画时间过长时,暂停当前正在执行的线程对象,通知CPU来执行其他线程(注意:这里的其他也包含当前线程) 6.主界面: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 import java.util.ArrayList; import java.util.Random; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * 游戏主界面 * @author ZHF * */ public class GameView extends SurfaceView implements SurfaceHolder.Callback { SurfaceHolder holder; DrawThread drawThread; //绘画线程 Ball[] ballArray = new Ball[ 5 ]; //装小球的数组 int ballPointer = 0 ; //当前指向数组中第几个球 static ArrayList<Obstruction> obstructList = new ArrayList<Obstruction>(); //装障碍物的集合 int xDown, yDown; //记录手指按下时的坐标 public GameView(Context context) { super (context); holder = getHolder(); //获取画布锁 holder.addCallback( this ); //添加回调 //初始化障碍物 Random random = new Random(); for ( int i = 0 ; i < 3 ; i++) { Obstruction o = new Obstruction(random.nextInt( 380 ) + 50 , random.nextInt( 700 ) + 50 , 50 ); obstructList.add(o); //将创出的障碍物对象添加到集合中去 } } @Override public void surfaceCreated(SurfaceHolder holder) { drawThread = new DrawThread( this ); drawThread.start(); //开启绘画线程 } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { //画布发生变化,eg:转屏操作,处理画布操作 } @Override public void surfaceDestroyed(SurfaceHolder holder) { //销毁画布操作 drawThread.flag = false ; //停掉线程 drawThread = null ; //GC会及时发现并处理掉该对象 } public void draw(Canvas canvas) { canvas.drawColor(Color.BLACK); //背景颜色 Paint paint = new Paint(); paint.setTextSize( 25 ); paint.setColor(Color.WHITE); //文字颜色 canvas.drawText( "小球碰撞检测" , 50 , 20 , paint); //画出小球 for ( int i = 0 ; i < 5 ; i++) { if (ballArray[i] != null ) { ballArray[i].drawSelf(canvas); //当前小球绘画出自己 } } //画出障碍物 for ( int i = 0 ; i < obstructList.size(); i++) { obstructList. get (i).drawSelf(canvas); } } @Override public boolean onTouchEvent(MotionEvent event) { int x = ( int ) event.getX(); int y = ( int ) event.getY(); if (event.getAction() == 0 ) { //按下 //记录按下时X,Y的坐标 xDown = x; yDown = y; //生成第一个球 Ball ball = new Ball(x, y, 0 , 0 , 20 ); if (ballArray[ballPointer] != null ) { ballArray[ballPointer].ballThread.flag = false ; //关闭小球移动线程 ballArray[ballPointer].ballThread = null ; } ballArray[ballPointer] = ball; } else if (event.getAction() == 1 ) { //抬起 int xOffset = x - xDown; int yOffset = y - yDown; double sin = yOffset / Math.sqrt(xOffset * xOffset + yOffset * yOffset); double cos = xOffset / Math.sqrt(xOffset * xOffset + yOffset * yOffset); ballArray[ballPointer].startTimeX = System.nanoTime(); //当前小球开始时间 ballArray[ballPointer].startTimeY = System.nanoTime(); ballArray[ballPointer].vX = (float) ( 500 * cos); //当前小球的速度 ballArray[ballPointer].vY = (float) ( 500 * sin); ballArray[ballPointer].ballThread.start(); //开启小球移动线程 ballPointer ++; //下一个小球 if (ballPointer >= 5 ) { ballPointer = 0 ; } } return true ; } } 分析: 1.这里我们启动小球移动线程方式:采用手指触屏滑动,记录按下、抬起位置,通过计算角度得出算出发射方向。 2.每次发出小球后下标ballPointer ++指向下一个小球,当到达数组上限后,重新返回到下标0. ok! 到此功能已经实现,想要完整源码在此下载:http://download.csdn.net/detail/zhf651555765/5775035 附件:http://down.51cto.com/data/2363159 本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1251882,如需转载请自行联系原作者

优秀的个人博客,低调大师

操作记录:在ubuntu16.04.1配置fuse开发环境及fuse开发规范测试

1、使用ssh客户端,登陆ubuntu ssh-p2206root@127.0.0.1 2、下载fuse源码,进行编译,安装(当前工作目录为~) wgethttps://github.com/libfuse/libfuse/releases/download/fuse-3.0.0rc3/fuse-3.0.0rc3.tar.gz tarxvffuse-3.0.0rc3.tar.gz cdfuse-3.0.0rc3/ ./configure make-j8 makeinstall depmod modprobefuse 3、测试example\hello_ll是否能正常工作 cdexample/ ./hello_ll--help ./hello_ll/mnt mount cd/mnt ls cathello cd umount/mnt 针对example\hello_ll.c,进行改动测试: 1、在根目录下多创建一个文件出来,节点号定为5,名称为frombyte,内容为文本"http://www.datahf.net" 改动如下: /* FUSE:FilesysteminUserspace Copyright(C)2001-2007MiklosSzeredi<miklos@szeredi.hu> ThisprogramcanbedistributedunderthetermsoftheGNUGPL. SeethefileCOPYING. */ /**@file * *minimalexamplefilesystemusinglow-levelAPI * *Compilewith: * *gcc-Wallhello_ll.c`pkg-configfuse3--cflags--libs`-ohello_ll * *##Sourcecode## *\includehello_ll.c */ #defineFUSE_USE_VERSION30 #include<config.h> #include<fuse_lowlevel.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<fcntl.h> #include<unistd.h> #include<assert.h> staticconstchar*hello_str="HelloWorld!\n"; staticconstchar*hello_name="hello"; //change1#0 staticconstchar*inode5_str="http://www.datahf.net!\n"; staticconstchar*inode5_name="frombyte"; //changeend staticinthello_stat(fuse_ino_tino,structstat*stbuf) { stbuf->st_ino=ino; switch(ino){ case1: stbuf->st_mode=S_IFDIR|0755; stbuf->st_nlink=2; break; case2: stbuf->st_mode=S_IFREG|0444; stbuf->st_nlink=1; stbuf->st_size=strlen(hello_str); break; //change1#1 case5: stbuf->st_mode=S_IFREG|0444; stbuf->st_nlink=1; stbuf->st_size=strlen(inode5_str); break; //change1end default: return-1; } return0; } staticvoidhello_ll_getattr(fuse_req_treq,fuse_ino_tino, structfuse_file_info*fi) { structstatstbuf; (void)fi; memset(&stbuf,0,sizeof(stbuf)); if(hello_stat(ino,&stbuf)==-1) fuse_reply_err(req,ENOENT); else fuse_reply_attr(req,&stbuf,1.0); } staticvoidhello_ll_lookup(fuse_req_treq,fuse_ino_tparent,constchar*name) { structfuse_entry_parame; //change1#2 /* if(parent!=1||strcmp(name,hello_name)!=0) fuse_reply_err(req,ENOENT); else{ memset(&e,0,sizeof(e)); e.ino=2; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); }*/ if(parent!=1) fuse_reply_err(req,ENOENT); elseif(strcmp(name,hello_name)==0){ memset(&e,0,sizeof(e)); e.ino=2; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } elseif(strcmp(name,inode5_name)==0){ memset(&e,0,sizeof(e)); e.ino=5; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } else fuse_reply_err(req,ENOENT); //change1end } structdirbuf{ char*p; size_tsize; }; staticvoiddirbuf_add(fuse_req_treq,structdirbuf*b,constchar*name, fuse_ino_tino) { structstatstbuf; size_toldsize=b->size; b->size+=fuse_add_direntry(req,NULL,0,name,NULL,0); b->p=(char*)realloc(b->p,b->size); memset(&stbuf,0,sizeof(stbuf)); stbuf.st_ino=ino; fuse_add_direntry(req,b->p+oldsize,b->size-oldsize,name,&stbuf, b->size); } #definemin(x,y)((x)<(y)?(x):(y)) staticintreply_buf_limited(fuse_req_treq,constchar*buf,size_tbufsize, off_toff,size_tmaxsize) { if(off<bufsize) returnfuse_reply_buf(req,buf+off, min(bufsize-off,maxsize)); else returnfuse_reply_buf(req,NULL,0); } staticvoidhello_ll_readdir(fuse_req_treq,fuse_ino_tino,size_tsize, off_toff,structfuse_file_info*fi) { (void)fi; if(ino!=1) fuse_reply_err(req,ENOTDIR); else{ structdirbufb; memset(&b,0,sizeof(b)); dirbuf_add(req,&b,".",1); dirbuf_add(req,&b,"..",1); dirbuf_add(req,&b,hello_name,2); //change1 dirbuf_add(req,&b,inode5_name,5); //end reply_buf_limited(req,b.p,b.size,off,size); free(b.p); } } staticvoidhello_ll_open(fuse_req_treq,fuse_ino_tino, structfuse_file_info*fi) { //change1 //if(ino!=2) if((ino!=2)&&(ino!=5)) //end fuse_reply_err(req,EISDIR); elseif((fi->flags&3)!=O_RDONLY) fuse_reply_err(req,EACCES); else fuse_reply_open(req,fi); } staticvoidhello_ll_read(fuse_req_treq,fuse_ino_tino,size_tsize, off_toff,structfuse_file_info*fi) { (void)fi; //change1 //assert(ino==2); //reply_buf_limited(req,hello_str,strlen(hello_str),off,size); switch(ino){ case2: reply_buf_limited(req,hello_str,strlen(hello_str),off,size); break; case5: reply_buf_limited(req,inode5_str,strlen(inode5_str),off,size); break; default: ; } //end } staticstructfuse_lowlevel_opshello_ll_oper={ .lookup =hello_ll_lookup, .getattr =hello_ll_getattr, .readdir =hello_ll_readdir, .open =hello_ll_open, .read =hello_ll_read, }; intmain(intargc,char*argv[]) { structfuse_argsargs=FUSE_ARGS_INIT(argc,argv); structfuse_session*se; structfuse_cmdline_optsopts; intret=-1; if(fuse_parse_cmdline(&args,&opts)!=0) return1; if(opts.show_help){ printf("usage:%s[options]<mountpoint>\n\n",argv[0]); fuse_cmdline_help(); fuse_lowlevel_help(); ret=0; gotoerr_out1; }elseif(opts.show_version){ printf("FUSElibraryversion%s\n",fuse_pkgversion()); fuse_lowlevel_version(); ret=0; gotoerr_out1; } se=fuse_session_new(&args,&hello_ll_oper, sizeof(hello_ll_oper),NULL); if(se==NULL) gotoerr_out1; if(fuse_set_signal_handlers(se)!=0) gotoerr_out2; if(fuse_session_mount(se,opts.mountpoint)!=0) gotoerr_out3; fuse_daemonize(opts.foreground); /*Blockuntilctrl+corfusermount-u*/ if(opts.singlethread) ret=fuse_session_loop(se); else ret=fuse_session_loop_mt(se,opts.clone_fd); fuse_session_unmount(se); err_out3: fuse_remove_signal_handlers(se); err_out2: fuse_session_destroy(se); err_out1: free(opts.mountpoint); fuse_opt_free_args(&args); returnret?1:0; } 结果测试: cd~/fuse-3.0.0rc3/example/ make ./hello_ll/mnt ll-i/mnt cat/mnt/frombyte umount/mnt 2、增加目录、增加二进制文件测试: /* FUSE:FilesysteminUserspace Copyright(C)2001-2007MiklosSzeredi<miklos@szeredi.hu> ThisprogramcanbedistributedunderthetermsoftheGNUGPL. SeethefileCOPYING. */ /**@file * *minimalexamplefilesystemusinglow-levelAPI * *Compilewith: * *gcc-Wallhello_ll.c`pkg-configfuse3--cflags--libs`-ohello_ll * *##Sourcecode## *\includehello_ll.c */ #defineFUSE_USE_VERSION30 #include<config.h> #include<fuse_lowlevel.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<fcntl.h> #include<unistd.h> #include<assert.h> staticconstchar*hello_str="HelloWorld!\n"; staticconstchar*hello_name="hello"; //change1#0 staticconstchar*inode5_str="http://www.datahf.net!\n"; staticconstchar*inode5_name="frombyte"; staticconstchar*inode3_name="frombyte.dir"; staticconstchar*inode6_name="inode6.img"; //changeend staticinthello_stat(fuse_ino_tino,structstat*stbuf) { stbuf->st_ino=ino; switch(ino){ case1: stbuf->st_mode=S_IFDIR|0755; stbuf->st_nlink=3; break; case2: stbuf->st_mode=S_IFREG|0444; stbuf->st_nlink=1; stbuf->st_size=strlen(hello_str); break; //change1#1 case3: stbuf->st_mode=S_IFDIR|0755; stbuf->st_nlink=2; break; case5: stbuf->st_mode=S_IFREG|0444; stbuf->st_nlink=1; stbuf->st_size=strlen(inode5_str); break; case6: stbuf->st_mode=S_IFREG|0444; stbuf->st_nlink=1; stbuf->st_size=1024*1024*1024; break; //change1end default: return-1; } return0; } staticvoidhello_ll_getattr(fuse_req_treq,fuse_ino_tino, structfuse_file_info*fi) { structstatstbuf; (void)fi; memset(&stbuf,0,sizeof(stbuf)); if(hello_stat(ino,&stbuf)==-1) fuse_reply_err(req,ENOENT); else fuse_reply_attr(req,&stbuf,1.0); } staticvoidhello_ll_lookup(fuse_req_treq,fuse_ino_tparent,constchar*name) { structfuse_entry_parame; //change1#2 /* if(parent!=1||strcmp(name,hello_name)!=0) fuse_reply_err(req,ENOENT); else{ memset(&e,0,sizeof(e)); e.ino=2; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); }*/ switch(parent){ case1: if(strcmp(name,hello_name)==0){ memset(&e,0,sizeof(e)); e.ino=2; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } elseif(strcmp(name,inode3_name)==0){ memset(&e,0,sizeof(e)); e.ino=3; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } else fuse_reply_err(req,ENOENT); break; case3: if(strcmp(name,inode5_name)==0){ memset(&e,0,sizeof(e)); e.ino=5; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } elseif(strcmp(name,inode6_name)==0){ memset(&e,0,sizeof(e)); e.ino=6; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } else fuse_reply_err(req,ENOENT); break; default: fuse_reply_err(req,ENOENT); break; } //change1end } structdirbuf{ char*p; size_tsize; }; staticvoiddirbuf_add(fuse_req_treq,structdirbuf*b,constchar*name, fuse_ino_tino) { structstatstbuf; size_toldsize=b->size; b->size+=fuse_add_direntry(req,NULL,0,name,NULL,0); b->p=(char*)realloc(b->p,b->size); memset(&stbuf,0,sizeof(stbuf)); stbuf.st_ino=ino; fuse_add_direntry(req,b->p+oldsize,b->size-oldsize,name,&stbuf, b->size); } #definemin(x,y)((x)<(y)?(x):(y)) staticintreply_buf_limited(fuse_req_treq,constchar*buf,size_tbufsize, off_toff,size_tmaxsize) { if(off<bufsize) returnfuse_reply_buf(req,buf+off, min(bufsize-off,maxsize)); else returnfuse_reply_buf(req,NULL,0); } staticvoidhello_ll_readdir(fuse_req_treq,fuse_ino_tino,size_tsize, off_toff,structfuse_file_info*fi) { (void)fi; /* if(ino!=1) fuse_reply_err(req,ENOTDIR); else{*/ structdirbufb; switch(ino){ case1: memset(&b,0,sizeof(b)); dirbuf_add(req,&b,".",1); dirbuf_add(req,&b,"..",1); dirbuf_add(req,&b,hello_name,2); //change1 dirbuf_add(req,&b,inode3_name,3); //end reply_buf_limited(req,b.p,b.size,off,size); free(b.p); break; case3: memset(&b,0,sizeof(b)); dirbuf_add(req,&b,".",3); dirbuf_add(req,&b,"..",1); dirbuf_add(req,&b,inode5_name,5); dirbuf_add(req,&b,inode6_name,6); reply_buf_limited(req,b.p,b.size,off,size); free(b.p); break; default: fuse_reply_err(req,ENOTDIR); break; } //} } staticvoidhello_ll_open(fuse_req_treq,fuse_ino_tino, structfuse_file_info*fi) { //change1 //if(ino!=2) switch(ino) { case2:case5:case6: if((fi->flags&3)!=O_RDONLY) fuse_reply_err(req,EACCES); else fuse_reply_open(req,fi); break; default: fuse_reply_err(req,EISDIR); break; } } staticvoidhello_ll_read(fuse_req_treq,fuse_ino_tino,size_tsize, off_toff,structfuse_file_info*fi) { (void)fi; char*tbuf; //change1 //assert(ino==2); //reply_buf_limited(req,hello_str,strlen(hello_str),off,size); switch(ino){ case2: reply_buf_limited(req,hello_str,strlen(hello_str),off,size); break; case5: reply_buf_limited(req,inode5_str,strlen(inode5_str),off,size); break; case6: tbuf=(char*)malloc(size); for(inti=0;i<size/sizeof(int);i++) ((int*)tbuf)[i]=size; fuse_reply_buf(req,tbuf,size); free(tbuf); default: ; } //end } staticstructfuse_lowlevel_opshello_ll_oper={ .lookup =hello_ll_lookup, .getattr =hello_ll_getattr, .readdir =hello_ll_readdir, .open =hello_ll_open, .read =hello_ll_read, }; intmain(intargc,char*argv[]) { structfuse_argsargs=FUSE_ARGS_INIT(argc,argv); structfuse_session*se; structfuse_cmdline_optsopts; intret=-1; if(fuse_parse_cmdline(&args,&opts)!=0) return1; if(opts.show_help){ printf("usage:%s[options]<mountpoint>\n\n",argv[0]); fuse_cmdline_help(); fuse_lowlevel_help(); ret=0; gotoerr_out1; }elseif(opts.show_version){ printf("FUSElibraryversion%s\n",fuse_pkgversion()); fuse_lowlevel_version(); ret=0; gotoerr_out1; } se=fuse_session_new(&args,&hello_ll_oper, sizeof(hello_ll_oper),NULL); if(se==NULL) gotoerr_out1; if(fuse_set_signal_handlers(se)!=0) gotoerr_out2; if(fuse_session_mount(se,opts.mountpoint)!=0) gotoerr_out3; fuse_daemonize(opts.foreground); /*Blockuntilctrl+corfusermount-u*/ if(opts.singlethread) ret=fuse_session_loop(se); else ret=fuse_session_loop_mt(se,opts.clone_fd); fuse_session_unmount(se); err_out3: fuse_remove_signal_handlers(se); err_out2: fuse_session_destroy(se); err_out1: free(opts.mountpoint); fuse_opt_free_args(&args); returnret?1:0; } 3、fuse的根节点号是1,在源码中是以常量的方式定义的,本来想改成变量,估计工作量和稳定性会有麻烦,变通处理吧。 4、修改代码,实现自定义文件生成 /* FUSE:FilesysteminUserspace Copyright(C)2001-2007MiklosSzeredi<miklos@szeredi.hu> ThisprogramcanbedistributedunderthetermsoftheGNUGPL. SeethefileCOPYING. */ /**@file * *minimalexamplefilesystemusinglow-levelAPI * *Compilewith: * *gcc-Wallhello_ll.c`pkg-configfuse3--cflags--libs`-ohello_ll * *##Sourcecode## *\includehello_ll.c */ /*change2: 定义一个idx文件,格式为typedefstructStr_idx{ intlow_off; shorthige_off; shortfileid; }str_idx; 按每8字节一个索引的方式组合某个镜像文件,文件ID为0表示自由,用字符'F'填充。 文件ID为1,表示使用当前目录下的$MFT文件做为数据源进行加工。 测试代码,至少还需补全: 1、配置文件(文件大小、源文件路径等)的参数指定 2、idx结构的准确大小(int,short和机器位长有关系,需修改为与机器位长无关的数据类型) 3、排错:文件打不开 4、排错:文件大小与idx不符 5、排错:文件溢出处理 6、修改缓冲机制,不能先把源文件全读到内存,需要建立缓冲机制,应对读函数,或者简单地用fopen加缓冲处理。 bywww.datahf.net张宇 */ #defineFUSE_USE_VERSION30 #include<config.h> #include<fuse_lowlevel.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<fcntl.h> #include<unistd.h> #include<assert.h> #include<string.h> staticconstchar*hello_str="HelloWorld!\n"; staticconstchar*hello_name="hello"; //change1#0 staticconstchar*inode5_str="http://www.datahf.net!\n"; staticconstchar*inode5_name="frombyte"; staticconstchar*inode3_name="frombyte.dir"; staticconstchar*inode6_name="inode6.img"; unsignedchar*databuf; #defineINODE6_SIZE(1024*1024*4) //changeend staticinthello_stat(fuse_ino_tino,structstat*stbuf) { stbuf->st_ino=ino; switch(ino){ case1: stbuf->st_mode=S_IFDIR|0755; stbuf->st_nlink=3; break; case2: stbuf->st_mode=S_IFREG|0444; stbuf->st_nlink=1; stbuf->st_size=strlen(hello_str); break; //change1#1 case3: stbuf->st_mode=S_IFDIR|0755; stbuf->st_nlink=2; break; case5: stbuf->st_mode=S_IFREG|0444; stbuf->st_nlink=1; stbuf->st_size=strlen(inode5_str); break; case6: stbuf->st_mode=S_IFREG|0444; stbuf->st_nlink=1; stbuf->st_size=INODE6_SIZE; break; //change1end default: return-1; } return0; } staticvoidhello_ll_getattr(fuse_req_treq,fuse_ino_tino, structfuse_file_info*fi) { structstatstbuf; (void)fi; memset(&stbuf,0,sizeof(stbuf)); if(hello_stat(ino,&stbuf)==-1) fuse_reply_err(req,ENOENT); else fuse_reply_attr(req,&stbuf,1.0); } staticvoidhello_ll_lookup(fuse_req_treq,fuse_ino_tparent,constchar*name) { structfuse_entry_parame; //change1#2 /* if(parent!=1||strcmp(name,hello_name)!=0) fuse_reply_err(req,ENOENT); else{ memset(&e,0,sizeof(e)); e.ino=2; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); }*/ switch(parent){ case1: if(strcmp(name,hello_name)==0){ memset(&e,0,sizeof(e)); e.ino=2; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } elseif(strcmp(name,inode3_name)==0){ memset(&e,0,sizeof(e)); e.ino=3; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } else fuse_reply_err(req,ENOENT); break; case3: if(strcmp(name,inode5_name)==0){ memset(&e,0,sizeof(e)); e.ino=5; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } elseif(strcmp(name,inode6_name)==0){ memset(&e,0,sizeof(e)); e.ino=6; e.attr_timeout=1.0; e.entry_timeout=1.0; hello_stat(e.ino,&e.attr); fuse_reply_entry(req,&e); } else fuse_reply_err(req,ENOENT); break; default: fuse_reply_err(req,ENOENT); break; } //change1end } structdirbuf{ char*p; size_tsize; }; //change2 typedefstructStr_idx{ intlow_off; shorthige_off; shortfileid; }str_idx; staticvoiddirbuf_add(fuse_req_treq,structdirbuf*b,constchar*name, fuse_ino_tino) { structstatstbuf; size_toldsize=b->size; b->size+=fuse_add_direntry(req,NULL,0,name,NULL,0); b->p=(char*)realloc(b->p,b->size); memset(&stbuf,0,sizeof(stbuf)); stbuf.st_ino=ino; fuse_add_direntry(req,b->p+oldsize,b->size-oldsize,name,&stbuf, b->size); } #definemin(x,y)((x)<(y)?(x):(y)) staticintreply_buf_limited(fuse_req_treq,constchar*buf,size_tbufsize, off_toff,size_tmaxsize) { if(off<bufsize) returnfuse_reply_buf(req,buf+off, min(bufsize-off,maxsize)); else returnfuse_reply_buf(req,NULL,0); } staticvoidhello_ll_readdir(fuse_req_treq,fuse_ino_tino,size_tsize, off_toff,structfuse_file_info*fi) { (void)fi; /* if(ino!=1) fuse_reply_err(req,ENOTDIR); else{*/ structdirbufb; switch(ino){ case1: memset(&b,0,sizeof(b)); dirbuf_add(req,&b,".",1); dirbuf_add(req,&b,"..",1); dirbuf_add(req,&b,hello_name,2); //change1 dirbuf_add(req,&b,inode3_name,3); //end reply_buf_limited(req,b.p,b.size,off,size); free(b.p); break; case3: memset(&b,0,sizeof(b)); dirbuf_add(req,&b,".",3); dirbuf_add(req,&b,"..",1); dirbuf_add(req,&b,inode5_name,5); dirbuf_add(req,&b,inode6_name,6); reply_buf_limited(req,b.p,b.size,off,size); free(b.p); break; default: fuse_reply_err(req,ENOTDIR); break; } //} } staticvoidhello_ll_open(fuse_req_treq,fuse_ino_tino, structfuse_file_info*fi) { //change1 //if(ino!=2) switch(ino) { case2:case5:case6: if((fi->flags&3)!=O_RDONLY) fuse_reply_err(req,EACCES); else fuse_reply_open(req,fi); break; default: fuse_reply_err(req,EISDIR); break; } } staticvoidhello_ll_read(fuse_req_treq,fuse_ino_tino,size_tsize, off_toff,structfuse_file_info*fi) { (void)fi; //change1 //assert(ino==2); //reply_buf_limited(req,hello_str,strlen(hello_str),off,size); switch(ino){ case2: reply_buf_limited(req,hello_str,strlen(hello_str),off,size); break; case5: reply_buf_limited(req,inode5_str,strlen(inode5_str),off,size); break; case6: fuse_reply_buf(req,databuf+off,size); default: ; } //end } staticstructfuse_lowlevel_opshello_ll_oper={ .lookup =hello_ll_lookup, .getattr =hello_ll_getattr, .readdir =hello_ll_readdir, .open =hello_ll_open, .read =hello_ll_read, }; intmain(intargc,char*argv[]) { structfuse_argsargs=FUSE_ARGS_INIT(argc,argv); structfuse_session*se; structfuse_cmdline_optsopts; intret=-1; if(fuse_parse_cmdline(&args,&opts)!=0) return1; if(opts.show_help){ printf("usage:%s[options]<mountpoint>\n\n",argv[0]); fuse_cmdline_help(); fuse_lowlevel_help(); ret=0; gotoerr_out1; }elseif(opts.show_version){ printf("FUSElibraryversion%s\n",fuse_pkgversion()); fuse_lowlevel_version(); ret=0; gotoerr_out1; } //change2 FILE*f_idx,*f_img; f_idx=fopen("./1.idx","rb"); f_img=fopen("./$MFT","rb"); if((f_idx==-1)||(f_img==-1)) { printf("f_idxis%d\nf_imgis%d\n",f_idx,f_img); gotoerr_out1; } size_ts_idx,s_img; s_idx=512; unsignedcharidx_buf[512]; databuf=NULL; databuf=(char*)malloc(INODE6_SIZE); fread(idx_buf,512,1,f_idx); inti=0; structStr_idx*tidx; tidx=(structStr_idx*)idx_buf; for(i=0;i<4;i++) { if(tidx[i].fileid==0) memset(databuf+i*1024*1024,'F',1024*1024); elseif(tidx[i].fileid==1) { fseek(f_img, tidx[i].low_off*1024*1024+tidx[i].hige_off*1024*1024, SEEK_SET); fread(databuf+i*1024*1024,1024*1024,1,f_img); } else ; printf("#i:%d,%d,%d\n",tidx[i].low_off,tidx[i].hige_off,tidx[i].fileid); } se=fuse_session_new(&args,&hello_ll_oper, sizeof(hello_ll_oper),NULL); if(se==NULL) gotoerr_out1; if(fuse_set_signal_handlers(se)!=0) gotoerr_out2; if(fuse_session_mount(se,opts.mountpoint)!=0) gotoerr_out3; fuse_daemonize(opts.foreground); /*Blockuntilctrl+corfusermount-u*/ if(opts.singlethread) ret=fuse_session_loop(se); else ret=fuse_session_loop_mt(se,opts.clone_fd); fuse_session_unmount(se); err_out3: fuse_remove_signal_handlers(se); err_out2: fuse_session_destroy(se); err_out1: free(opts.mountpoint); fuse_opt_free_args(&args); returnret?1:0; } 待续

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册