您的位置:首页 > 其它

字符设备驱动之笔记-异步通知(fasync)

2016-01-08 11:44 489 查看
 发信号:

1. 谁发

2. 发给谁

3. 发什么

4. 怎么发

5. 收到信号后做什么

16th_signal_app

发信号:

1. 谁发    a

2. 发给谁  b

3. 发什么  SIGIO

4. 怎么发  int kill(pid_t pid, int sig);

5. 收到信号后做什么: sighandler_t signal(int signum, sighandler_t handler);

驱动和应用

发信号:

1. 谁发    按键中断服务程序

2. 发给谁  使用按键的应用程序

3. 发什么  SIGIO

4. 怎么发  kill_fasync(谁, SIGIO)

5. 收到信号后做什么: sighandler_t signal(int signum, sighandler_t handler);

怎么写驱动?

1. 定义一个fasync_struct指针:

struct fasync_struct *buttons_async;

2. 设置它:

static int buttons_fasync(int fd, struct file *filp, int on)

{

 int retval;

 retval = fasync_helper(fd, filp, on, &buttons_async);

 if (retval < 0)

  return retval;

 return 0;

}

static const struct file_operations buttons_fops = {

    ......

 .fasync  = buttons_fasync,

};

3. 使用它:

kill_fasync(&buttons_async, SIGIO, POLL_IN);

 

怎么写应用?

1. 注册信号处理函数

signal(SIGNO, signal_function);

2. 执行某些函数, 使得驱动里的fasync被调用

 flag = fcntl(fd, F_GETFL);

 flag |= FASYNC;

 fcntl(fd, F_SETFL, flag);

 

3. 把应用程序的PID告诉驱动:

 fcntl(fd, F_SETOWN, getpid());

应用调用到驱动里的fasync:

1.

app:    flag = fcntl(fd, F_GETFL);

--------------------------------------------------------

kernel:  sys_fcntl

             do_fcntl

                 err = filp->f_flags;

                 return err;

2.

app:    fcntl(fd, F_SETFL, flag);

--------------------------------------------------------

kernel:  sys_fcntl

             do_fcntl

    err = setfl(fd, filp, arg);

       // 要改变file->f_flasgs的FASYNC时

       // 调用驱动的fasync

       if ((arg ^ filp->f_flags) & FASYNC) {

        if (filp->f_op && filp->f_op->fasync) {

         error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);

         if (error < 0)

          goto out;

        }

3.

app:    fcntl(fd, F_SETOWN, getpid());

-----------------------------------------------------

kernel: sys_fcntl

   do_fcntl

    err = f_setown(filp, arg, 1);

        result = __f_setown(filp, pid, type, force);

4.

kill_fasync(&buttons_async, SIGIO, POLL_IN);

 __kill_fasync(*fp, sig, band);

    fown = &fa->fa_file->f_owner;

    send_sigio(fown, fa->fa_fd, band);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: