Skip site navigation (1)Skip section navigation (2)
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>