Demo1,使用aio_suspend轮循IO状态
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <aio.h>
int main(int argc, char *argv[])
{
int fd, ret;
struct aiocb cb = {};
const struct aiocb *cbs[1] = {};
if (argc < 2)
{
printf("Usage: %s <file>\n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open()");
return 1;
}
cb.aio_fildes = fd;
cb.aio_lio_opcode = LIO_READ;
cb.aio_buf = malloc(10241);
cb.aio_nbytes = 10240;
aio_read(&cb);
cbs[0] = &cb;
while (1)
{
ret = aio_suspend(cbs, 1, NULL);
if (ret == -1)
{
if (errno == EAGAIN)
{
continue;
}
else
{
perror("aio_suspend()");
break;
}
}
break;
}
if (aio_error(cbs[0]))
{
perror("aio_error()");
}
else
{
printf("%s", (char *)cbs[0]->aio_buf);
}
free((void *)cbs[0]->aio_buf);
close(fd);
return 0;
}
Dem2,使用信号回调函数获得IO完成事件
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <aio.h>
#include <signal.h>
void sig_handle_func(int signo, siginfo_t *info, void *context)
{
struct aiocb *cbp;
cbp = (struct aiocb *)info->si_ptr;
if (aio_error(cbp))
{
perror("aio_error()");
}
else
{
printf("%s", (char *)cbp->aio_buf);
}
}
int main(int argc, char *argv[])
{
int fd, ret;
struct aiocb cb = {};
struct sigaction act = {};
sigset_t set;
if (argc < 2)
{
printf("Usage: %s <file>\n", argv[0]);
return 1;
}
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = sig_handle_func;
sigaction(SIGIO, &act, NULL);
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open()");
return 1;
}
cb.aio_fildes = fd;
cb.aio_lio_opcode = LIO_READ;
cb.aio_buf = malloc(10241);
cb.aio_nbytes = 10240;
cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
cb.aio_sigevent.sigev_signo = SIGIO;
cb.aio_sigevent.sigev_value.sival_ptr = (void *)&cb;
aio_read(&cb);
sleep(3);
free((void *)cb.aio_buf);
close(fd);
return 0;
}
Demo3,使用信号等待函数等待IO完成信号
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <aio.h>
#include <signal.h>
int main(int argc, char *argv[])
{
int fd, ret;
struct aiocb cb = {};
struct sigaction act = {};
sigset_t set;
if (argc < 2)
{
printf("Usage: %s <file>\n", argv[0]);
return 1;
}
sigemptyset(&set);
sigaddset(&set, SIGIO);
sigprocmask(SIG_BLOCK, &set, NULL);
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open()");
return 1;
}
cb.aio_fildes = fd;
cb.aio_lio_opcode = LIO_READ;
cb.aio_buf = malloc(10241);
cb.aio_nbytes = 10240;
cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
cb.aio_sigevent.sigev_signo = SIGIO;
cb.aio_sigevent.sigev_value.sival_ptr = (void *)&cb;
aio_read(&cb);
sigwaitinfo(&set, NULL);
if (aio_error(&cb))
{
perror("aio_error()");
}
else
{
printf("%s", (char *)cb.aio_buf);
}
free((void *)cb.aio_buf);
close(fd);
return 0;
}
Demo4,通过新线程通知IO完成事件
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <aio.h>
#include <pthread.h>
void notify_func(sigval_t sv)
{
struct aiocb *cbp;
cbp = (struct aiocb *)sv.sival_ptr;
if (aio_error(cbp))
{
perror("aio_error()");
}
else
{
printf("%s", (char *)cbp->aio_buf);
}
}
int main(int argc, char *argv[])
{
int fd, ret;
struct aiocb cb = {};
if (argc < 2)
{
printf("Usage: %s <file>\n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open()");
return 1;
}
cb.aio_fildes = fd;
cb.aio_lio_opcode = LIO_READ;
cb.aio_buf = malloc(10241);
cb.aio_nbytes = 10240;
cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
cb.aio_sigevent.sigev_value.sival_ptr = (void *)&cb;
cb.aio_sigevent.sigev_notify_function = notify_func;
cb.aio_sigevent.sigev_notify_attributes = NULL;
aio_read(&cb);
sleep(3);
free((void *)cb.aio_buf);
close(fd);
return 0;
}
Demo5,使用指定线程等待IO完成信号(目前不支持)
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <aio.h>
#include <pthread.h>
pid_t thread_tid;
pid_t gettid()
{
return syscall(SYS_gettid);
}
void *thread_main(void *data)
{
siginfo_t info = {};
struct aiocb *cbp;
thread_tid = gettid();
sigwaitinfo((sigset_t *)data, &info);
cbp = (struct aiocb *)info.si_ptr;
if (aio_error(cbp))
{
perror("aio_error()");
}
else
{
printf("%s", (char *)cbp->aio_buf);
}
return 0;
}
int main(int argc, char *argv[])
{
sigset_t set;
pthread_attr_t attr;
pthread_t thread_id;
long thread_ret;
int fd, ret;
struct aiocb cb = {};
if (argc < 2)
{
printf("Usage: %s <file>\n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open()");
return 1;
}
sigemptyset(&set);
sigaddset(&set, SIGIO);
pthread_sigmask(SIG_BLOCK, &set, NULL);
pthread_attr_init(&attr);
pthread_create(&thread_id, &attr, thread_main, (void *)&set);
sleep(1);
cb.aio_fildes = fd;
cb.aio_lio_opcode = LIO_READ;
cb.aio_buf = malloc(10241);
cb.aio_nbytes = 10240;
cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID;
cb.aio_sigevent.sigev_signo = SIGIO;
cb.aio_sigevent.sigev_value.sival_ptr = (void *)&cb;
cb.aio_sigevent._sigev_un._tid = thread_tid;
aio_read(&cb);
pthread_join(thread_id, (void **)&thread_ret);
pthread_attr_destroy(&attr);
free((void *)cb.aio_buf);
close(fd);
return 0;
}
编译时需要添加库:rt, pthread
1, 发起AIO之后,可以使用 aio_suspend() 阻塞当前线程直到有IO完成;
2, 也可以使用信号通知,设置 struct aiocb 的 aio_sigevent.sigev_notify 为 SIGEV_SIGNAL;
3, 还可以使用新线程通知,设置 struct aiocb 的 aio_sigevent.sigev_notify 为 SIGEV_THREAD;
4, 未来还可能支持使用固定线程接收信号,设置 struct aiocb 的 aio_sigevent.sigev_notify 为 SIGEV_THREAD_ID (目前不可用,官方解释这个选项目前仅用于定时器)。