fuse相关流程.docx

上传人:b****3 文档编号:12633259 上传时间:2023-04-21 格式:DOCX 页数:18 大小:776.64KB
下载 相关 举报
fuse相关流程.docx_第1页
第1页 / 共18页
fuse相关流程.docx_第2页
第2页 / 共18页
fuse相关流程.docx_第3页
第3页 / 共18页
fuse相关流程.docx_第4页
第4页 / 共18页
fuse相关流程.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

fuse相关流程.docx

《fuse相关流程.docx》由会员分享,可在线阅读,更多相关《fuse相关流程.docx(18页珍藏版)》请在冰豆网上搜索。

fuse相关流程.docx

fuse相关流程

1Fuse系统架构

图1系统架构

整体上分2个部分:

a)用户态libfuse

b)内核fuse:

◆Fuse文件系统

◆/dev/fuse设备驱动

2Fuse的结构

Fuse包括三个模块:

用户空间库,内核模块以及mount工具

(1)用户库(2.9.2)

提供编程接口,程序员通过实现fuse提供的两组接口fuse_lowlevel_ops,fuse_operations之一即可实现一个用户空间文件系统。

(2)内核模块(3.10.X):

实现了一个完整文件系统的框架。

(3)mount工具fusermount(这个代码由用户库提供,fusermount.c):

用于挂载基于fuse的文件系统。

3Fuse下write的整体流程(用户空间和kernel)

图2fuse下write流程

在基于FUSE的用户空间文件系统中执行write操作的流程如图2所示

流程说明:

(1)客户端在mount目录下,对一个file调用write,这一步是在用户空间执行;

(2)Write内部会调用vfs提供的一致性接口vfs_write;

(3)根据fuse模块注册的file_operations信息,vfs_write会调用fuse_file_aio_write,将写请求放入到requestpendingqueue,随后进入睡眠等待应用程序reply。

见kernel中fs/fuse/dev.c中的fuse_request_send:

●将请求加入到pending队列

●唤醒等待队列(wake_up(&fc->waitq)),这时fuse_dev_do_read中request_wait就会被唤醒,fuse_session_loop就会从pending队列中取数据

(4)用户空间的libfuse的fuse_session_loop轮询设备/dev/fuse,一旦requestqueue有请求即通过fuse_kern_chan_receive接收;

(5)Fuse_kern_chan_receive通过read读取requestqueue中的内容,read系统调用实际上是调用的/dev/fuse设备驱动接口fuse_dev_read;

(6)用户空间读取分析数据,执行用户定义的wirte操作,将状态通过fuse_reply_write返回给kernel;

(7)fuse_reply_write调用vfs提供的一致性接口vfs_write

(8)vfs_write最终调用fuse_dev_wirte将执行结果返回给第3步中等待在waitq的进程,此进程得到reply后,write返回

注意:

fuse文件系统和/dev/fuse的注册在kernelfs/fuse/inode.c的fuse_init中,分别初始化了fuse_init_inode和fuse_dev_init

4fuse在用户空间工作的流程图

图3libfuse的工作流程

 

关键点说明:

(1)fusermount会调用kernel的fuse_mount,fuse_fill_super中file->private_data=fuse_conn_get(fc)是一个关键的部分,file就是/dev/fuse。

(2)fuse_session_loop会不停的调用fuse_session_receive_buf,最终调用fuse_dev_read,然后request_wait等待requestqueue中有数据并被唤醒,然后从queue中取出数据返回给用户空间

(3)fuse_session_proc中完成libfuse注册的api接口,见附录一的代码,fuse_session_proc中会调用sfs_write来完成相应的工作(有可能会调用其他的接口),一个posix对应1或多个libfuse中注册的api

5Fusewrite的详细流程

客户端在mount目录下,对一个file调用write,这一步是在用户空间执行,Write内部会调用vfs提供的一致性接口vfs_write,根据fuse文件系统注册的接口,最终会调用fuse_file_aio_write

图4

图5

 

关键说明:

(1)图5中的fuse_write_fill完成fuse数据的填充,如操作码等

(2)fuse_request_send是关键部分:

●将request插入到pending队列,并将req的状态置为FUSE_REQ_PENDING

