File Locking in Linux
File locking in Linux is the solution by which you can ensure that the file for reading/writing is going to be handled safely.
β Sagar Sharma
Nope, this is not about password-protecting your files.
When multiple processes are working on the same file, you might not get intentional output as there was no order defined on how processes are going to handle the same file!
And file locking is the solution by which you can ensure that the file for reading/writing is going to be handled the safe way by defining the order.
It might sound too complex and that's perfectly fine. So before approaching the solution, let me bring light to the problem.
Why File Locking is Needed
The problem is similar to the Race condition where multiple processes are modifying the same data simultaneously and the result strictly depends on the order of the process.
Let's say there are two processes A and B which are dealing with the file named account.txt (initial data is 100)and their behavior is like this:
- A reads the current value and subtracts 20 from the initial balance
- B reads the current value and adds 50 to the balance.
On paper, everything looks excellent and the final data should be 130 but it ends up being something else. Let me show you how:
- Process A: Reads data (100) and prepares for the operation.
- Process B: Reads data (100) and saves the current data to its buffer.
- Process A: Subsctracts 20 from 100 making it 80.
- Process B: It is unaware of the fact that the original data has been modified and uses 100 as the initial value so the final result ends up being 150 (100 + 50) rather than what you expected (130).
And there comes the implementation for file locking. So let's have a look at the types of file locking in Linux.
Types of File Locking in Linux
There are two types of file locking in Linux:
- Advisory Locking
- Mandatory Locking
1. Β Advisory Locking
The advisory locking system will not force the forces and will only work if both processes are participating in locking.
For example, process A acquires the lock and starts given tasks with a file.
And if process B starts without acquiring a lock, it can interrupt the ongoing task with process A.
So the condition for making an advisory lock is to ensure each process participates in locking.
2. Mandatory Locking
Mandatory locking can be understood as a forced locking system and it does not require any cooperation by the processes.
A mandatory locking causes the kernel to monitor every open, read, and write to verify that the process is not going to violate any process.
But making mandatory locking work requires comparatively more steps:
- Mounting files with the β-o mandβ option.
- Also, users are required to turn off the group execute bit and turn on set-group-ID to enable mandatory locking as when you turn off the group-execute bit, set-group-ID will have no impact.
How to Enable Advisory Locking
For this, I'll be using the flock command which allows users to handle tasks related to advisory locking. And the syntax for the flock command is as follows:
flock file_to_lock command
First, let's make a file to hold the default value:
touch account.txt
Now, let's make it hold 100 as the default value:
echo "100" > account.txt
So let's create a simple script to handle the logical part of the processes:
#!/bin/bash
file="account.txt"
value=$(cat $file)
echo "Read current balance:$value"
#sleep 10 seconds to simulate business calculation
progress=10
while [[ $progress -lt 101 ]]; do
echo -n -e "\033[77DCalculating new balance..$progress%"
sleep 1
progress=$((10+progress))
done
echo ""
value=$((value+$1))
echo "Write new balance ($value) back to $file."
echo $value > "$file"
echo "Done."
Now, let's create the process a.sh with advisory locking:
touch a.sh
nano a.sh
And make sure it contains the following:
#!/bin/bash
flock --verbose balance.dat ./update_balance.sh '-20'
Now, let's make it executable:
chmod +x a.sh
So let's put it to the test:
./a.sh
Behavior with Non-cooperative process
For this example, I'll be creating the script b.sh
which will be non-cooperative to its nature.
touch b.sh
nano b.sh
And script should contain the following:
#----------------------------------------
# non-cooperative way
#----------------------------------------
./update_balance.sh '80'
Make it executable by following the given command:
chmod +x b.sh
So let's put it to the test:
As you can clearly see, my desired value was supposed to be 160 but the process b messed up and gave 180.
Behavior with Cooperative Processes
In this section, I'll be making process b a cooperative process with some minor changes as given:
#----------------------------------------
# A cooperative way
#----------------------------------------
flock --verbose balance.dat ./update_balance.sh '80'
Its show time:
As you can clearly see, process B waited while the first process was being executed and I got the desired results!
How to Inspect Locks in Linux
You can inspect all locks using lslocks command. And the usage is quite easy. A single command and that's it:
lslocks
And it will show everything from the command, and type of lock to the path.
Final Words
This guide explained all the basics related to locks in Linux with examples of how you can use advisory Linux for suitable tasks.
And if you have any queries, let me know in the comments.
A software engineer who loves to tinker with hardware till it gets crashed. While reviving my crashed system, you can find me reading literature, manga, or watering my plants.