Linux信号驱动IO-SIGIO

Linux中的信号:由内核发送给应用程序在这里插入图片描述
处理方式:

忽略:
接收到信号后不做任何反应

捕获:
用自定义的信号处理函数来执行特定的动作(注册响应函数

默认:
接收到信号后按系统默认的行为处理该信号,如Ctrl+C。

捕获函数signal()

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);

给signum这个信号注册一个处理函数。

信号驱动IO工作过程

在这里插入图片描述

  1. 应用程序调用 sigaction或者signal(系统调用);内核在调用之后立刻返回一个结果,但是内核本身会阻塞等待数据;应用程序正常进行。两者是异步的
  2. 内核层收集(准备好)数据,给用户层递交一个SIGIO信号; 用户层触发信号处理程序,去执行处理函数,在处理函数中 使用系统调 用去内核读取数据。
  3. 用户层通过系统调用去内核中拷贝数据,该过程中用户层是阻塞的;直到拷贝结束内核通知任务完成。
  4. 简单来说就是用户层给内核一个任务,你去接受数据,等有数据了内核通知我,我再去去取数据。

Fasync方法

内核能够接受用户层的信号注册函数需要支持Fasync方法,于file_operations里定义

struct file_operations {
......
int (*fasync) (int, struct file *, int);
......
}

实际使用实例
在这里插入图片描述

fasync_helper(int fd, struct file * filp, int on, struct fasync_struct * * fapp);

struct fasync_struct {
	spinlock_t		fa_lock;
	int			magic;
	int			fa_fd;
	struct fasync_struct	*fa_next; /* singly linked list */
	struct file		*fa_file;
	struct rcu_head		fa_rcu;
};

fasync_helper:该函数负责启动fasync队列等,说白了就是初始化的必须
fasync_struct:它的作用就是储存内容的列表,在初始化和发出信号时候使用;函数会自动申请内存并赋值给hello_fasync,所以不需要对hello_fasync进行定义

实例使用

main

void func(int signo)
{
	printf("signo= %d\n",signo);
	read(fd,buff,sizeof(buff));
	printf("buff=%s\n",buff);
	return ;
}

main:
	int flage;
	fcntl(fd,F_SETOWN,getpid());
	flage=fcntl(fd,F_GETFL);
	fcntl(fd,F_SETFL,flage|FASYNC);
    signal(SIGIO,func);

1、一般默认情况下同步是不开的,需要通过fcntl设置fd的性质
2、给信号SIGIO注册处理函数。

驱动

static struct file_operations hello_ops = 
{
	.open = hello_open,
	.release = hello_release,
	.read = hello_read,
	.write = hello_write,
	.fasync = hello_fsync_func;
};
int hello_fsync_func (int fd, struct file *filep, int on)
{
	printk("hello_fsync_func()\n");
	return fasync_helper(fd, filep, int, on, &hello_fasync);
}

发生信号(由内核发出地)

 kill_fasync(struct fasync_struct * * fp, int sig, int band);

内核数据准备好后给用户层发信号
int sig:内核发送信号的是啥;int band:分为POLLIN/POLLOUT,表示可读可写

使用实例

驱动

static ssize_t hello_write (struct file *filep, const char __user *buf, size_t size, loff_t *pos)
{
	int error;
	if(size > KMAX_LEN)
	{
		size = KMAX_LEN;
	}
	memset(kbuf,0,sizeof(kbuf));
	if(copy_from_user(kbuf, buf, size))
	{
		error = -EFAULT;
		return error;
	}
	printk("%s\n",kbuf);

	// 当内核中有数据就可以给应用程序发送信号
	kill_fasync(&hello_fasync, SIGIO, POLLIN);
	return size;
}

kill_fasync负责给应用程序发送信号。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值