注册/删除回调中断处理函数
- /*
-
req:请求处理句柄
-
func:处理的回调函数
-
data:实参
-
*/
-
void fuse_req_interrupt_func(fuse_req_t req,fuse_interrupt_func_t func,
-
void *data);
在路由到具体操作时,需要进行调用处理函数,具体代码如下:
- //获取req所在的fuse结构,多线程共享
-
struct fuse *f = req_fuse_prepare(req);
-
/*实现互斥变量
-
struct fuse_intr_data {
-
pthread_t tid;
-
pthread_cond_t cond;
-
int finished;
-
}
-
*/
-
struct fuse_intr_data d;
-
…..
-
fuse_prepare_interrupt(f,req,&d);
-
….....
-
fuse_finish_interrupt(f,req,&d);
-
….....
现在进行分析上面的函数:
- //在进行真正操作前,需要判断该操作是否被中断
-
fuse_prepare_interrupt(struct fuse*f,fuse_req_t req,
-
struct fuse_intr_data *d)
-
--->fuse_do_prepare_interrupt(req,d)
-
static void fuse_do_prepare_interrupt(fuse_req_t req,struct fuse_intr_data *d)
-
{
-
d->id = pthread_self();
-
//条件变量初始化
-
pthread_cond_init(&d->cond,NULL);
-
d->finished = 0;
-
fuse_req_interrupt_func(req,fuse_interrupt,d);
-
}
-
//中断结束后,再次确认是否已经被中断
-
fuse_finish_interrupt(struct fuse *f,fuse_req_t req,
-
struct fuse_intr_data *d)
-
--->fuse_do_finish_interrupt(f,req,d);
-
static void fuse_do_finish_interrupt(struct fuse *f,fuse_req_t req,
-
struct fuse_intr_data *d)
-
{
-
pthread_mutex_lock(&f->lock);
-
d->finished = 1;
-
pthread_cond_broadcast(&d->cond);
-
pthread_mutex_unlock(&f->lock);
-
fuse_req_interrupt_func(req,NULL,NULL);
-
pthread_cond_destroy(&d->cond);
-
}
而fuse_req_interrupt_func操作则确认该操作是否被中断,如果中断则执行中断处理函数,否则就返回
- void fuse_req_interrupt_func(fuse_req_t req,fuse_interrupt_func_t func,
-
void *data)
-
{
-
pthread_mutex_lock(&req->lock);
-
pthread_mutex_lock(&req->f->lock);
-
//将中断处理函数的指针,数据挂接到req中
-
req->u.ni.func = func;
-
req->u.ni.data = data;
-
pthread_mutex_unlock(&req->f->lock);
-
//中断就处理指定的中断函数
-
if(req->interrupted && func)
-
func(req,data);
-
pthread_mutex_unlock(&req->lock);
-
}
中断处理函数:
- static void fuse_interrupt(fuse_req_t req, void *d_)
-
{
-
struct fuse_intr_data *d = d_;
-
struct fuse *f = req_fuse(req);
-
-
//如果再是本身线程中断,就说明操作已经完成,没有必要继续下去
-
if(d->id == pthread_self())
-
return;
-
-
pthread_mutex_lock(&f->lock);
-
while(!d->finished) {
-
struct timeval now;
-
struct timespec timeout;
-
-
pthread_kill(d->id,f->conf.intr_signal);
-
gettimeofday(&now,NULL);
-
timeout.tv_sec = now.tv_sec + 1;
-
timeout.tv_nsec = now.tv_usec * 1000;
-
pthread_cond_timeout(&d->cond,&f->lock,&timeout);
-
}
-
pthread_mutex_unlock(&f->lock);
-
}
现在查看一个interrupt流程如何产生及处理:
当操作被中断后,调用注册的中断处理函数do_interrupt,当然如果没有没有被中断,则添加到请求列表中
- static void do_interrupt(fuse_req_t req,fuse_ino_t nodeid,const void *inarg)
-
{
-
struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *)arg;
-
struct fuse_ll *f = req->f ;
-
//表明该变量下面不会再次被使用
-
(void) nodeid;
-
if(f->debug)
-
fprintf(stderr,”INTERRUPT:%llu\n”,
-
(unsigned long long) arg->unique);
-
req->u.i.unique = arg->unique;
-
-
pthread_mutex_lock(&f->lock);
-
/*
-
先在请求列表中查找该请求如果查找成功,标记该请求,调用回调函数,释放资源,返回
-
否则在中断列表中查找该请求,查找成功,返回
-
*/
-
if(find_interrupted(f,req))
-
//删除该请求
-
destroy_req(req);
-
else
-
//查找失败,将该请求添加到中断列表中,这种情况应该很少见?
-
//先出中断,再出请求,不过没关系,因为中断的请求nodeid是相同的
-
list_add_req(req,&f->interrupts);
-
pthread_mutex_unlock(&f->lock);
-
}
由于nodeid是相同的,所以在每次正常请求处理之前都会去检查该请求是否已经被注册到中断列表中:
- ….....
-
if(in->opcode != FUSE_INTERRUPT) {
-
struct fuse_req *intr;
-
pthread_mutex_lock(&f->lock);
-
/*
-
在interrupts列表中查找该中断请求,如果找到,则将该请求标记为中断,
-
并从中断列表中删除该请求,继续处理,不过在判断中断之前,已经被处理了
-
*/
-
intr = check_interrupt(f,req);
-
list_add_req(req,&f->list);
-
pthread_mutex_unlock(&f->lock);
-
if(intr)
-
fuse_reply_err(intr,EAGAIN);
-
}
-
fuse_ll_ops[in->opcode].func(req,in->nodeid,inarg);
-
….......
阅读(2439) | 评论(0) | 转发(1) |