In some situations, we need to explicitly unlock a file. The same system call, lockf, will help us, but we need to pass F_ULOCK as a parameter. We mentioned that in the above example we passed a value of 0 as the third parameter to the lockf call. This resulted in the locking of an entire file. But in some cases, we may be interested in locking some part of a file. The third parameter passed to the lockf call is the number of bytes of the file that will be locked.
When we use files, we may encounter a situation known as ‘deadlock’. Take a look at the following program to understand this situation better:
fd = open(“testfile”,O_RDWR);
printf(“Parent locked 10 charsn”);
pid = fork();
if (pid == 0)
printf(“End of 1st Child processn”);
printf(“End of Parent processn”);
Here, we first open a file and lock the first ten bytes. Then a child process is forked and gets the time slice. In the child process, we try to lock ten bytes. But these have already been locked. Thus the child waits for the parent to unlock the file. But in the parent process, we have a wait() call and thus the parent waits till the child process is over. So we are in a situation where parent waits for the child and child waits for the parent. Hence a deadlock situation. Whenever such a situation occurs, Linux is smart enough to recognise it and sort it out. When Linux realises that a deadlock has occurred, it prints an error message and terminates the parent process.
Linux provides another synchronisation primitive – known as semaphores. Even though they are a form of IPC, they are not used for exchanging large amounts of data. They are basically intended to let multiple processes synchronise their operations. One main purpose of semaphore is to synchronise the access to a shared memory segment. As semaphores are used to provide resource synchronisation between various processes, it is natural to expect the value of a semaphore to be stored in the kernel.
To obtain a resource that is controlled by a semaphore, a process needs to test its current value. If the current value is greater than zero, then decrement the value by one. If the current value is zero, then the process needs to wait until the value is greater than zero. To release a resource that is controlled by a semaphore, a process increments the semaphore value. If some other process has been waiting for the semaphore value to become greater than zero, that other process can now obtain the semaphore.