Chinaunix首页 | 论坛 | 博客
  • 博客访问: 491539
  • 博文数量: 72
  • 博客积分: 1851
  • 博客等级: 上尉
  • 技术积分: 1464
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-16 17:50
文章分类

全部博文(72)

文章存档

2013年(1)

2012年(17)

2011年(51)

2010年(3)

分类: LINUX

2011-06-20 16:09:53

处理流程

当线程执行do_work操作之后,开始调用函数fuse_chan_recv读取/dev/fuse设备中的请求,接着处理的流程如下:

process:生成具体的请求

       ----->op():ino转化为具体请求路径

         ---->user level op:用户级程序操作

           ------> return:返回

下面分析各个函数原型

读取请求

函数原型如下:

  1. ///dev/fuse设备中读取数据,调用函数为:fuse_chan_recv(&ch,w->buf,w->bufsize)
  2. //bufsize定义大小为:min(getpagsize()+0x1000,0x21000),发送协议规定包头至少8K
  3. int fuse_chan_recv(struct fuse_chan **chp,char* buf,size_t size)
  4. {
  5.     struct fuse_chan *ch=*chp;
  6.     if(ch->compat)
  7.         return ((struct fuse_chan_ops_compat24 *)&ch->op)
  8.             ->receive(ch,buf,size);
  9.     else     
  10.         return ch->op.receive(chp,buf,size);
  11. }

上面的 op.receive函数则具体指向的函数如下:

  1. static int fuse_kern_chan_receive(struct fuse_chan **chp,char *buf,
  2.                         size_t size)
  3. {
  4.     ….
  5. restart:
  6.      res = read(fuse_chan_fd(ch),buf,size);
  7.      err = errno;
  8.     
  9.      if(fuse_session_exited(se)) return 0;
  10.      if(res==-1) {
  11.         //此错误代表被中断,可以进行重启
  12.         if(err == ENOENT) goto restart;
  13.         if(err == ENODEV) {
  14.             fuse_session_exit(se);
  15.             return 0;
  16.         }
  17.         if(err!=EINTR && err !=EAGAIN)
  18.             perror(“fuse:reading device”);
  19.         return -err;
  20.     }
  21.     //数据至少有一个包头
  22.      if((size_t)res < sizeof(sruct fuse_in_header)) {
  23.         fprintf(stderr,” short read on fuse device\n”);
  24.         return -EIO;
  25. }
  26.         return res;
  27. }

处理请求

在数据读取完成之后,就进行处理:

fuse_session_process(mt->se,w->buf,res,ch);

函数原型如下:

  1. void fuse_session_process(struct fuse_session *se,const char* buf,size_t len,struct fuse_chan *ch)
  2. {
  3.     se->op.process(se->data,buf,len,ch);
  4. }

session在进行初始化时,处理函数如下:

在该函数中使用的数据结构如下:

  1. //请求链表
  2. struct fuse_req {
  3.      struct fuse_ll *f;
  4.      uint64_t unique;
  5.      int ctr;
  6.      pthread_mutex_t lock;
  7.      struct fuse_ctx ctx;
  8.      struct fuse_chan *ch;
  9.      int interrupted;
  10.      union {
  11.     struct {
  12.          uint64_t unique;
  13.     }i;
  14.     struct {
  15.         fuse_interrupt_func_t func;
  16.         void *data;
  17.     }ni;
  18.     }u;
  19.     struct fuse_req *next;
  20.     struct fuse_req *prev;
  21. };
  22. //与请求相关的上下文
  23. struct fuse_ctx {
  24.     uid_t uid;//调用进程的用户ID
  25.     gid_t gid;//调用线程的组ID
  26.     pid_t pid;//调用线程的进程ID
  27.     mode_t mask;//调用线程的文件掩码
  28. }
  29. //与读写相关的参数
  30. struct fuse_ll{
  31.     int debug;
  32.     int allow_root;
  33.     int atomic_o trunc;
  34.     int no_remote_lock;
  35.     int big_writes;
  36.     struct fuse_lowlevel_ops op;
  37.     int got_init;
  38.     struct cuse_data *cuse_data;
  39.     void *cuse_data;
  40.     uid_t owner;
  41.     struct fuse_conn_info conn;
  42.     struct fuse_req list;//一个正常操作链表
  43.     struct fuse_req interrupts;//一个中断操作链表
  44.     pthread_mutex_t lock;
  45.     int got_destroy;
  46. }