●唤醒等待队列wake_up(&fc->waitq)

●异步通知用户进程数据到达kill_fasync(&fc->fasync,SIGIO,POLL_IN)

●调用request_wait_answer,进程休眠,等待请求完成wait_event(req->waitq,req->state==FUSE_REQ_FINISHED)。

用户进程处理完请求,它会replay,休眠的进程(request_wait_answer)被唤醒,request_wait_answer返回,向上层返回结果。

 

用户态的进程在fuse_session_loop中循环read(读取/dev/fuse),read最终调用fuse_dev_read。

图6

关键说明:

(1)fuse_dev_read首先通过fuse_get_conn获取structfuse_conn(它是在fuse_mount是就完成实例化的)

(2)request_wait等待请求到达:

(3)fuse_copy_one将数据拷贝到structfuse_copy_state的buf中(此buf指向应用层的void*buf)

用户态进程读取上面的数据,然后做相应的处理,以write为例,这是会调用sfs_write(附录一),sfs_write处理完后,调用fuse_lib_write_buf,然后调用fuse_reply_write回复,最终调用/dev/fuse注册的fuse_dev_write

图7

关键流程说明:

request_end:

请求处理完成,设置req->state=FUSE_REQ_FINISHED,唤醒等待在waitq的进程wake_up(&req->waitq),最终唤醒图5中的request_wait_answer

 

附录一

下面是基于fuse开发的文件系统

#defineFUSE_USE_VERSION29

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

intg_debug=1;

staticchar*rootdir;

staticvoidfullpath(charfpath[PATH_MAX],constchar*path)

{

strcpy(fpath,rootdir);

strncat(fpath,path,PATH_MAX);

}

voidsfs_usage()

