Is it possible to use mutex in multiprocessing case on Linux/UNIX ?
Asked Answered
C

5

42

This is an interview question.

Is it possible to use mutex in multiprocessing case on Linux/UNIX ?

My idea: No, different processes have separate memory space.

mutex is only used for multithreading.

semaphore is used for multiprocessing to do synchronization.

right ?

Any comments are welcome.

thanks

Cope answered 22/2, 2012 at 5:50 Comment(3)
Depends on what you mean by "multiprocessing". If you go by the stackoverflow definition, then multiprocessing would include multithreading. If you mean "multiple processes", then you're right.Imputable
See https://mcmap.net/q/15678/-interprocess-mutex-with-pthreadsTruncate
Note: I know you asked about Linux, and I also thought that the term Mutex is strictly used for inner-process thread synchronization, but in Windows for instance a named mutex can be access from other processes too - CreateMutexCatarrhine
C
44

Mutual exclusion locks (mutexes) prevent multiple threads from simultaneously executing critical sections of code that access shared data (that is, mutexes are used to serialize the execution of threads). All mutexes must be global. A successful call for a mutex lock by way of mutex_lock() will cause another thread that is also trying to lock the same mutex to block until the owner thread unlocks it by way of mutex_unlock(). Threads within the same process or within other processes can share mutexes.

Mutexes can synchronize threads within the same process or in other processes. Mutexes can be used to synchronize threads between processes if the mutexes are allocated in writable memory and shared among the cooperating processes (see mmap(2)), and have been initialized for this task.

Initialization

Mutexes are either intra-process or inter-process, depending upon the argument passed implicitly or explicitly to the initialization of that mutex. A statically allocated mutex does not need to be explicitly initialized; by default, a statically allocated mutex is initialized with all zeros and its scope is set to be within the calling process.

For inter-process synchronization, a mutex needs to be allo- cated in memory shared between these processes. Since the memory for such a mutex must be allocated dynamically, the mutex needs to be explicitly initialized using mutex_init().

Ctesiphon answered 24/2, 2012 at 7:21 Comment(1)
also, for inter-process synchronization, besides the requirement to be allocated in shared memory, the mutexes must also use the attribute PTHREAD_PROCESS_SHARED, otherwise accessing the mutex from another process than its creator results in undefined behaviour (see this: linux.die.net/man/3/pthread_mutexattr_setpshared): "The process-shared attribute is set to PTHREAD_PROCESS_SHARED to permit a mutex to be operated upon by any thread that has access to the memory where the mutex is allocated, even if the mutex is allocated in memory that is shared by multiple processes"Stray
T
11

It is quite possible to use a process-shared mutex.

In fact, modern applications prefer using a process shared mutex along with process shared condition variable over a semaphore because the latter is less flexible.

I remember using Red Hat Linux in 2004 and at that time it supported both process shared mutexes and condition variables.

Tyus answered 22/2, 2012 at 9:26 Comment(0)
S
6

Not quite. POSIX threads has a concept of a process-shared attribute which can be used to create mutexes that can be operated on by multiple processes.

You can put such a mutex in shared memory so that multiple processes can all get at it.

Whether LINUX implements this., I'm not sure, I've never had a need to use it since it seems unnecessarily complex.

For a useful precis of attributes, see my answer to this question.

Stolen answered 22/2, 2012 at 5:58 Comment(0)
H
2

I was looking for a named mutex so that I could ensure mutual exclusion for the lifetime of a process (making sure only one process running per some set of properties). I didn't find one (looks like I might have not looked hard enough) and so I implemented my own pseudo named mutex in linux by using an abstract UNIX domain socket. Only a single bind() to that socket will succeed. The other nice thing is that the OS will cleanup the abstract UNIX domain socket if the process dies and thus doesn't cleanup the socket itself. Unfortunately I'm not sure of any way for you to "wait" on this pseudo mutex to become available.

An abstract UNIX domain socket is a UNIX domain socket whose name begins with a null byte. Beware though, I believe that the entire buffer is used as the name and thus you want to ensure that you don't just memcpy or strcpy a partial string into it, or if you do make sure you first fill the entire buffer with some character.

All but the first bind() will fail with an errno of EADDRINUSE.

// Create an abstract socket to use as a mutex.                             

int err;
int mutex_sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (mutex_sock == -1)
    {
    err = errno;
    printf("main, failed creating mutex socket: %s\n",
            get_error_string(errno, error_string, sizeof(error_string)));
    log_event(LOG_LEVEL_ERROR, "main, failed creating mutex socket: "
            "%s", get_error_string(errno, error_string,
            sizeof(error_string)));
    errno = err;
    goto done;
    }

// Bind to abstract socket.  We use this as a sort of named mutex.          

struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path + 1, socket_name, sizeof(addr.sun_path) - 2);
result = bind(mutex_sock, (struct sockaddr*) &addr, sizeof(addr));
if (result == -1)
    {
    err = errno;
    if (errno == EADDRINUSE)
        {
        printf("main, failed bind to mutex socket: %s.  "
                "Another instance must be running.\n",
                get_error_string(errno,
                error_string, sizeof(error_string)));
        log_event(LOG_LEVEL_ERROR, "main, failed bind to mutex socket: "
                "%s.  "
                "Another instance must be running.",
                get_error_string(errno,
                error_string, sizeof(error_string)));
        }
    else
        {
        printf("main, failed bind to mutex socket: %s\n",
                get_error_string(errno, error_string,
                sizeof(error_string)));
        log_event(LOG_LEVEL_ERROR, "main, failed bind to mutex socket: %s",
                get_error_string(errno, error_string,
                sizeof(error_string)));
        }
    errno = err;
    goto done;
    }

Thanks, Nick

Hirst answered 16/5, 2016 at 14:28 Comment(1)
Doesn't seem to work on macOS. bind returns errno = 2Tenement
D
0

Yes, in general in Linux we have only unnamed mutexes due to which they cannot operate between processes. We need a semaphore to get over that.

In windows, they have a concept of named mutexes which lets us use mutexes across processes.

Demetricedemetris answered 22/2, 2012 at 6:6 Comment(2)
See linux.die.net/man/3/pthread_mutexattr_init - LINUX allows for process-shared mutexes. Whether they're named or not is not relevant here, Linux and UNIX can share them without names by attaching to common shared memory blocks.Stolen
Yes, that is correct. You can use them by attaching to shared blocks. :)Demetricedemetris

© 2022 - 2024 — McMap. All rights reserved.