现在的位置: 首页 > 综合 > 正文

FUSE队列管理浅析

2012年05月10日 ⁄ 综合 ⁄ 共 2719字 ⁄ 字号 评论关闭

fuse通过fuse_session_loop来启动守护程序,守护程序最终会调用fuse_dev_readv,fuse_dev_readv调用request_wait,使得进程在fcwaitq队列上睡眠。

 

代码片段1

static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,

                  unsigned long nr_segs, loff_t *off)

{

    …..

    request_wait(fc);

    ….

}

 

/* Wait until a request is available on the pending list */

static void request_wait(struct fuse_conn *fc)

{

    //定义一个队列节点变量wait,其与当前进程相关联

    DECLARE_WAITQUEUE(wait, current);

   

//wait加入到fc->waitq等待队列中,当有请求发到fuse文件系统时(通过request_send),这个等待队列上的进程会被唤醒,某一个进程会被赋予CPU使用权

    add_wait_queue_exclusive(&fc->waitq, &wait);

 

    //不断的检查fcpending队列及interrupts队列,看是否有请求,没有请求会一直while循环

    while (fc->connected && !request_pending(fc)) {

        set_current_state(TASK_INTERRUPTIBLE);

        if (signal_pending(current))

            break;

 

        spin_unlock(&fc->lock);

        schedule(); //选择一个进程运行

        spin_lock(&fc->lock);

    }

    //有请求,将进程设为TASK_RUNNING状态

    set_current_state(TASK_RUNNING);

    //wait从等待队列中移除

    remove_wait_queue(&fc->waitq, &wait);

}

 

static int request_pending(struct fuse_conn *fc)

{

    return !list_empty(&fc->pending) || !list_empty(&fc->interrupts);

}

             

request_send是用户请求经过vfs,再到fuse operation中被调用的,它向/dev/fuse发送请求

代码片段2

void request_send(struct fuse_conn *fc, struct fuse_req *req)

{

……

queue_request(fc, req);

request_wait_answer(fc, req);

……

}

 

static void queue_request(struct fuse_conn *fc, struct fuse_req *req)

{

//将请求加入到pending队列

list_add_tail(&req->list, &fc->pending);

req->state = FUSE_REQ_PENDING;

if (!req->waiting) {

            req->waiting = 1;

            atomic_inc(&fc->num_waiting);

}

//唤醒等待等列

wake_up(&fc->waitq);

kill_fasync(&fc->fasync, SIGIO, POLL_IN);

}

 

/* Called with fc->lock held.  Releases, and then reacquires it. */

static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)

{

     //该调用会在reqwaitq上睡眠,fuse守护程序处理完请求后,会将其唤醒

}

 

fuse守护程序处理完请求,最终通过fuse_dev_writev写回/dev/fuse,它将唤醒相应reqwaitq的等待队列元素,从而让文件系统请求完成request_wait_answer,获取到结果。

 

/*

Write a single reply to a request.  First the header is copied from the write buffer.  The request is then searched on the processing list by the unique ID found in the header.  If found, then remove it from the list and copy the rest of the buffer to the request. The request is finished by calling request_end()

 */

static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,

                           unsigned long nr_segs, loff_t *off)

{

req = request_find(fc, oh.unique);

request_end(fc, req);

           

}

 

/*

 * This function is called when a request is finished.  Either a reply

 * has arrived or it was aborted (and not yet sent) or some error

 * occurred during communication with userspace, or the device file

 * was closed.  The requester thread is woken up (if still waiting),

 * the 'end' callback is called if given, else the reference to the

 * request is released

 *

 * Called with fc->lock, unlocks it

 */

static void request_end(struct fuse_conn *fc, struct fuse_req *req)

{

//唤醒req上的等待队列

wake_up(&req->waitq);

}

 

抱歉!评论已关闭.