I want to synchronize access to files. I am using Linux and g++.
I would like to lock the file by using the function flock().
I developed 2 tests applications writing and reading to/from the same file.
They both call flock() with LOCK_SH.
The writer starts first, writes and then sleeps. The second app starts later.
I was expecting to see the reader app blocking when it calls flock() since the writer process didn't release the lock.
Is this the right expectation or do they block ONLY when read() and write() are called concurrently i.e. at the same exact time?
What have I misunderstood?
PROG A PROG B
-open file
-flock -open file
-write -sleep 5
-sleep 1000 -flock ** expected to block ?? **
-close -read data
flock would only block if at least one process uses it with LOCK_EX:
If some process holds exclusive lock then any process trying get exclusive/shared lock will be blocked.
If some process holds shared lock then process trying to get exclusive lock will be blocked.
In general you should use shared locks for read and exclusive for write or read/write.
LOCK_SH is a shared lock. This means there's no problem in several processes holding such a lock simultaneously. This kind of lock is used by readers.
Related
Currently working on a light weight filter in the NDIS stack. I'm trying to inject a packet which set in a global variable as an NBL. During receive NBL, if an injected NBL is pending, than a lock is taken by the thread before picking the injected NBL up to process it. Originally I was looking at using a spin lock or FAST_MUTEX. But according to the documentation for FAST_MUTEX, any other threads attempting to take the lock will wait for the lock to release before continuing.
The problem is, that receive NBL is running in DPC mode. This would cause a DPC running thread to pause and wait for the lock to release. Additionally, I'd like to be able to assert ownership of a thread's ownership over a lock.
My question is, does windows kernel support unique mutex locks in the kernel, can these locks be taken in DPC mode and how expensive is assertion of ownership in the lock. I'm fairly new to C++ so forgive any syntax errors.
I attempted to define a mutex in the LWF object
// Header file
#pragma once
#include <mutex.h>
class LWFobject
{
public:
LWFobject()
std::mutex ExampleMutex;
std::unique_lock ExampleLock;
}
//=============================================
// CPP file
#include "LWFobject.h"
LWFobject::LWFObject()
{
ExmapleMutex = CreateMutex(
NULL,
FALSE,
NULL);
ExampleLock(ExampleMutex, std::defer_lock);
}
Is the use of unique_locks supported in the kernel? When I attempt to compile it, it throws hundreds of compilation errors when attempting to use mutex.h. I'd like to use try_lock and owns_lock.
You can't use standard ISO C++ synchronization mechanisms while inside a Windows kernel.
A Windows kernel is a whole other world in itself, and requires you to live by its rules (which are vast - see for example these two 700-page books: 1, 2).
Processing inside a Windows kernel is largely asynchronous and event-based; you handle events and schedule deferred calls or use other synchronization techniques for work that needs to be done later.
Having said that, it is possible to have a mutex in the traditional sense inside a Windows driver. It's called a Fast Mutex and requires raising IRQL to APC_LEVEL. Then you can use calls like ExAcquireFastMutex, ExTryToAcquireFastMutex and ExReleaseFastMutex to lock/try-lock/release it.
A fundamental property of a lock is which priority (IRQL) it's synchronized at. A lock can be acquired from lower priorities, but can never be acquired from a higher priority.
(Why? Imagine how the lock is implemented. The lock must raise the current task priority up to the lock's natural priority. If it didn't do this, then a task running at a low priority could grab the lock, get pre-empted by a higher priority task, which would then deadlock if it tried to acquire the same lock. So every lock has a documented natural IRQL, and the lock will first raise the current thread to that IRQL before attempting to acquire exclusivity.)
The NDIS datapath can run at any IRQL between PASSIVE_LEVEL and DISPATCH_LEVEL, inclusive. This means that anything on the datapath must only ever use locks that are synchronized at DISPATCH_LEVEL (or higher). This really limits your choices: you can use KSPIN_LOCKs, NDIS_RW_LOCKs, and a handful of other uncommon ones.
This gets viral: if you have one function that can sometimes run at DISPATCH_LEVEL (like the datapath), it forces the lock to be synchronized at DISPATCH_LEVEL, which forces any other functions that hold the lock to also run at DISPATCH_LEVEL. That can be inconvenient, for example you might want to hold the locks while reading from the registry too.
There are various approaches to design your driver:
* Use spinlocks everywhere. When reading from the registry, read into temporary variables, then grab a spinlock and copy the temporary variables into global state.
* Use mutexes (or better yet: pushlocks) everywhere. Quarantine the datapath into a component that runs at dispatch level, and carefully copy any configuration state into this component's private state.
* Somehow avoid having your datapath interact with the rest of your driver, so there's no shared state, and thus no shared locks.
* Have the datapath rush to PASSIVE_LEVEL by queuing all packets to a worker thread.
I have to write a daemon to decide acces policy for mutexes ( it establishes which process get the mutex if more than one want the same mutex on whatever criteria)
For that I established some codes : L 1 231 (LOCK mtx_id process_pid).
When a process requests a mutex it writes on a shared memory zone some code similar to the one above.
The daemon reads it. (For every mutex I have a queue with processe waiting to get it.) Puts the process pid in queue.
If it is unlocked , pop queue, give mutex.( Write in shared memory id_mutex and process of the pid that got it, for other processes to read and know who has the mutex.
My question is : how do more processe request same mutex ? Creating them at first and selecting the requested process manually does not seem such a good option.
Any help is appreciated.THank you
Many OS have a container, a catalog, directory or registry, of OS objects that can be stored by name. Once stored in the container, they can be looked up by name and a reference token returned. That token can then be used to access the object.
A synchro object like an inter-process mutex would be a good candidate for storage in the container. Multiple processes could then look up the mutex by name and use it.
Such cataloged objects are often reference-counted so that they are only destroyed when the last process with a token calls for it to be closed.
BTW - see comments, your design suc.... has issues :(
I'm trying to make inter-process communication in C/C++ on Windows environment.
I am creating a shared memory page file and two processes get the handle to that file. It's like this:
Process1: Initialize shared memory area. Wait for Process2 to fill it.
Process2: Get handle to shared memory area. Put stuff in it.
I am creating a named mutex in process1 as well. Now process1 acquires the ownership of the mutex soon after creating it (using WaitSingleObject). Obviously, there is nothing in the memory area so I need to release the mutex. Now I need to wait until the memory is filled instead of trying to acquire the mutex again.
I was thinking of conditional variables. Process2 signals the condition variable once it fills in the memory area and process1 will acquire the information immediately.
However, as per MS Documentation on Condition Variables, they are not shared across processes which is clear from their initialization as they are not named.
Furthermore, the shared memory area can hold up to one element at any given moment which means process2 cannot refill after filling it unless process1 extracts its information.
From the given description it's clear that condition variables are the best for this purpose (or Monitors). So is there a way around this?
Conditional variables can be used with in the process, but not across the processes.
Try NamedPipe with PIPE_ACCESS_DUPLEX as open mode. So that you have communication options from both process.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx
I have used events for this before. Use 2 named auto reset events. 1 data ready event and one buffer ready event. Writer waits for buffer ready, writes data and sets the data ready event. Reader waits for data ready event, reads memory and sets the buffer ready event. If done properly you should not need the mutex.
I'm setting the stale lock time to 100 ms using this code:
QLockFile lock1(fn);
lock1.setStaleLockTime(100);
QVERIFY(lock1.lock());
QLockFile lock2(fn);
lock2.setStaleLockTime(100);
QVERIFY(lock2.lock());
I expected it to block for only 100ms, but it blocks indefinitely. Why is that?
Am I misunderstanding how lock files should become stale? Here's what the docs say:
The value of staleLockTime is used by lock() and tryLock() in order to determine when an existing lock file is considered stale, i.e. left over by a crashed process. This is useful for the case where the PID got reused meanwhile, so one way to detect a stale lock file is by the fact that it has been around for a long time.
You misunderstand something
If the process holding the lock crashes, the lock file stays on disk
and can prevent any other process from accessing the shared resource,
ever. For this reason, QLockFile tries to detect such a "stale" lock
file, based on the process ID written into the file. To cover the
situation that the process ID got reused meanwhile, the current
process name is compared to the name of the process that corresponds
to the process ID from the lock file. If the process names differ, the
lock file is considered stale. Additionally, the last modification
time of the lock file (30s by default, for the use case of a
short-lived operation) is taken into account. If the lock file is
found to be stale, it will be deleted.
So not only staleLockTime but also process ID checked and other things. So you can't use this method such way.
How can i lock a file for read and write operation. That is If "ABC" file name is in Write lock, it also provide Read Lock on the same locked file. In normal case we want to wait till write operation completion.So if there any ways to acquire this kind of locking
Many programs simply use a lock file to signify that a certain file is currently in use for writing.
The lock file is later removed when done writing.
For example, when process #1 is about to start writing to file example, it creates file example.lock. Later when done writing, it simply removes example.lock.
When process #2 want to read from file example it first checks if file example.lock exists. If it does then the file is locked for write operations and process #2 will have to wait.
shared_mutex from Boost implements read/write locking.