信号驱动I/O详解

1、Linux中的信号

1.1、查看信号

[centos6-jk128:latest ~]$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

(1)使用"kill -l"查看linux中的全部信号,信号又分为可靠信号和不可靠信号,每个信号更详细的介绍自行查询;
(2)信号驱动I/O中使用的SIGIO信号;

1.2、信号处理方式

(1)忽略:接收到信号后不做任何反应;
(2)捕获:用自定义的信号处理函数来执行相应信号;不是所有信号都可以捕获的,关闭进程的信号就不能捕获;
(3)默认:按系统默认的信号处理方式响应信号,不去显示的指定信号处理方式,就是按默认的方式;

1.3、信号注册

	sighandler_t signal(int signum, sighandler_t handler)

(1)signum:要捕获的信号;
(2)handler:当进程接收到信号时绑定的处理函数;

2、信号驱动I/O

2.1、信号驱动I/O的原理

(1)应用层打开文件并设置好文件的相关标志位;
(2)绑定SIGIO信号处理函数,在信号处理函数中读/写文件;
(3)当驱动中有可读数据时,向相应进程发送SIGIO信号;
(4)进程接收到SIGIO信号后,运行绑定的信号处理函数;
总结:应用层打开文件并绑定信号处理函数,进程并不会阻塞,只有在接收到SIGIO信号时才去执行信号处理函数,属于异步通知;

2.2、应用层实现信号驱动I/O

void func(int signo)
{
	读文件的操作;
}

fd = open("/dev/hellodev",O_RDWR);

fcntl(fd,F_SETOWN,getpid());

flage=fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,flage|FASYNC);

   signal(SIGIO,func);

(1)应用层打开文件得到文件描述符,设置文件的属主进程,属主进程的进程ID号被保存代struct file filep->fowner中,将来内核才知道应该给
哪个进程发SIGIO信号;
(2)设置文件的FASYNC标志,通过fcntl的F_SETFL命令实现,也就是调用文件的file_operations结构体的fasync方法;
(3)绑定进程的SIGIO信号的响应函数;
总结:执行完上面的步骤,当文件在新数据到达时向进程发送一个SIGIO信号,进程就去读文件;

2.3、驱动层使用信号驱动I/O

//这是fasync_helper()函数和kill_fasync()函数需要用到的,照着写就行
struct fasync_struct *hello_fasync;

static struct file_operations hello_ops = 
{
	.open = hello_open,
	.release = hello_release,
	.read = hello_read,
	.write = hello_write,
	.fasync = hello_fasync_func,
};

int hello_fasync_func (int fd, struct file *filep, int on)
{
	printk("hello_fasync_func()\n");
	return fasync_helper(fd, filep, on, &hello_fasync);
}

static ssize_t hello_write (struct file *filep, const char __user *buf, size_t size, loff_t *pos)
{
	······
	kill_fasync(&hello_fasync, SIGIO, POLLIN); //给注册的进程发送SIGIO信号
	······
return size;
}

(1)F_SETOWN被调用时对file->f_owner赋值,此外什么也不做;
(2)在执行F_SETFL启动FASYNC时,调用驱动程序的fasync方法,上面的代码中就是执行hello_fasync_func()函数;
(3)当数据到达时,也就是有其他的进程调用驱动的write函数写数据时,向注册为异步通知的进程发送SIGIO信号;
(4)hello_fasync:这是fasync_helper()函数和kill_fasync()函数需要用到的信息,照着格式写就行;
(5)POLLIN:表示文件数据可读;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值