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);