Applying C - File Descriptors |
Written by Harry Fairhead | |||||
Monday, 24 August 2020 | |||||
Page 4 of 4
To test this we need a simple reader which follows the same general pattern as the writer: #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char** argv) { struct flock lockread={0}; lockread.l_type = F_RDLCK; lockread.l_whence = SEEK_SET; lockread.l_start = 10; lockread.l_len = 4; int value=0; int fd = open("/tmp/fd.txt", O_RDWR , 0600); for (;;) { lseek(fd, 10, SEEK_SET); lockread.l_type = F_RDLCK; fcntl(fd, F_SETLKW, &lockread); read(fd, &value, 4); lockread.l_type = F_UNLCK; fcntl(fd, F_SETLK, &lockread); if((value!=0x55555555) && (value!=~0x55555555)){ printf("%x\n", value); } fflush(stdout); } close(fd); } In this case the process attempts to gain a read lock and then reads the value from the same four bytes that the writer process writes to. The call to fcntl is blocking, so if the read lock cannot be acquired the process waits. After reading the value we test to make sure that it is one of the two possible values that the writer process writes to the file. If you compile both programs and run them you will see no errors printed. The reason is that the reading program cannot read the four bytes while the writing programming is updating the value and the writing program cannot write to the four bytes while the reading program is reading a value. This use of locks may sound unnecessary, but if you remove the call to fcntl to acquire the lock in the writing program you will soon see that it is very necessary. You will see values such as: 555aaaaa 555555aa aaaa5555 555555aa aaaa5555 These result when the writing program is in the middle of changing the value while the reading program is in the middle of reading the value. Notice that the locks are per process and any threads within the process share the same set of locks. This also means that if a process closes a file then all of its locks are released, even if it still has other file descriptors open on the same file. In particular, if a library function opens and then closes the same file then all the locks are lost. The fact that all the threads in a process share the same set of locks imposes some restrictions on what you can achieve. For example, if a single thread acts as the writer program, then with a other threads acting as readers, everything works. Either the process has a read lock or it has a write lock and only the writer or one of the reader thread can access the file. Where things go wrong is if two threads try to write to the same area of the file. In this case the process will have a write lock on the region and both threads will attempt to write at the same time. Put simply, you cannot stop multiple threads modifying the same region of the file at the same time. If you need to use locks with threads and you want to protect your program from a loss of locks if a file is closed, you need to use open file description locks. This is a Linux-only facility; to use it you simply change the commands used in the fcntl call: F_OFD_SETLK - acquire or release lock non-blocking F_OFD_SETLKW - as F_OFD_SETLK but blocking, returns -1 if interrupted F_OFD_GETLK - test to see if there is a lock of the type specified. In the remainder of the chapter but not in this extract
Summary
Now available as a paperback or ebook from Amazon.Applying C For The IoT With Linux
Also see the companion book: Fundamental C <ASIN:1871962609> <ASIN:1871962617> Related ArticlesRemote C/C++ Development With NetBeans Getting Started With C/C++ On The Micro:bit To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.
Comments
or email your comment to: comments@i-programmer.info |
|||||
Last Updated ( Monday, 24 August 2020 ) |