io_setup中的nr_events与io_submit和io_getevents中的nr有什么关系?
What is the relationship between nr_events in io_setup and nr in io_submit and io_getevents?
#include <linux/aio_abi.h> /* Defines needed types */
int io_setup(unsigned nr_events, io_context_t *ctx_idp);
int io_submit(io_context_t ctx_id, long nr, struct iocb **iocbpp);
int io_getevents(io_context_t ctx_id, long min_nr, long nr,
struct io_event *events, struct timespec *timeout);
问题 1:
如果我使用io_setup(32, ctx_idp)
,我可以提交100次吗?还是只能提交32次,先用io_getevents处理数据,再提交?
io_submit(ctx_id, 100, iocbpp);
或
for(I = 0; I<100; I++) {
io_submit(ctx_id, 1, iocbpp);
}
问题 2:
io_getevents中的long min_nr, long nr
是由io_setup中的nr_events决定的吗?
1 <= min_nr <= 32 and 1 <= nr <= 32?
还是由io_submit中的nr
决定?所以
1 <= min_nr <= 100 and 1 <= nr <= 100?
问题 1 的答案:
是的,您可以创建一个上下文来处理 32 个 并发 请求,其中 io_setup
和 运行 io_submit
处理 100 个类似于以下内容的请求io_submit(ctx_id, 100, iocbpp);
。我已经在 CentOS 7 上成功测试了这个(没有 libaio
使用来自 here 的改编代码)。
问题 2 的答案:
io_getevents
参数与io_submit
提交的请求数有关(我也成功测试过)。
这是我用过的代码。
它需要 2 个参数,并允许写入单个文件,但偏移量不同,您可以检查 io_submit
正在写入什么。
/*
* taio.c
*
* test AIO on Linux
*
* taio <number of operations for io_setup> <number of control blocks for io_submit>
*
*
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <linux/aio_abi.h>
inline int io_setup(unsigned nr, aio_context_t *ctxp) {
return syscall(__NR_io_setup, nr, ctxp);
}
inline int io_destroy(aio_context_t ctx) {
return syscall(__NR_io_destroy, ctx);
}
inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) {
return syscall(__NR_io_submit, ctx, nr, iocbpp);
}
inline int io_getevents(aio_context_t ctx, long min_nr, long max_nr,
struct io_event *events, struct timespec *timeout) {
return syscall(__NR_io_getevents, ctx, min_nr, max_nr, events, timeout);
}
/*
* size must match
*/
#define IO_SIZE 10
int main(int argc, char *argv[]) {
aio_context_t ctx;
struct iocb *tcb;
struct iocb **lcb;
char *data;
char **tdata;
struct io_event *events;
int ret;
int fd;
int i,j;
long int nr_iosetup;
long int nr_iosubmit;
int current_offset;
if (argc != 1 && argc != 3)
{
printf("taio: usage <number of operations for io_setup> <number of control blocks for io_submit>");
return 1;
}
nr_iosetup = 1;
nr_iosubmit = 1;
for(i=0; i < argc; i++)
{
if (i == 1)
nr_iosetup = atoi(argv[1]);
if (i == 2)
nr_iosubmit = atoi(argv[2]);
}
tdata = malloc(nr_iosubmit * sizeof(char *));
if (tdata == NULL)
{
perror("malloc tdata");
return 1;
}
tcb = malloc(nr_iosubmit * sizeof(struct iocb));
if (tcb == NULL)
{
perror("malloc tcb");
return 1;
}
lcb = malloc(nr_iosubmit * sizeof(struct iocb *));
if (lcb == NULL)
{
perror("malloc lcb");
return 1;
}
for (j=0; j < nr_iosubmit; j++)
{
data = malloc(IO_SIZE);
if (data == NULL)
{
perror("malloc data");
return 1;
}
tdata[j] = data;
sprintf(data, "%d\n", j);
}
events = malloc(nr_iosubmit * sizeof(struct io_event));
if (events == NULL)
{
perror("malloc events");
return 1;
}
ret = unlink("/tmp/taio.dat");
/* ignore error */
fd = open("/tmp/taio.dat", O_RDWR | O_CREAT | O_EXCL, S_IRWXU);
if (fd < 0) {
perror("open");
return -1;
}
printf("open\t\t=> fd=%d\n", fd);
ctx = (aio_context_t)0;
ret = io_setup(nr_iosetup, &ctx);
if (ret < 0) {
perror("io_setup");
return -1;
}
printf("io_setup\t=> nr_iosetup=%ld ret=%d\n", nr_iosetup, ret);
/* command-specific options */
for (j=0, current_offset=0; j < nr_iosubmit; j++)
{
/* setup I/O control block */
memset(&tcb[j], 0, sizeof(struct iocb));
tcb[j].aio_fildes = fd;
tcb[j].aio_lio_opcode = IOCB_CMD_PWRITE;
tcb[j].aio_buf = (uint64_t)tdata[j];
tcb[j].aio_offset = current_offset;
tcb[j].aio_nbytes = IO_SIZE;
lcb[j] = &tcb[j];
current_offset += IO_SIZE;
}
ret = io_submit(ctx, nr_iosubmit, lcb);
if (ret < 0)
{
perror("io_submit");
return 1;
}
printf("io_submit\t=> nr_iosubmit=%ld ret=%d\n", nr_iosubmit, ret);
ret = io_getevents(ctx, nr_iosubmit, nr_iosubmit, events, NULL);
printf("io_getevents\t=> ret=%d\n", ret);
ret = io_destroy(ctx);
if (ret < 0) {
perror("io_destroy");
return -1;
}
printf("io_destroy\t=> ret=%d\n", ret);
return 0;
}
执行:
./taio 32 100
open => fd=3
io_setup => nr_iosetup=32 ret=0
io_submit => nr_iosubmit=100 ret=100
io_getevents => ret=100
io_destroy => ret=0
#include <linux/aio_abi.h> /* Defines needed types */
int io_setup(unsigned nr_events, io_context_t *ctx_idp);
int io_submit(io_context_t ctx_id, long nr, struct iocb **iocbpp);
int io_getevents(io_context_t ctx_id, long min_nr, long nr,
struct io_event *events, struct timespec *timeout);
问题 1:
如果我使用io_setup(32, ctx_idp)
,我可以提交100次吗?还是只能提交32次,先用io_getevents处理数据,再提交?
io_submit(ctx_id, 100, iocbpp);
或
for(I = 0; I<100; I++) {
io_submit(ctx_id, 1, iocbpp);
}
问题 2:
io_getevents中的long min_nr, long nr
是由io_setup中的nr_events决定的吗?
1 <= min_nr <= 32 and 1 <= nr <= 32?
还是由io_submit中的nr
决定?所以
1 <= min_nr <= 100 and 1 <= nr <= 100?
问题 1 的答案:
是的,您可以创建一个上下文来处理 32 个 并发 请求,其中 io_setup
和 运行 io_submit
处理 100 个类似于以下内容的请求io_submit(ctx_id, 100, iocbpp);
。我已经在 CentOS 7 上成功测试了这个(没有 libaio
使用来自 here 的改编代码)。
问题 2 的答案:
io_getevents
参数与io_submit
提交的请求数有关(我也成功测试过)。
这是我用过的代码。
它需要 2 个参数,并允许写入单个文件,但偏移量不同,您可以检查 io_submit
正在写入什么。
/*
* taio.c
*
* test AIO on Linux
*
* taio <number of operations for io_setup> <number of control blocks for io_submit>
*
*
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <linux/aio_abi.h>
inline int io_setup(unsigned nr, aio_context_t *ctxp) {
return syscall(__NR_io_setup, nr, ctxp);
}
inline int io_destroy(aio_context_t ctx) {
return syscall(__NR_io_destroy, ctx);
}
inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) {
return syscall(__NR_io_submit, ctx, nr, iocbpp);
}
inline int io_getevents(aio_context_t ctx, long min_nr, long max_nr,
struct io_event *events, struct timespec *timeout) {
return syscall(__NR_io_getevents, ctx, min_nr, max_nr, events, timeout);
}
/*
* size must match
*/
#define IO_SIZE 10
int main(int argc, char *argv[]) {
aio_context_t ctx;
struct iocb *tcb;
struct iocb **lcb;
char *data;
char **tdata;
struct io_event *events;
int ret;
int fd;
int i,j;
long int nr_iosetup;
long int nr_iosubmit;
int current_offset;
if (argc != 1 && argc != 3)
{
printf("taio: usage <number of operations for io_setup> <number of control blocks for io_submit>");
return 1;
}
nr_iosetup = 1;
nr_iosubmit = 1;
for(i=0; i < argc; i++)
{
if (i == 1)
nr_iosetup = atoi(argv[1]);
if (i == 2)
nr_iosubmit = atoi(argv[2]);
}
tdata = malloc(nr_iosubmit * sizeof(char *));
if (tdata == NULL)
{
perror("malloc tdata");
return 1;
}
tcb = malloc(nr_iosubmit * sizeof(struct iocb));
if (tcb == NULL)
{
perror("malloc tcb");
return 1;
}
lcb = malloc(nr_iosubmit * sizeof(struct iocb *));
if (lcb == NULL)
{
perror("malloc lcb");
return 1;
}
for (j=0; j < nr_iosubmit; j++)
{
data = malloc(IO_SIZE);
if (data == NULL)
{
perror("malloc data");
return 1;
}
tdata[j] = data;
sprintf(data, "%d\n", j);
}
events = malloc(nr_iosubmit * sizeof(struct io_event));
if (events == NULL)
{
perror("malloc events");
return 1;
}
ret = unlink("/tmp/taio.dat");
/* ignore error */
fd = open("/tmp/taio.dat", O_RDWR | O_CREAT | O_EXCL, S_IRWXU);
if (fd < 0) {
perror("open");
return -1;
}
printf("open\t\t=> fd=%d\n", fd);
ctx = (aio_context_t)0;
ret = io_setup(nr_iosetup, &ctx);
if (ret < 0) {
perror("io_setup");
return -1;
}
printf("io_setup\t=> nr_iosetup=%ld ret=%d\n", nr_iosetup, ret);
/* command-specific options */
for (j=0, current_offset=0; j < nr_iosubmit; j++)
{
/* setup I/O control block */
memset(&tcb[j], 0, sizeof(struct iocb));
tcb[j].aio_fildes = fd;
tcb[j].aio_lio_opcode = IOCB_CMD_PWRITE;
tcb[j].aio_buf = (uint64_t)tdata[j];
tcb[j].aio_offset = current_offset;
tcb[j].aio_nbytes = IO_SIZE;
lcb[j] = &tcb[j];
current_offset += IO_SIZE;
}
ret = io_submit(ctx, nr_iosubmit, lcb);
if (ret < 0)
{
perror("io_submit");
return 1;
}
printf("io_submit\t=> nr_iosubmit=%ld ret=%d\n", nr_iosubmit, ret);
ret = io_getevents(ctx, nr_iosubmit, nr_iosubmit, events, NULL);
printf("io_getevents\t=> ret=%d\n", ret);
ret = io_destroy(ctx);
if (ret < 0) {
perror("io_destroy");
return -1;
}
printf("io_destroy\t=> ret=%d\n", ret);
return 0;
}
执行:
./taio 32 100
open => fd=3
io_setup => nr_iosetup=32 ret=0
io_submit => nr_iosubmit=100 ret=100
io_getevents => ret=100
io_destroy => ret=0