Applying C - File Descriptors |
Written by Harry Fairhead | |||||||||||||||||||||||||||||||||||||||
Monday, 24 August 2020 | |||||||||||||||||||||||||||||||||||||||
Page 1 of 4 There is the C way of working with files and there is the Linux way - sometimes you just need to use the Linux file descriptor. This extract is from my book on using C in an IoT context. 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> There is a standard C approach to files, but there is also a POSIX standard that is implemented in Linux/Unix and in many ways this is more general than the C file functions. The reason is that once you move beyond files stored on disks, suddenly it is the POSIX approach to files that becomes the natural one to use. Of course, the C file handling functions are mapped onto the native file functions of the operating system and in the case of the POSIX system these are based on the use of a file descriptor. In most cases, however, you are better off using the standard C file functions as they are robust, easy to use and buffered. In any particular implementation these functions are mapped to the file system calls that the operating system provides. The file pointer returned by fopen and used by the other file handling functions is actually a pointer to a structure that defines the file. However, this structure is supposed to be opaque in the sense that you are not supposed to make use of its internal structure, which may vary according to the operating system. What all this means is that the C standard library file handling is a uniform wrapper around the varying file handling facilities provided by the operating system. If you can avoid using anything else your programs will have the advantage of being portable. In this chapter it is assumed that you know the basics of file handling and, in particular, are familiar with the C standard file functions. A brief summary of the C file functions is given in the table below:
File DescriptorsThere are many occasions when you need to call functions that are provided by the operating system and if the call involves a file then it will generally need to be passed something that corresponds to the native way that the operating system works with files. While there is no overall standard for this, for Linux and other Unix-like operating systems we rely on POSIX. A POSIX-conforming operating system uses a file descriptor rather than a file pointer. A file descriptor is a simple int that is an index into an internal operating system table of open files. Each process has its own table and each such table references a globally held table of files. By default there are three predefined file descriptors: STDIN_FILENO STDOUT_FILENO STDERR which under Linux/Unix correspond to 0,1 and 2. What all of this means is that most programs running under Linux, or any POSIX operating system, sooner or later have to abandon the C standard way of working with files. This is both good and bad news. The bad news is, of course, that this is not as portable. The good news is that it is a lower-level way of working with files that makes it possible to do more, in particular they are not buffered. The final piece of good news is that the POSIX functions, defined in unistd.h and fcntl.h are very similar to the C standard library files. The open function, defined in fcntl.h: open(filename,flags, mode); opens the file and returns an int, the file descriptor. The flags and mode parameters control how the file is to be opened and file permissions to be set when the file is created. The flags are formed by the bitwise OR of one of: O_RDONLY open for reading only O_WRONLY open for writing only O_RDWR open for reading and writing. with any of the following optional arguments: O_APPEND append on each write O_CREAT create file if it does not exist O_TRUNC truncate size to 0. If you are creating a file you also have to supply the mode parameter. This is simply the Linux permissions code and, as this is usually presented to the end user in octal, you can also use octal. There are also a set of predefined macros that can be ORed together to set the permission you require. For example S_IRUSR sets the user read bit. |
|||||||||||||||||||||||||||||||||||||||
Last Updated ( Monday, 24 August 2020 ) |