POSIX 비동기 I / O (AIO)의 상태는 어떻습니까?


93

POSIX AIO 시설을 다양한 세부 사항으로 설명하는 페이지가 웹에 흩어져 있습니다. 그들 중 누구도 끔찍하게 최근의 것이 아닙니다. 정확히 무엇을 설명하고 있는지 명확하지 않습니다. 예를 들어 여기에있는 Linux 커널 비동기 I / O 지원을위한 "공식"(?) 웹 사이트에서는 소켓이 작동하지 않는다고 말하지만 Ubuntu 8.04.1 워크 스테이션의 "aio.h"매뉴얼 페이지는 모두 다음을 암시하는 것 같습니다. 임의의 파일 설명자에 대해 작동합니다. 그런 다음 더 적은 문서로 라이브러리 계층에서 작동하는 것으로 보이는 또 다른 프로젝트가 있습니다.

알고 싶습니다 :

  • POSIX AIO의 목적은 무엇입니까? 내가 찾을 수있는 구현의 가장 명백한 예가 소켓을 지원하지 않는다는 것을 감안할 때 모든 것이 이상하게 보입니다. 비동기 디스크 I / O 전용입니까? 그렇다면 왜 하이퍼 일반 API입니까? 그렇지 않다면 왜 디스크 I / O가 가장 먼저 공격을 받았습니까?
  • 내가 볼 수있는 완전한 POSIX AIO 프로그램의 예는 어디에 있습니까 ?
  • 실제로 실제로 사용하는 사람이 있습니까?
  • POSIX AIO를 지원하는 플랫폼은 무엇입니까? 그들은 어떤 부분을 지원합니까? <aio.h>약속 된 것처럼 보이는 "모든 FD에 대한 모든 I / O"를 실제로 지원하는 사람이 있습니까?

제가 사용할 수있는 다른 멀티플렉싱 메커니즘은 완벽하게 훌륭하지만 주변에 떠 다니는 임의의 정보 조각이 저를 궁금하게 만들었습니다.

답변:


27

POSIX 네트워크 서버를 작성하는 모든 사람이 이벤트 기반 비 차단 방식을 사용하기 때문에 네트워크 I / O는 AIO의 우선 순위가 아닙니다. 구식 Java "수십억 개의 차단 스레드"접근 방식은 끔찍합니다.

디스크 쓰기 I / O는 이미 버퍼링되어 있으며 posix_fadvise와 같은 함수를 사용하여 디스크 읽기 I / O를 버퍼로 프리 페치 할 수 있습니다. 따라서 버퍼링되지 않은 직접 디스크 I / O가 AIO의 유일한 유용한 용도로 남습니다.

버퍼링되지 않은 직접 I / O는 트랜잭션 데이터베이스에만 실제로 유용하며 이들은 자체 스레드 또는 프로세스를 작성하여 디스크 I / O를 관리하는 경향이 있습니다.

따라서 결국 POSIX AIO는 유용한 목적을 제공 하지 않는 위치에 있습니다. 그것을 사용하지 마십시오.


8
네트워크 (NFS, Samba) 파일 시스템에서 읽기 / 쓰기는 어떻습니까?
Alex B

1
잘. 내가 캐시로 보내면 dirty_ratio가 최고점에 도달하여 다른 모든 사람을 차단하는 멍청한 작가가 여러 개 있습니다. 직접 IO를 사용하면 너무 느립니다. 스레드가 1 개만 있으면 직접 관리 할 수 ​​있지만 1 트레드에서 다른 IO 우선 순위를 지원하기가 어려울 것입니다. AIO + CFQ 정말 AIO가 일 경우, 좋은 조합을 보인다 wouls
N-알렉산더

37
동의하지 않습니다. 디스크 I / O는 버퍼링되는 경향이 있지만 차단 될 수 있습니다. 파일 FD를 poll () 할 때 FD가 차단 되더라도 항상 읽을 수 있다고보고합니다. 이로 인해 스레드 또는 AIO를 사용하지 않는 한 이벤트 방식으로 디스크 파일에서 비 차단 작업을 수행 할 수 없습니다.
Hongli

2
@Matt : 데이터 그램 소켓에서는 순서가 중요하지 않습니다. @Zan : 비동기 I / O는 미디어 플레이어와 같은 실시간 스트리밍 데이터를 미리 버퍼링하는 데 매우 좋습니다.
Ben Voigt 2011 년

