4 Stimmen

Sollte ich synchronisieren mq_timedreceive Anrufe, wenn sie von mehreren Threads ausgeführt werden?

Ich verwende Posix Message Queues unter Linux. Grundsätzlich habe ich mehrere Threads, die Nachrichten von der gleichen Warteschlange durch Aufrufe von mq_timedreceive empfangen.

Wenn mehr als ein Thread gleichzeitig läuft und die Warteschlange nicht leer ist, ist garantiert, dass eine Nachricht nicht mehr als einmal empfangen wird (d.h. die Nachricht wird nicht an mehrere Threads übermittelt)?

Um sicher zu gehen, könnte ich den Empfang mit einem Mutex synchronisieren, aber ich würde gerne dieses Sperren vermeiden, wenn möglich. Ich habe alle Man-Pages gelesen (man mq_overview(3)), aber nichts Explizites gefunden.

Im Voraus vielen Dank.

3voto

Kristof Provost Punkte 25400

Der Kernel übernimmt diese Sperrung für Sie.

Schauen Sie sich die Implementierung in ipc/mqueue.c an:

SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
                size_t, msg_len, unsigned int __user *, u_msg_prio,
                const struct timespec __user *, u_abs_timeout)
{    
    ...   
    struct mqueue_inode_info *info;
    ...
    filp = fget(mqdes);
    if (unlikely(!filp)) {
        ret = -EBADF;
        goto out;
    }

    inode = filp->f_path.dentry->d_inode;
    ...
    spin_lock(&info->lock);
    if (info->attr.mq_curmsgs == 0) {
        if (filp->f_flags & O_NONBLOCK) {
            spin_unlock(&info->lock);
...
    } else {
        msg_ptr = msg_get(info);

        inode->i_atime = inode->i_mtime = inode->i_ctime =
                            CURRENT_TIME;

        /* Es gibt jetzt freien Speicherplatz in der Warteschlange. */
        pipelined_receive(info);
        spin_unlock(&info->lock);
        ret = 0;
    }

Jedes mqueue hat ein Sperrsignal, das vor dem Überprüfen auf neue Nachrichten erworben wird.

Das letzte else (pipelined_receive) ist der Ort, an dem die Nachricht aus der Warteschlange genommen wird. Dies wird durch das info->lock geschützt, so dass keine Möglichkeit besteht, dass zwei Threads dieselbe Nachricht erhalten.

2voto

Simon Elliott Punkte 2057

Diese man Seite beschreibt es ziemlich gut:

http://pubs.opengroup.org/onlinepubs/009604499/functions/mq_receive.html

Wenn mehr als ein Thread darauf wartet, eine Nachricht zu empfangen, wenn eine Nachricht in eine leere Warteschlange eintrifft und die Prioritätsscheduling-Option unterstützt wird, wird der Thread mit der höchsten Priorität, der am längsten gewartet hat, ausgewählt, um die Nachricht zu empfangen. Andernfalls ist nicht spezifiziert, welcher Wartethread die Nachricht empfängt.

Dies ermöglicht Ihnen, POSIX Nachrichtenwarteschlangen zu verwenden, um Producer-/Consumer-Threads zu implementieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X