5

私は (S[O|F|U] ネットワーク内と他の場所の両方で) 熱心に検索しましたが、これは珍しい質問だと思います。Debian Linux 2.6.28-4 を実行する Atmel AT91SAM9263-EK 開発ボード (ARM926EJ-S コア、ARMv5 命令セット) を使用しています。RS-485シリアルコントローラーと通信するためにttyドライバーを使用して(私は信じています)書いています。書き込みと読み取りがアトミックであることを確認する必要があります。ソース コードの数行 (カーネル ソースのインストール ディレクトリを基準として、この投稿の最後にリストされています) は、これを暗示しているか、暗黙のうちに述べています。

このデバイスへの書き込み/読み取りが実際にアトミック操作であることを確認する方法はありますか? または、/dev/ttyXX デバイスは FIFO と見なされ、引数はそこで終了しますか? コードがこの主張を強制していると単純に信じるだけでは十分ではないようです - 今年の 2 月のように、freebsd は小さな行のアトミックな書き込みを欠いていることが実証されました。. はい、freebsd が Linux とまったく同じではないことは承知していますが、私の言いたいことは、慎重に確認しても問題ないということです。私が考えることができるのは、データを送信し続けて順列を探すことだけです.もう少し科学的で、理想的には決定論的なものを望んでいました. 残念ながら、私は大学時代の並行プログラミングの授業について正確には何も覚えていません。平手打ちや正しい方向への突き出しに心から感謝します。返信を選択した場合は、事前に感謝します。

敬具、

ジェイス


ドライバー/char/tty_io.c:1087

void tty_write_message(struct tty_struct *tty, char *msg)
{
    lock_kernel();
    if (tty) {
        mutex_lock(&tty->atomic_write_lock);
        if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags))
            tty->ops->write(tty, msg, strlen(msg));
        tty_write_unlock(tty);
    }
    unlock_kernel();
    return;
}


アーチ/アーム/インクルード/asm/bitops.h:37

static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
{
    unsigned long flags;
    unsigned long mask = 1UL << (bit & 31);

    p += bit >> 5;

    raw_local_irq_save(flags);
    *p |= mask;
    raw_local_irq_restore(flags);
}


ドライバー/シリアル/serial_core.c:2376

static int
uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
    struct uart_state *state = tty->driver_data;
    struct uart_port *port;
    struct circ_buf *circ;
    unsigned long flags;
    int c, ret = 0;

    /*
     * This means you called this function _after_ the port was
     * closed.  No cookie for you.
     */
    if (!state || !state->info) {
        WARN_ON(1);
        return -EL3HLT;
    }

    port = state->port;
    circ = &state->info->xmit;

    if (!circ->buf)
        return 0;

    spin_lock_irqsave(&port->lock, flags);
    while (1) {
        c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
        if (count < c)
            c = count;
        if (c <= 0)
            break;
        memcpy(circ->buf + circ->head, buf, c);
        circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
        buf += c;
        count -= c;
        ret += c;
    }
    spin_unlock_irqrestore(&port->lock, flags);

    uart_start(tty);
    return ret;
}

また、man write(3) ドキュメントから:

パイプまたは FIFO への書き込みの試みには、いくつかの主要な特徴があります。

  • アトミック/非アトミック: 1 回の操作で書き込まれた量全体が他のプロセスからのデータとインターリーブされていない場合、書き込みはアトミックです。これは、単一のリーダーにデータを送信するライターが複数ある場合に便利です。アプリケーションは、書き込み要求がアトミックに実行されると予想される大きさを知る必要があります。この最大値は {PIPE_BUF} と呼ばれます。IEEE Std 1003.1-2001 のこのボリュームでは、{PIPE_BUF} バイトを超える書き込み要求がアトミックであるかどうかは述べていませんが、{PIPE_BUF} バイト以下の書き込みがアトミックである必要があります。
4

2 に答える 2

3

技術的には、デバイスは FIFO ではないため、引用した保証が適用されることになっていることはまったく明らかではありません。

プロセス内の部分的な書き込みと読み取りについて心配していますか、それとも実際に異なるプロセスから同じデバイスを読み書きしていますか? 後者を想定すると、何らかのプロキシ プロセスを実装した方がよい場合があります。プロキシはデバイスを排他的に所有し、すべての読み取りと書き込みを実行するため、マルチプロセスの原子性の問題を完全に回避できます。

要するに、「このデバイスからの読み取り/書き込みが実際にはアトミック操作である」ことを確認しようとしないことをお勧めします。自信を持って行うのは難しく、新しいバージョンの Linux (またはまったく異なる o/s) が必要な方法で原子性を実装できなかった場合、微妙な障害が発生する可能性があるアプリケーションが残ります。

于 2009-12-28T19:06:08.003 に答える
2

PIPE_BUF正しいことだと思います。現在、バイト未満の書き込みはPIPE_BUFアトミックではない可能性がありますが、そうでない場合は OS のバグです。OSに既知のバグがあるかどうかをここで尋ねることができると思います. しかし、本当に、そのようなバグがある場合は、すぐに修正する必要があります。

アトミック以上に書きたい場合PIPE_BUFは、運が悪いと思います。アプリケーションの調整と協力以外に、より大きなサイズの書き込みがアトミックに行われるようにする方法はないと思います。

この問題の解決策の 1 つは、デバイスの前に独自のプロセスを配置し、デバイスに書き込みたいすべての人がそのプロセスにアクセスして、代わりにデータを送信するようにすることです。その後、アトミック性の保証に関して、アプリケーションにとって意味のあることは何でも行うことができます。

于 2009-12-28T19:06:47.890 に答える