问题:编一个小程序实现:主循环在调用sleep(),当用户通过键盘输入一个特定的字符时主循环退出,用信号SIGIO来实现。
先了解SIGIO信号:它是一个异步I/O信号,这个信号可以发送给已经注册了该信号的进程,即当某一进程有一个I/O口(一般就是对于文件描述符),如果对这个I/O口有I/O操作,就会发送SIGIO信号给该进程,进程就可根据信号进行自己的操作。
注册信号的步骤:
s1. 对文件描述符调用fcntl函数,设置O_NONBLOCK和O_ASYNC(只能对终端和网络的文件描述符使用)属性;
fcntl(fd, F_SETFL, old | O_NONBLOCK | O_ASYNC)
s2. 对文件描述符设置SIGIO、SIGURG信号所通知的进程,一般是调用进程本身;
fcntl(fd, F_SETOWN, getpid())
s3. 编写signal handler函数,并使用signal或sigaction函数注册。
所以我们就可以很快的写出代码:
#include <curses.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int done ;
main()
{
void actfun(int);
done = 1;
struct sigaction sig_act;
int fl = 0;
fflush(stdin);
fflush(stdout);
fl = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, fl | O_NONBLOCK | O_ASYNC );
fcntl(STDIN_FILENO, F_SETOWN, getpid());
sigemptyset(&sig_act.sa_mask);
sig_act.sa_flags = 0;
sig_act.sa_handler = actfun;
sigaction(SIGIO, &sig_act, NULL);
while(done){
sleep(1);
if(done == 0)
break;
}
}
void actfun(int signum)
{
char buf[10];
read(0,buf,10);
if(strncmp(buf,"q",1) == 0)
{
done = 0;
}
}
在这里我们也可以用aio_read来实现
int aio_read( struct aiocb *aiocbp );
struct aiocb结构体
struct aiocb {
int aio_fildes; // File Descriptor
int aio_lio_opcode; // Valid only for lio_listio (r/w/nop)
volatile void *aio_buf; // Data Buffer
size_t aio_nbytes; // Number of Bytes in Data Buffer
struct sigevent aio_sigevent; // Notification Structure
off_t aio_offset;
};
aio_fildes 字段表示被打开用来读或者写的文件描述符,读或写操作从aio_offset指定的偏移量开始。读操作会复制到aio_buf,写操作会从aio_buf复制出来。aio_nbytes表示要读或者写的字节数。
其中aio_sigevent字段可以控制在I/O事件完成之后,如何通知应用程序。更详细的查阅资料
用aio_read()代码如下:
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <aio.h>
void setup_aio_buffer();
struct aiocb kbcbuf;
main()
{
setup_aio_buffer(); /* initialize aio ctrl buff */
aio_read(&kbcbuf); /* place a read request */
while(done){
if(done == 0)
break;
}
}
void actfun(int signum)
{
char buf[10];
read(0,buf,10);
if(strncmp(kbcbuf.aio_buf,"q",1) == 0)
{
done = 0;
printf("22222222222222 ");
}
aio_read(&kbcbuf); /* place a read request */
}
void setup_aio_buffer()
{
static char input[1]; /* 1 char of input */
/* describe what to read */
kbcbuf.aio_fildes = 0; /* standard intput */
kbcbuf.aio_buf = input; /* buffer */
kbcbuf.aio_nbytes = 1; /* number to read */
kbcbuf.aio_offset = 0; /* offset in file */
/* describe what to do when read is ready */
kbcbuf.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
kbcbuf.aio_sigevent.sigev_signo = SIGIO; /* send sIGIO */
}