低级处理

  1. static void fuse_ll_process(void*data,const char*buf,size_t len,struct fuse_chan *ch)
  2. {
  3.     //系统初始化时,就已经设置,通过用户指定的命令参数
  4.     struct fuse_ll *f = (struct fuse_ll*)data;
  5.     //转化为读取的数据包头信息
  6.     struct fuse_in_header *in = (struct fuse_in_header *)buf;
  7.     //包头后面就是具体参数了,直接通过偏移量实现
  8.     const void *inarg = buf+sizeof(struct fuse_in_header);
  9.     struct fuse_req *req;
  10.     ….......
  11.     //生成具体的请求包头
  12.     req = (struct fuse_req*)calloc(1,sizeof(struct fuse_req));
  13.     ….
  14.     req->f = f;
  15.     req->unique = in->unique;
  16.     req->ctx.uid = in->uid;
  17.     req->ctx.gid = in->gid;
  18.     req->ctx.pid = in->pid;
  19.     req->ch = ch;
  20.     req->ctr = 1;
  21.     list_init_req(req);
  22.     fuse_mutex_init(&req->lock);
  23.     
  24.     err = EIO;
  25.     //如果没有初始化
  26.     if(!f->got_init) {
  27.      enum fuse_opcode expected;
  28.     //有两种设备/dev/cuse,/dev/fuse,当打开设备或者挂载上去时,就发送初始化信息
  29.     expected = f->cuse_data?CUSE_INIT:FUSE_INIT;
  30.     if(in->opcode != expected)
  31.         goto reply_err;
  32.     } else if(in->opcode == FUSE_INIT || in->opcode ==CUSE_INIT)
  33.         goto reply_err;
  34.     err = EACCES;
  35.     //在允许权限中处理这些函数
  36.     if(f->allow_root && in->uid !=f->owner && in->uid!=0&&
  37.      in->opcode != FUSE_INIT && in->opcode !=FUSE_READ &&
  38.      in-> FUSE_WRITE && in-> FUSE_FSYNC &&
  39.      in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
  40.      in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR)
  41.         goto reply_err;
  42.     err = ENOSYS;
  43.     //判断操作码是否合法
  44.     if(in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
  45.         goto reply_err;
  46.     //如果没有被中断,就从中断的链表中删除,同时添加到正常的链表中去
  47.     if(in->opcode != FUSE_INTERRUPT) {
  48.     struct fuse_req *intr;
  49.     pthread_mutex_lock(&f->lock);
  50.     
  51.     intr = check_interrrupt(f,req);
  52.     list_add_req(req,&f->list);
  53.     pthread_mutex_unlock(&f->lock);
  54.     if(intr)
  55.         fuse_reply_err(intr,EAGAIN);
  56. }
  57.     //转发到具体的操作函数
  58.     fuse_ll_ops[in->opcode].func(req,in->nodeid,inarg);
  59.     return;
  60. reply_err:
  61.     fuse_reply_err(req,err);
  62. }

中断处理

当正在操作fuse文件系统的程序被中断后,fuse内核模块就接收到INTERRUPT信号,该模块立即将此请求转发至客户端,处理模块如下:

  1. static void do_interrupt(fuse_req_t req,fuse_ino_t nodeid,const void* inarg)
  2. {
  3.     //struct fuse_interrupt_in 中只有一个参数:__u64 unique
  4.     struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *)inarg;
  5.     //提取与请求相关的数据
  6.     struct fuse_ll *f = req->f;
  7.     
  8.     (void) nodeid;
  9.     if(f->debug)
  10.         fprintf(stderr,”INTERRUPT: %llu\n”,(unsigned long long)arg->unique);
  11.     //设置得到的需要被中断请求标识符
  12.     req->u.i.unique = arg->unique;
  13.     
  14.     pthread_mutex_lock(&f->lock);
  15.     //如果在正常的链表中找到对应的请求,删除该请求,如果出现在中断链表中,就简单返回
  16.     if(find_interrupt(f,req))
  17.         destroy_req(req);
  18.     else
  19.         //没有查找到就加入中断链表中
  20.         list_add_req(req,&f->interrupts);

  21.     //不用进行回复
  22.     pthread_mutex_unlock(&f->lock);
  23. }

阅读(3290) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~