NAME

io_submit - 비동기 I/O 처리 요청 제출하기

SYNOPSIS

#include <linux/aio_abi.h>          /* 필요한 타입 정의 */

int io_submit(aio_context_t ctx_id, long nr, struct iocb **iocbpp);

주의: 이 시스템 호출에 대한 glibc 래퍼가 없다. NOTES 참고.

DESCRIPTION

주의: 이 페이지에선 리눅스 시스템 호출 인터페이스를 설명한다. libaio에서 제공하는 래퍼 함수에서는 ctx_id 인자에 다른 타입을 쓴다. NOTES 참고.

io_submit() 시스템 호출은 AIO 문맥 ctx_id에서 처리 큐에 nr 개 I/O 요청 블록을 넣는다. iocbpp 인자는 nr 개 AIO 제어 블록의 배열이어야 하며 이를 문맥 ctx_id로 제출하게 된다.

linux/aio_abi.h에 정의돼 있는 iocb(I/O 제어 블록) 구조체에 I/O 동작을 제어하는 매개변수들이 있다.

#define <linux/aio_abi.h>

struct iocb {
    __u64   aio_data;
    __u32   PADDED(aio_key, aio_rw_flags);
    __u16   aio_lio_opcode;
    __s16   aio_reqprio;
    __u32   aio_fildes;
    __u64   aio_buf;
    __u64   aio_nbytes;
    __s64   aio_offset;
    __u64   aio_reserved2;
    __u32   aio_flags;
    __u32   aio_resfd;
};

이 구조체의 필드들은 다음과 같다.

aio_data
I/O 완료 시 이 데이터가 io_event 구조체의 data 필드로 복사된다. (io_getevents(2) 참고.)
aio_key
커널 내부용 필드이다. io_submit() 호출 후에 이 필드를 변경하지 말 것.
aio_rw_flags

구조체와 함께 전달하는 읽기/쓰기 플래그들이다. 유효한 값은 다음과 같다.

RWF_APPEND (리눅스 4.16부터)
파일 끝에 데이터를 덧붙임. pwritev2(2)에 있는 같은 이름의 플래그 설명과 open(2)O_APPEND 설명 참고.
RWF_DSYNC (리눅스 4.13부터)
동기화 I/O 데이터 무결성 요건에 따라 쓰기 동작이 완료됨. pwritev2(2)에 있는 같은 이름의 플래그 설명과 open(2)O_DSYNC 설명 참고.
RWF_HIPRI (리눅스 4.13부터)
높은 우선도 요청. 가능하면 폴링.
RWF_NOWAIT (리눅스 4.14부터)
커널 내에서 파일 블록 할당이나 변경 페이지 플러싱, 뮤텍스 락 같은 동작이나 혼잡한 블록 장치 때문에 I/O가 블록 되려는 경우에 대기하지 않는다. 이 중 한 조건이라도 해당하면 io_event 구조체의 res 필드에 반환 값 -EAGAIN을 담아서 제어 블록을 즉시 반환한다. (io_getevents(2) 참고.)
RWF_SYNC (리눅스 4.13부터)
동기화 I/O 파일 무결성 요건에 따라 쓰기 동작이 완료됨. pwritev2(2)에 있는 같은 이름의 플래그 설명과 open(2)O_SYNC 설명 참고.
aio_opcode
iocb 구조체로 수행할 I/O 종류를 나타낸다. 유효한 값들이 linux/aio_abi.h에 열거형으로 정의돼 있다.
enum {
    IOCB_CMD_PREAD = 0,
    IOCB_CMD_PWRITE = 1,
    IOCB_CMD_FSYNC = 2,
    IOCB_CMD_FDSYNC = 3,
    IOCB_CMD_POLL = 5,
    IOCB_CMD_NOOP = 6,
    IOCB_CMD_PREADV = 7,
    IOCB_CMD_PWRITEV = 8,
};
aio_reqprio
요청 우선순위를 나타낸다.
aio_fildes
I/O 동작을 수행할 파일 디스크립터이다.
aio_buf
읽기 또는 쓰기 동작에서 데이터 이동에 사용할 버퍼이다.
aio_nbytes
aio_buf가 가리키는 버퍼의 크기이다.
aio_offset
I/O 동작을 수행할 파일 오프셋이다.
aio_flags

iocb 구조체에 연계할 플래그들의 집합이다. 유효한 값은 다음과 같다.

IOCB_FLAG_RESFD
비동기 I/O 제어 로직에서 완료 시 aio_resfd에 있는 파일 디스크립터로 알림을 줘야 한다.
IOCB_FLAG_IOPRIO (리눅스 4.18부터)
aio_reqprio 필드를 linux/ioprio.h에 정의된 IOPRIO_VALUE로 해석한다.
aio_resfd
비동기 I/O 완료 시에 알림을 보낼 파일 디스크립터이다.

RETURN VALUE

성공 시 io_submit()은 제출된 iocb 개수를 반환한다. (nr보다 작을 수도 있으며 nr이 0이면 0일 수도 있다.) 실패 반환에 대해선 NOTES를 보라.

ERRORS

EAGAIN
iocb를 큐에 넣기 위한 자원이 충분치 않다.
EBADF
첫 번째 iocb에 지정한 파일 디스크립터가 유효하지 않다.
EFAULT
한 자료 구조가 유효하지 않은 데이터를 가리키고 있다.
EINVAL
ctx_id로 지정한 AIO 문맥이 유효하지 않다. nr이 0보다 작다. *iocbpp[0]에 있는 iocb가 제대로 초기화 되어 있지 않다. 지정한 동작이 iocb의 파일 디스크립터에 유효하지 않다. aio_reqprio 필드의 값이 유효하지 않다.
ENOSYS
이 아키텍처에 io_submit()이 구현돼 있지 않다.
EPERM
aio_reqprio 필드가 클래스 IOPRIO_CLASS_RT로 설정돼 있지만 제출 동작을 하는 문맥에 CAP_SYS_ADMIN 역능이 없다.

VERSIONS

리눅스 2.5에서 비동기 I/O 시스템 호출들이 처음 등장했다.

CONFORMING TO

io_submit()은 리눅스 전용이므로 이식성이 있어야 하는 프로그램에서는 사용하지 말아야 한다.

NOTES

glibc에서 이 시스템 호출의 래퍼를 제공하지 않는다. syscall(2)을 이용해 호출할 수도 있다. 하지만 아마 그보다는 libaio에서 제공하는 io_submit() 래퍼 함수를 쓰고 싶을 것이다.

참고로 libaio 래퍼 함수에서는 ctx_id 인자에 다른 타입(io_context_t)을 쓴다. 또한 libaio 래퍼에서는 일반적인 C 라이브러리 오류 표시 관행을 따르지 않는다. 즉 오류 시에 음수 오류 번호를 (ERRORS에 나열된 값들 중 하나의 음수 값을) 반환한다. syscall(2)을 통해 시스템 호출을 부르는 경우에는 반환 값이 일반적인 오류 표시 관행을 따른다. 즉 -1이고 errno에 오류를 나타내는 (양수) 값이 설정된다.

SEE ALSO

io_cancel(2), io_destroy(2), io_getevents(2), io_setup(2), aio(7)


2021-03-22