13
AIO가 이벤트 기반 시스템에서 쓸모가 없다는 것은 사실이 아닙니다. recv ()에 대한 이벤트 기반 알림으로는 불가능한 적절한 AIO를 사용하여 실제로 제로 카피 네트워킹에 도달 할 수 있습니다. 다른 것들이 이것을 대부분 이론적 인 한계로 만들기 위해 공모 할 수 있지만, 적절한 AIO (Windows에서 오버랩 됨)의 부족은 Linux의 마지막 큰 구멍 중 하나라고 생각합니다.
Jon Watte 2012

69

소켓 I / O를 효율적으로 수행하는 것은 kqueue, epoll, IO 완료 포트 등으로 해결되었습니다. 비동기 파일 I / O를 수행하는 것은 일종의 후발입니다 (Windows의 중첩 된 I / O 및 posix AIO에 대한 solaris 초기 지원과는 별개).

소켓 I / O를 수행하려는 경우 위의 메커니즘 중 하나를 사용하는 것이 좋습니다.

따라서 AIO의 주요 목적은 비동기 디스크 I / O 문제를 해결하는 것입니다. 이것이 Mac OS X이 소켓이 아닌 일반 파일에 대해서만 AIO를 지원하는 이유 일 가능성이 큽니다 (kqueue가 더 나은 방법이기 때문입니다).

쓰기 작업은 일반적으로 커널에 의해 캐시되고 나중에 플러시됩니다. 예를 들어 드라이브의 읽기 헤드가 블록이 기록 될 위치를 지나가는 경우입니다.

그러나 읽기 작업의 경우 커널에서 읽기 우선 순위를 지정하고 순서를 지정하려면 AIO가 실제로 유일한 옵션입니다. 커널이 (이론적으로) 어떤 사용자 수준 응용 프로그램보다 더 잘 할 수있는 이유는 다음과 같습니다.

  • 커널은 응용 프로그램 디스크 작업뿐만 아니라 모든 디스크 I / O를보고 글로벌 수준에서 주문할 수 있습니다.
  • 커널은 디스크 읽기 헤드가 어디에 있는지 알고 있으며, 헤드를 최단 거리로 이동하기 위해 최적의 순서로 전달하는 읽기 작업을 선택할 수 있습니다.
  • 커널은 원시 명령 대기열 을 활용 하여 읽기 작업을 더욱 최적화 할 수 있습니다.
  • readv ()보다 lio_listio ()를 사용하여 시스템 호출 당 더 많은 읽기 작업을 수행 할 수 있습니다. 특히 읽기가 (논리적으로) 연속적이지 않은 경우 시스템 호출 오버 헤드를 약간 절약 할 수 있습니다.
  • 읽기 또는 쓰기 호출에서 차단할 추가 스레드가 필요하지 않기 때문에 AIO를 사용하면 프로그램이 약간 더 간단해질 수 있습니다.

즉, posix AIO에는 매우 어색한 인터페이스가 있습니다. 예를 들면 다음과 같습니다.

  • 유일하게 효율적이고 잘 지원되는 이벤트 콜백 수단은 신호를 통한 것이므로 프로세스 전역 신호 네임 스페이스의 신호 번호를 사용하기 때문에 라이브러리에서 사용하기가 어렵습니다. OS가 실시간 신호를 지원하지 않는다면, 어떤 요청이 실제로 완료되었는지 확인하기 위해 모든 미해결 요청을 반복해야 함을 의미합니다 (예 : Linux가 아닌 Mac OS X의 경우). 다중 스레드 환경에서 신호를 포착하면 몇 가지 까다로운 제한이 발생합니다. 일반적으로 시그널 핸들러 내부의 이벤트에 반응 할 수 없지만 시그널을 발생 시키거나 파이프에 쓰거나 signalfd () (리눅스에서)를 사용해야합니다.
  • lio_suspend ()는 select ()와 동일한 문제를 가지고 있으며 작업 수에 따라 확장되지 않습니다.
  • 구현 된대로 lio_listio ()는 전달할 수있는 작업의 수가 상당히 제한되어 있으며 이식 가능한 방식으로이 제한을 찾는 것은 사소한 일이 아닙니다. sysconf (_SC_AIO_LISTIO_MAX)를 호출해야합니다.이 경우 실패 할 수 있습니다.이 경우 반드시 정의되지 않은 AIO_LISTIO_MAX 정의를 사용할 수 있지만 지원이 보장되는 것으로 정의 된 2를 사용할 수 있습니다.

posix AIO를 사용하는 실제 응용 프로그램의 경우 지원을 도입 할 때 성능 측정을 게시 한 lighttpd (lighty)를 살펴볼 수 있습니다 .

