epollをセットアップする
epollセットを作成して登録します。
「epollをセットアップする」はCoddyKit上の無料C Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。
epollインスタンスの作成
すべては、ファイルディスクリプタでもあるepollインスタンスから始まります。epoll_create1()で作成します。
引数はフラグフィールドです。デフォルトの動作にする場合は0を、exec()をまたいでディスクリプタを自動的に閉じる場合はEPOLL_CLOEXECを渡します。返されたfdを、以降のすべてのepoll呼び出しに渡します。
int epfd = epoll_create1(EPOLL_CLOEXEC);
if (epfd == -1) { perror("epoll_create1"); exit(1); }epoll_create1とepoll_createの違い
古いepoll_create(int size)はサイズのヒントを受け取っていましたが、現在のカーネルはこれを無視します。必要なのは、値が正数であることだけでした。
epoll_create1()を使用してください。意味のないサイズではなくフラグを受け取り、EPOLL_CLOEXECをアトミックに指定できるため、別途fcntl()を呼び出す必要がありません。
/* legacy form, size arg ignored by kernel */
int epfd = epoll_create(1);epoll_event構造体
監視対象と結果は、どちらもstruct epoll_eventで表します。eventsビットマスクとdata共用体を持ちます。
data共用体には、イベント発生時に返してほしい値を格納します。一般的にはdata.fdを使いますが、確保した接続オブジェクトを指すdata.ptrを格納することもできます。
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = listen_fd;EPOLL_CTL_ADDによる登録
epoll_ctl()で監視対象リストを管理します。ディスクリプタの監視を開始するには、EPOLL_CTL_ADD操作を使用します。
epoll fd、操作、対象fd、およびepoll_eventへのポインタを渡します。これ以降、epollはそのディスクリプタの準備完了を通知します。
struct epoll_event ev = { .events = EPOLLIN, .data.fd = listen_fd };
if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev) == -1)
perror("epoll_ctl: add");イベントフラグ: EPOLLINとEPOLLOUT
eventsマスクで、何を監視するかを指定します。EPOLLINはディスクリプタが読み取り可能であることを、EPOLLOUTは書き込み可能であることを意味します。
通常、接続待ちソケットでは接続を受け付けるためにEPOLLINを監視し、クライアントソケットでも読み取りのためにEPOLLINを監視します。EPOLLOUTを追加するのは、送信しきれなかったデータをバッファリングしている場合だけにしてください。
ev.events = EPOLLIN | EPOLLOUT;エラーと切断のフラグ
カーネルは、要求していない場合でも特定の状態を常に通知します。EPOLLERRはエラー、EPOLLHUPは切断、EPOLLRDHUPは相手側によるハーフクローズを表します。
ハンドラーでこれらを確認してください。切断されたソケットのEPOLLHUPを無視すると、イベントループが空回りします。
if (ev.events & (EPOLLERR | EPOLLHUP)) {
close(ev.data.fd);
continue;
}EPOLL_CTL_MODによる監視対象の変更
ディスクリプタを登録した後でも、登録を解除せずにイベントマスクを変更できます。EPOLL_CTL_MODを使用します。
よくあるパターンは、通常はEPOLLINだけを監視し、送信バッファがいっぱいになったらEPOLLIN | EPOLLOUTに切り替え、送信し終わったら元に戻す方法です。
ev.events = EPOLLIN | EPOLLOUT;
ev.data.fd = conn_fd;
epoll_ctl(epfd, EPOLL_CTL_MOD, conn_fd, &ev);EPOLL_CTL_DELによる削除
接続を閉じるときは、EPOLL_CTL_DELで監視を停止します。最後のepoll_event引数は無視されるため、最近のカーネルではNULLを指定できます。
ディスクリプタを閉じると、すべてのepoll監視対象リストから自動的に削除されます。ただし、閉じる前に明示的に削除しておくと、管理状態が分かりやすくなります。
epoll_ctl(epfd, EPOLL_CTL_DEL, conn_fd, NULL);
close(conn_fd);レベルトリガーとエッジトリガー
デフォルトでは、epollはレベルトリガーです。ディスクリプタが読み取り可能なままである限り、すべてのepoll_wait()で通知されます。扱いやすく、実装も簡単です。
EPOLLETフラグを追加すると、エッジトリガーモードになります。準備状態が変化したときだけ通知されるため、EAGAINになるまでループしてソケットを完全に読み出す必要があります。
ev.events = EPOLLIN | EPOLLET; /* edge-triggered */
epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev);コンテキストポインタの格納
data.fdの代わりに、接続ごとの構造体を指すdata.ptrを格納できます。イベントが発生すると、そのポインタを直接取得できるため、検索テーブルは必要ありません。
ただし、これは共用体であることを忘れないでください。data.ptrを設定した場合、同じイベントからdata.fdも読み取ることはできません。
struct conn *c = malloc(sizeof *c);
c->fd = conn_fd;
ev.events = EPOLLIN;
ev.data.ptr = c;
epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev);後処理
epollインスタンスは単なるファイルディスクリプタなので、サーバーの終了時にclose()で解放します。
epoll fdを閉じると、カーネルの監視対象リストが解放されます。まだ開いている監視対象ソケットは開いたままなので、リソースを解放するには別途閉じてください。
close(epfd);確認テスト
epollのセットアップAPIを理解できているか確認しましょう。
まとめ
epoll_create1()でインスタンスを作成し、epoll_ctl()でADD、MOD、DELを使って監視対象を管理します。各struct epoll_eventには、eventsマスクとdata共用体が格納されます。
簡潔さを重視する場合はレベルトリガーを、エッジトリガーの性能を活用する場合はEPOLLETを選択します。次は、これらの要素をイベントループから動かします。
よくある質問
「epollをセットアップする」レッスンは無料ですか?
はい。「epollをセットアップする」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。
「epollをセットアップする」で何を学びますか?
epollセットを作成して登録します。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「epollをセットアップする」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC Academyレッスンでコードを書いて実行できますか?
はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- ブロッキングI/OとノンブロッキングI/O
- epollをセットアップする
- イベントループ
- シンプルなエコーサーバー