{

fprintf(stderr,"usage:

sfsrootDirmountPoint\n");

abort();

}

staticintsfs_getattr(constchar*path,structstat*statbuf)

{

if(g_debug)

printf("-->sfs_getattr%s\n",path);

intret=0;

charfpath[PATH_MAX];

fullpath(fpath,path);

ret=lstat(fpath,statbuf);

if(ret!

=0)

{

if(g_debug)

printf("sfs_getattrlstaterror\n");

return-errno;

}

return0;

}

staticintsfs_open(constchar*path,structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_open%s\n",path);

intfd;

charfpath[PATH_MAX];

fullpath(fpath,path);

fd=open(fpath,fi->flags);

if(fd==-1)

return-errno;

fi->fh=fd;

return0;

}

staticintsfs_read(constchar*path,char*buf,size_tsize,off_toffset,

structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_read%s\n",path);

intret;

ret=pread(fi->fh,buf,size,offset);

if(ret==-1)

ret=-errno;

returnret;

}

staticintsfs_create(constchar*path,mode_tmode,structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_create%s\n",path);

intfd;

charfpath[PATH_MAX];

fullpath(fpath,path);

fd=open(fpath,fi->flags,mode);

if(fd==-1)

return-errno;

fi->fh=fd;

return0;

}

staticintsfs_write(constchar*path,constchar*buf,size_tsize,off_toffset,structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_write%s\n",path);

intret=0;

ret=pwrite(fi->fh,buf,size,offset);

if(ret<0)

{

return-errno;

}

returnret;

}

staticintsfs_unlink(constchar*path)

{

if(g_debug)

printf("-->sfs_unlink%s\n",path);

intret=0;

charfpath[PATH_MAX];

fullpath(fpath,path);

ret=unlink(fpath);

if(ret<0)

return-errno;

return0;

}

staticintsfs_fsync(constchar*path,intisdatasync,

structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_fsync%s\n",path);

intret;

(void)path;

ret=fsync(fi->fh);

if(ret==-1)

return-errno;

return0;

}

staticintsfs_truncate(constchar*path,off_tnewsize)

{

if(g_debug)

printf("-->sfs_truncate%s\n",path);

intret=0;

charfpath[PATH_MAX];

fullpath(fpath,path);

ret=truncate(fpath,newsize);

if(ret<0)

return-errno;

return0;

}

staticintsfs_flush(constchar*path,structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_flush%s\n",path);

intres;

(void)path;

res=close(dup(fi->fh));

if(res==-1)

return-errno;

return0;

}

staticintsfs_release(constchar*path,structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_release%s\n",path);

(void)path;

close(fi->fh);

return0;

}

staticintsfs_mkdir(constchar*path,mode_tmode)

{

if(g_debug)

printf("-->sfs_mkdir%s\n",path);

intres;

charfpath[PATH_MAX];

fullpath(fpath,path);

res=mkdir(fpath,mode);

if(res==-1)

return-errno;

return0;

}

intsfs_opendir(constchar*path,structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_opendir%s\n",path);

DIR*dp;

charfpath[PATH_MAX];

fullpath(fpath,path);

dp=opendir(fpath);

if(dp==NULL)

return-errno;

fi->fh=(uintptr_t)dp;

return0;

}

staticintsfs_readdir(constchar*path,void*buf,fuse_fill_dir_tfiller,off_toffset,

structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_readdir%s\n",path);

DIR*dp;

structdirent*de;

dp=(DIR*)(uintptr_t)fi->fh;

de=readdir(dp);

if(de==0)

{

return-errno;

}

do

{

//printf("-->sfs_readdir%s\n",de->d_name);

if(filler(buf,de->d_name,NULL,0)!

=0)

{

return-ENOMEM;

}

}while((de=readdir(dp))!

=NULL);

return0;

}

staticintsfs_releasedir(constchar*path,structfuse_file_info*fi)

{

if(g_debug)

printf("-->sfs_releasedir%s\n",path);

closedir((DIR*)(uintptr_t)fi->fh);

return0;

}

staticintsfs_utime(constchar*path,structutimbuf*ubuf)

{

if(g_debug)

printf("-->sfs_utime%s\n",path);

intret=0;

charfpath[PATH_MAX];

fullpath(fpath,path);

ret=utime(fpath,ubuf);

if(ret<0)

return-errno;

returnret;

}

staticintsfs_rmdir(constchar*path)

{

if(g_debug)

printf("-->sfs_rmdir%s\n",path);

intret=0;

charfpath[PATH_MAX];

fullpath(fpath,path);

ret=rmdir(fpath);

if(ret<0)

return-errno;

return0;

}

staticstructfuse_operationssfs_oper={

//.init=sfs_init,

.getattr=sfs_getattr,

.open=sfs_open,

.read=sfs_read,

.create=sfs_create,

.write=sfs_write,

.unlink=sfs_unlink,

.fsync=sfs_fsync,

.truncate=sfs_truncate,

.flush=sfs_flush,

.release=sfs_release,

.mkdir=sfs_mkdir,

.opendir=sfs_opendir,

.readdir=sfs_readdir,

.releasedir=sfs_releasedir,

.utime=sfs_utime,

.rmdir=sfs_rmdir,

};

intmain(intargc,char*argv[])

{

umask(0);

fprintf(stderr,"Fuselibraryversion%d.%d\n",FUSE_MAJOR_VERSION,FUSE_MINOR_VERSION);

if((argc<3)||(argv[argc-2][0]=='-')||(argv[argc-1][0]=='-'))

{

sfs_usage();

}

rootdir=malloc(sizeof(char)*1024);

if(rootdir==NULL)

{

perror("Unabletoallocatememoryforrootdirname\n");

abort();

}

rootdir=realpath(argv[argc-2],NULL);

argv[argc-2]=argv[argc-1];

argv[argc-1]=NULL;

argc--;

fprintf(stderr,"rootdir:

%s\n",rootdir);

structfuse_argsargs=FUSE_ARGS_INIT(argc,argv);

if(fuse_opt_parse(&args,NULL,NULL,NULL)==-1)

{

sfs_usage();

}

returnfuse_main(argc,argv,&sfs_oper,rootdir);

}

 

OS:

Centos7

●安装依赖包:

Yuminstallfuse-devel

●编译:

gccsfs.c-osfs`pkg-configfuse--cflags--libs`

●运行:

./sfs/root/fuse/root/root/fuse/mount

然后再/root/fuse/mount文件操作

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 中职中专

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1