대부분의 posix 플랫폼은 현재 posix AIO를 지원합니다 (Linux, BSD, Solaris, AIX, tru64). Windows는 겹친 파일 I / O를 통해이를 지원합니다. 내 이해는 Solaris, Windows 및 Linux만이 진정으로 비동기를 지원한다는 것입니다. 다른 OS는 비동기를 에뮬레이트하는 반면 파일 I / O는 드라이버까지 내려갑니다. 커널 스레드가있는 I / O. Linux는 예외입니다. glibc의 posix AIO 구현은 사용자 수준 스레드를 사용하여 비동기 작업을 에뮬레이트하는 반면 기본 비동기 I / O 인터페이스 (io_submit () 등)는 드라이버가 지원한다고 가정 할 때 완전히 비동기식입니다. .

나는 모든 fd에 대해 posix AIO를 지원하지 않지만 일반 파일로 제한하는 것이 OS 사이에서 상당히 일반적이라고 생각합니다.


Windows는 Win32가 처음 출시 된 이후로 디스크 파일을 지원하는 I / O가 오버랩되었습니다. 전혀 새로운 것이 아닙니다. 그리고 POSIX에서 신호 네임 스페이스는 프로세스 전역이 아니라 스레드 단위입니다. 시그널은 특정 스레드로 전달됩니다 (또는 예외입니다. 확실히 기억할 수 없습니까?).
Ben Voigt 2011 년

1
어떤 스레드 AIO가 신호를 전달하는지 지정할 방법이 없습니다. Linux에서는 대부분 aio _ * () 명령을 실행 한 스레드에 전달 하는 것처럼 보이지만 항상 그런 것은 아닙니다 (내가 찾은 유일한 해결책은 여러 개의 signalfd를 만드는 것입니다). 몇 년 전 커널 메일 링리스트에 이것을 추가하는 리눅스 패치가 있었지만, 그것을 만들지 않았고, POSIX의 확장이었을 것입니다. Mac OS X에서 신호는 대부분 (내 경험상) 메인 스레드로 전달되는 것 같습니다. POSIX에 특정 동작이 필요하다고 생각하지 않습니다. 그렇다면 사양의 일부를보고 싶습니다.
Arvid 2011 년

5
glibc의 aio_read / write 구현은 사용자 영역의 스레드를 사용하므로 여기서는 커널 스레드조차 사용되지 않습니다.
Marenz 2011

"항상 일반적"이란 무엇을 의미합니까? 모든 방법에 대해 커널에 의해 쓰기가 캐시됩니다. 또는 AIO를 사용할 때? 쓰기가 성공적으로 완료되었는지 소프트웨어가 확신 할 수있는 방법이 있어야합니다. 그렇지 않으면 무결성 및 거래 목표를 달성 할 수 없습니다.
MikeB

AIO를 사용할 수있는 또 다른 실제 예는 nginx입니다. 모든 모드가 지원됩니다. 사용자 영역 스레드에 대한 오프로드를 선호하는 경우 일반적으로 직접 IO보다 훨씬 나쁘지만 Linux 기본 AIO는 직접 IO와 동등합니다. AIO가 실질적으로 유익 할 수있는 상황은 심각한 페이지 캐시 압력입니다. 비동기와 직접 IO를 사이의 개념 차이는 여기에서 볼 수있는 ftp.dei.uc.pt/pub/linux/kernel/people/suparna/aio-linux.pdf
심지


2

aio_write가 있습니다-glibc에서 구현되었습니다. aio_read 또는 aio_write 함수의 첫 번째 호출은 여러 사용자 모드 스레드, aio_write 또는 aio_read 포스트 요청을 해당 스레드에 생성하고 스레드는 pread / pwrite를 수행하며 완료되면 응답이 차단 된 호출 스레드에 다시 게시됩니다.

Ther은 또한 '실제'aio입니다-커널 수준에서 지원합니다 (libaio 필요, io_submit 호출 http://linux.die.net/man/2/io_submit 참조 ). 이를 위해 O_DIRECT도 필요합니다 (모든 파일 시스템에서 지원되지 않을 수도 있지만 주요 파일 시스템에서 지원함).

여기를 보아라:

http://lse.sourceforge.net/io/aio.html

http://linux.die.net/man/2/io_submit

Linux에서 POSIX AIO와 libaio의 차이점은 무엇입니까?


의 많은 결함은 aio_write위에서 다루었습니다. stackoverflow.com/a/5307557/13564
Glyph
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.