MW211 EXIT

devlog
C言語/スリープ「nanosleep()」
2013年06月03日
「nanosleep()」で「0.1秒」スリープをする例。
┌──────────────────────────────────────┐
│struct timespec  req;                                                       │
│req.tv_sec  = 0;                                                            │
│req.tv_nsec = 100 * 1000 * 1000;                                            │
│nanosleep(&req, NULL);                                                      │
└──────────────────────────────────────┘

「timespec」構造体は以下のような内訳で、
ナノ秒は「0~999,999,999」の範囲で指定可能。
┌──────────────────────────────────────┐
│struct timespec {                                                           │
│    time_t   tv_sec;   // 秒                                                │
│    long     tv_nsec;  // ナノ秒                                            │
│};                                                                          │
└──────────────────────────────────────┘

ちなみに、シグナルで一時停止され、再度復帰した場合には
第二引数にスリープしていない残り時間が戻ってくるので
再度実行すれば、全部で想定通りの合計になるらしい。
但し、様々な理由から合計値は若干ずれる模様。
┌──────────────────────────────────────┐
│struct timespec  req,rem;                                                   │
│if (nanosleep(&req, &rem) == -1) {                                          │
│    if (errno == EINTR) {                                                   │
│        nanosleep(&rem, NULL);                                              │
│    } else {                                                                │
│        nanosleep()のエラー;                                                │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
なお、より厳密にしたい場合には「clock_nanosleep()」という関数があるらしい。

また、ナノ秒までいらず秒単位でいいのであれば「sleep()」が使える。
┌──────────────────────────────────────┐
│残り秒 = sleep(指定秒);                                                     │
│if (残り秒 > 0) {                                                           │
│    sleep(残り秒);                                                          │
│}                                                                           │
└──────────────────────────────────────┘
みたいな感じになる。
分類:C/C++
C言語/排他処理flock()2
2013年06月02日
open()で取得されるファイルディスクリプタは
同一ファイル名であっても、openした順番に別の連番となる。

flock()にとる排他は、ファイルディスクリプタ単位ではなく
ファイルディスクリプタが対象とするファイル単位で行われる。

むしろ同一ファイルディスクリプタであれば排他対象外となる。

┌──────────────────────────────────────┐
│open(ファイル名,…);                           →ファイルディスクリプタ「1」│
│open(ファイル名,…);                           →ファイルディスクリプタ「2」│
│flock(1, LOCK_EX | LOCK_NB);                                        →OK(0) │
│flock(2, LOCK_EX | LOCK_NB);                                        →NG(-1)│
│flock(1, LOCK_EX | LOCK_NB);                                        →OK(0) │
└──────────────────────────────────────┘
分類:C/C++
C言語/排他処理flock()
2013年06月01日
┌──────────────────────────────────────┐
│flock(fd,                                                                   │
│      LOCK_SH);                                                             │
└──────────────────────────────────────┘
基本的に「flock()」でロックをかけるが、先に他でロックをかけていた場合は
「flock()」の中でずーっと待ち状態となる。
これでは埒があかないので、「LOCK_NB」を付加して、
ロック中の場合はエラーとするようにする。
┌──────────────────────────────────────┐
│if (flock(fd, LOCK_SH | LOCK_NB) == -1) {                                   │
│    if (errno == EWOULDBLOCK) {                                             │
│        他でロック中;                                                       │
│    } else {                                                                │
│        flock()エラー;                                                      │
│    }                                                                       │
│}                                                                           │
└──────────────────────────────────────┘
ロック中で即エラーするのもなんだから、リトライ処理で囲って
若干のスリープ処理なんかを挟み込んで、気にならない程度にリトライを
試みさせてみるのもよい。
┌──────────────────────────────────────┐
│for (i = 0; i <= リトライ回数; i++ ) {                                      │
│    if (flock(fd, LOCK_SH | LOCK_NB) == -1) {                               │
│        if (errno == EWOULDBLOCK) {                                         │
│              スリープ処理;                                                 │
│              continue;                                                     │
│        } else {                                                            │
│            flock()エラー;                                                  │
│            break;                                                          │
│        }                                                                   │
│    }                                                                       │
│    ロック成功フラグ = true;                                                │
│    break;                                                                  │
│}                                                                           │
│if (!ロック成功フラグ) {                                                    │
│    close(fd);                                                              │
│    return;                                                                 │
│}                                                                           │
└──────────────────────────────────────┘
分類:C/C++
前へ 1 2 3 次へ