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

60,458

Solution 1

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().

Solution 2

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.

Solution 3

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.

Solution 4

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

Share:
60,458
user1002288
Author by

user1002288

Updated on July 09, 2022

Comments

  • user1002288
    user1002288 almost 2 years

    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

  • paxdiablo
    paxdiablo about 12 years
    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.
  • Gargi Srinivas
    Gargi Srinivas about 12 years
    Yes, that is correct. You can use them by attaching to shared blocks. :)
  • user1284631
    user1284631 about 11 years
    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"