From owner-freebsd-questions Fri Apr 20 2:43:52 2001 Delivered-To: freebsd-questions@freebsd.org Received: from web4307.mail.yahoo.com (web4307.mail.yahoo.com [216.115.104.199]) by hub.freebsd.org (Postfix) with SMTP id 25C4237B422 for ; Fri, 20 Apr 2001 02:43:35 -0700 (PDT) (envelope-from zhang210@yahoo.com.cn) Message-ID: <20010420094335.18802.qmail@web4307.mail.yahoo.com> Received: from [192.11.226.119] by web4307.mail.yahoo.com; Fri, 20 Apr 2001 17:43:35 CST Date: Fri, 20 Apr 2001 17:43:35 +0800 (CST) From: =?gb2312?q?lei=20zhang?= Subject: help: aio_* + kevent to implement no-blocking io To: freebsd-questions@FreeBSD.ORG Cc: terry@lambert.org MIME-Version: 1.0 Content-Type: text/plain; charset=gb2312 Content-Transfer-Encoding: 8bit Sender: owner-freebsd-questions@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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