POXSIX提供了用于异步I/O的"aio_xxx"函数集。
名称 | 功能 |
---|---|
aio_read | 异步read |
aio_write | 异步write |
aio_fsync | 异步fsync |
aio_error | 获取错误状态 |
aio_return | 获取返回值 |
aio_cancel | 请求取消 |
aio_suspend | 请求等待 |
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char* argv[])
{
if (argc < 2) return 1;
struct aiocb cb;
const struct aiocb* cblist[1];
char buf[BUFSIZ];
int fd, n;
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
memset(&cb, 0, sizeof(struct aiocb));
cb.aio_fildes = fd;
cb.aio_buf = buf;
cb.aio_nbytes = BUFSIZ-1;
n = aio_read(&cb);
if (n < 0) {
perror("aio_read");
exit(EXIT_FAILURE);
}
cblist[0] = &cb;
n = aio_suspend(cblist, 1, NULL);
if (n != 0) {
perror("aio_read");
exit(EXIT_FAILURE);
}
n = aio_return(&cb);
if (n < 0) {
perror("aio_return");
exit(EXIT_FAILURE);
}
buf[n] = '\0';
printf("%s\n", buf);
return 0;
}
将aio_read, aio_suspend, aio_return 放在循环中时不能正确读取内容超过缓冲区大小的内容
在回调函数的调用上,有信号和线程两种方式,下面时使用线程进行回调的方式。
如果用SIGEV_THREAD设置回调函数并调用aio_read,从系统内部来看,实际上是用多个线程来实现异步IO。
#include
// #include
#include
#include
#include
#include
#include
#include
#include
#include
static void read_done(__sigval_t sigval)
{
struct aiocb *cb;
int n;
cb = (struct aiocb*)(sigval.sival_ptr);
if (aio_error(cb) == 0)
{
n = aio_return(cb);
if (n < 0)
{
perror("aio_return");
exit(EXIT_FAILURE);
}
printf("%d %d ---\n%.*s", n, cb->aio_nbytes, cb->aio_nbytes, cb->aio_buf);
exit(EXIT_SUCCESS);
}
return;
}
int main(int argc, char* argv[])
{
if (argc < 2) return 1;
struct aiocb cb;
char buf[BUFSIZ] = {'\0'};
int fd, n;
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
memset(&cb, 0, sizeof(struct aiocb));
cb.aio_fildes = fd;
cb.aio_buf = buf;
cb.aio_nbytes = BUFSIZ-1;
cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
cb.aio_sigevent.sigev_notify_function = &read_done;
cb.aio_sigevent.sigev_value.sival_ptr = &cb;
n = aio_read(&cb);
if (n < 0) {
perror("aio_read");
exit(EXIT_FAILURE);
}
select(0, NULL, NULL, NULL, NULL);
return 0;
}
#include
// #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static void read_done(__sigval_t sigval)
{
struct aiocb *cb;
int n;
cb = (struct aiocb*)(sigval.sival_ptr);
if (aio_error(cb) == 0)
{
n = aio_return(cb);
if (n < 0)
{
perror("aio_return");
exit(EXIT_FAILURE);
} else if (0 == n) {
printf("client %d gone\n", cb->aio_fildes);
aio_cancel(cb->aio_fildes, cb);
close(cb->aio_fildes);
free(cb);
return;
}
printf("client %d (%d)\n", cb->aio_fildes, n);
write(cb->aio_fildes, cb->aio_buf, n);
aio_read(cb);
}
else
{
printf("aio_error\n");
}
return;
}
static void register_read(int fd)
{
struct aiocb *cb;
char* buf;
printf("client register %d\n", fd);
cb = malloc(sizeof(struct aiocb));
buf = malloc(BUFSIZ);
memset(cb, 0, sizeof(struct aiocb));
cb->aio_fildes = fd;
cb->aio_buf = buf;
cb->aio_nbytes = BUFSIZ;
cb->aio_sigevent.sigev_notify = SIGEV_THREAD;
cb->aio_sigevent.sigev_notify_function = read_done;
cb->aio_sigevent.sigev_value.__sival_ptr = cb;//
if (aio_read(cb) != 0)
{
perror("aio_read");
return;
}
}
int main(int argc, char* argv[])
{
if (argc < 2) return 1;
struct sockaddr_in addr;
int s = socket(PF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(9999);
if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
perror("bind");
exit(EXIT_FAILURE);
}
listen(s, 5);
for (;;)
{
int c = accept(s, NULL, 0);
if (c < 0) continue;
register_read(c);
}
return 0;
}