Date: Fri, 20 Apr 2001 17:43:35 +0800 (CST) From: =?gb2312?q?lei=20zhang?= <zhang210@yahoo.com.cn> To: freebsd-questions@FreeBSD.ORG Cc: terry@lambert.org Subject: help: aio_* + kevent to implement no-blocking io Message-ID: <20010420094335.18802.qmail@web4307.mail.yahoo.com>
next in thread | raw e-mail | index | archive | help
Hi,
I want to implement a no-blocking IO and using
aio*+kevent to read/write for disk.
I have try more, but I can't do it.
my freebsd is 4.1, and the code is :
#include <aio.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <sys/queue.h>
#include <sys/event.h>
#define DISKSIZE 8000
/* the blocksize to test with in Kbytes */
#define BLOCKSIZE 15
/* the number of blocks to read for testing
* NOTE: for testing use_lio NRBLOCKS should be 16 or
less */
#define NRBLOCKS 20
/* no editing below here */
#define MAXBLOCKS ((DISKSIZE << 10) / BLOCKSIZE)
//#define BUFSIZE (BLOCKSIZE << 10)
#define BUFSIZE (BLOCKSIZE *1024 )
#define KQ_EVENT_MAX 1024
struct kevent kq_event[KQ_EVENT_MAX]; /* kqueue event
holder */
/* some macros for timing (user/system/elapsed) */
struct rusage ru_start, ru_end;
struct timeval utime, stime, ttime, start, end, etime;
struct aiocb iocb[NRBLOCKS];
int kq_handle;
struct timespec timeout;
#define START \
do { \
gettimeofday(&start, NULL); \
getrusage(RUSAGE_SELF, &ru_start); \
} while (0)
#define STOP(type) \
do { \
getrusage(RUSAGE_SELF, &ru_end); \
gettimeofday(&end, NULL); \
timersub(&ru_end.ru_utime, &ru_start.ru_utime,
&utime); \
timersub(&ru_end.ru_stime, &ru_start.ru_stime,
&stime); \
timeradd(&utime, &stime, &ttime); \
timersub(&end, &start, &etime); \
printf("%-10s: %2ld.%06ld %2ld.%06ld %2ld.%06ld
%2ld.%06ld %6.2f kbps\n", \
type, \
utime.tv_sec, utime.tv_usec, \
stime.tv_sec, stime.tv_usec, \
ttime.tv_sec, ttime.tv_usec, \
etime.tv_sec, etime.tv_usec, \
(float) NRBLOCKS*15 / (etime.tv_sec +
etime.tv_usec / 1E6)); \
} while (0)
/* array to store which blocks to read */
int blocks[NRBLOCKS];
void use_read(int);
void use_pread(int);
void use_aio(int);
void use_lio(int);
void kq_fd_set(int fd, short filter, u_short flags);
int kq_proc(struct timespec *tout);
int
main (int argc, char *argv[]) {
int fd, i,n ;
kq_handle = kqueue();
/* open the raw disk device */
if ((fd = open(argv[1], O_RDONLY)) == -1) {
err(1, "%s", argv[1]);
}
/* create array of blocks to read */
srandom(1);
for (i = 0; i < NRBLOCKS; i++) {
blocks[i] = random() % MAXBLOCKS;
}
printf("\n Testing: %s\n", argv[1]);
printf("Types : User Time Sys Time U+S
time Elapsed Blocks(KB/s)\n");
/* use aio */
START;
timeout.tv_sec = 0;
timeout.tv_nsec = 2500;
printf("start");
use_aio(fd);
for(;;) {
n = kq_proc(NULL);
printf("n= %d \n",n);
if ( n<1)
break;
}
STOP("aio");
close(fd);
return 0;
}
void
use_aio (int fd) {
struct aiocb iocb[NRBLOCKS];
int i, res, n;
printf("do aio");
for (i = 0; i < NRBLOCKS; i++) {
bzero(&iocb[i], sizeof(struct aiocb)); /* !!! */
kq_event[i].ident = kq_handle;
//kq_event[i].udata = &iocb[i] ;
kq_event[i].filter = EVFILT_AIO; /* EVFILT_READ or
EVFILT_WRITE */
//kq_event[i].flags = EV_ADD | EV_ENABLE; /*
EV_ADD or EV_DELETE */
iocb[i].aio_fildes = fd;
iocb[i].aio_offset = (off_t) blocks[i] * BUFSIZE;
iocb[i].aio_buf = malloc(BUFSIZE);
iocb[i].aio_nbytes = BUFSIZE;
iocb[i].aio_lio_opcode = &kq_event[i];
if ((res = aio_read(&iocb[i])) == -1)
printf("error: aio_read");
printf(" kq = %d &iocb= %x \n", kq_event[i].ident,
&iocb[i]);
n = kq_proc(&timeout);
printf("n= %d \n",n);
if (n < 0) {
if (errno == EINTR || errno == EINPROGRESS)
continue; /* interrupted by timer? */
}
}
}
/*-------------------------------------------------------------------------
* kq_fd_set - add or delete a kquque event
*-------------------------------------------------------------------------
*/
void kq_fd_set(int fd, short filter, u_short flags)
{
struct kevent *ke,kqe;
ke = &kqe;
ke->ident = fd;
ke->filter = filter; /* EVFILT_READ or
EVFILT_WRITE */
ke->flags = flags; /* EV_ADD or EV_DELETE */
ke->fflags = 0;
ke->data = 0;
/*
* add, modify, or delete kqueue events
*/
if (kevent(kq_handle, ke, 1, NULL, 0, NULL) < 0) {
printf("kq_fd_set: kevent() call error ");
return;
}
}
/*-------------------------------------------------------------------------
* kq_proc - process ready events (or timeout)
* Return: the number of ready events
*-------------------------------------------------------------------------
*/
int kq_proc(struct timespec *tout)
{
int i, fd, nready;
struct kevent *ke;
u_short flags;
short filter;
struct aiocb *iocb;
nready = kevent(kq_handle, NULL, 0, kq_event,
KQ_EVENT_MAX, tout);
if (nready < 0) {
return -1; /* error */
}
if (nready == 0) { /* timeout */
return (0);
}
for (i = 0; i < nready; i++) {
ke = &kq_event[i];
fd = ke->ident;
flags = ke->flags;
filter = ke->filter;
printf(" ident = %x udata = %x ",kq_event[i].ident,
ke->udata );
if (flags & EV_ERROR) {
continue;
}
//iocb = ke->udata;
//if (aio_return(fd) < 0)
// err(1, "aio_return");
kq_fd_set(fd, EVFILT_AIO, EV_DELETE);
}
return(nready);
}
Use this program, I only can get last 4 read result.
I know it might have some problem in aio + kevent.
but I don't know the correct method
Please help me.
_________________________________________________________
Do You Yahoo!? 登录免费雅虎电邮! http://mail.yahoo.com.cn
创建雅虎俱乐部,真我个性尽施展!http://cn.clubs.yahoo.com
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010420094335.18802.qmail>
