- Linux system programming: Open file, read file and write file
- Configuring your environment
- open(), read() and write() system calls
- How to use the Linux ‘lsof’ command to list open files
- Linux lsof command background
- I assume you’re logged in as root
- Basic Linux lsof command examples
- Common lsof options
- Summary: Linux lsof examples
Linux system programming: Open file, read file and write file
This is my first article in what I’m hoping will be a series of articles on system programming for POSIX compliant operating systems with focus on Linux. Actually I’ve touched this topic a while ago when I wrote three articles about library programming on Linux (static libraries, dynamic libraries and dynamic libraries using POSIX API). In this series my goal is to go trough basics of Linux system programming from the easiest topics like open file, read file and file write to a bit more complicated things like Berkeley sockets network programming. So lets get started with environment setup and an example of program that copies source file into destination file using POSIX API system calls to demonstrate open(), read() and write() system calls on Linux operating system.
Configuring your environment
I’ll use my trustworthy Ubuntu Linux operating system but you can actually use any POSIX compliant operating system, the only difference will probably be that you will need to configure your environment differently. What we need to begin with Linux system programming is gcc compiler with related packages and POSIX related man pages. So here’s how to install this packages on Ubuntu based operating system:
sudo apt-get install build-essential manpages manpages-dev manpages-posix manpages-posix-dev
Basically that’s all you need to create serious system tools for Linux operating system. Later we will probably need some more libraries but we will install them when necessary.
open(), read() and write() system calls
Lets continue with our first system call open() whose purpose is to open file for reading or writing or to create new file. You should open it’s man page if you haven’t already done so using man 2 open command and read trough basics (2 is manual section number, use man man to read more about integrated manual section numbers). In the following example we also use read() and write() system calls to copy from one file descriptor to the other (both descriptors returned by open() system call) so it is wise to open their man pages as well ( man 2 read and man 2 write ). So here’s the example code for program that copies input file passed as first argument into output file passed as second argument:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/* ============================================================================ Name : sp_linux_copy.c Author : Marko Martinović Description : Copy input file into output file ============================================================================ */ #include #include #include #include #include #include #define BUF_SIZE 8192 int main(int argc, char* argv[]) { int input_fd, output_fd; /* Input and output file descriptors */ ssize_t ret_in, ret_out; /* Number of bytes returned by read() and write() */ char buffer[BUF_SIZE]; /* Character buffer */ /* Are src and dest file name arguments missing */ if(argc != 3){ printf ("Usage: cp file1 file2"); return 1; } /* Create input file descriptor */ input_fd = open (argv [1], O_RDONLY); if (input_fd == -1) { perror ("open"); return 2; } /* Create output file descriptor */ output_fd = open(argv[2], O_WRONLY | O_CREAT, 0644); if(output_fd == -1){ perror("open"); return 3; } /* Copy process */ while((ret_in = read (input_fd, &buffer, BUF_SIZE)) > 0){ ret_out = write (output_fd, &buffer, (ssize_t) ret_in); if(ret_out != ret_in){ /* Write error */ perror("write"); return 4; } } /* Close file descriptors */ close (input_fd); close (output_fd); return (EXIT_SUCCESS); }
If you have named this code file sp_linux_copy.c and if you want to name executable file sp_linux_copy to compile this program you would probably use something like this:
gcc -Wall -o sp_linux_copy sp_linux_copy.c
Then if your source file is named source_file.txt and if you want to name the destination file destination_file.txt you would run this program like this:
./sp_linux_copy source_file.txt destination_file.txt
Now lets go trough the code and explain tricky parts. First thing we must do is to include necessary header files. Man page of every system call tells you what header files you need to include to be able to use this system call. Second we will define constant we will use to define size of our buffer in bytes. Smaller buffer size will make our copy process longer but it will save memory. Next we open source and destination file descriptors, source with O_RDONLY to make it read only, destination with O_WRONLY | O_CREAT to make it writable and to create destination file with 0644 file system permission flags. In case of error we use perror() man 3 perror to print relatively user friendly error message.
Now we are ready to start copy process. We run read() and write() inside loop (because source file might be bigger than our buffer) to copy from one file into another. Important to notice is that write() is using number of bytes read from source file returned by read() so it would know how much to write into destination file. If number of bytes read (ret_in) and number of bytes written (ret_out) differ this indicates error so once again we use perror() to print out error description. At the end if all went well we do cleanup by closing both file descriptors and returning 0 (EXIT_SUCCESS) to indicate that program ended without errors.
That’s it for this introductory article on Linux system programming topic. In my next article I will show you few more examples on POSIX input/output and then move on to memory management related system calls.
How to use the Linux ‘lsof’ command to list open files
Linux “open files” FAQ: Can you share some examples of how to show open files on a Linux system — i.e., how to use the lsof command?
Linux lsof command background
The Linux lsof command lists information about files that are open by processes running on the system. The lsof command is an acronym for, “list of open files.” In this article I’ll share some lsof command examples.
I assume you’re logged in as root
One other note: In these examples I’ll assume that you’re logged in as the Unix/Linux root user. If not, you’re lsof command output may be significantly limited. If you’re logged in as a non-root user, either su to root, or use sudo to run these commands.
Basic Linux lsof command examples
Typing the lsof command by itself lists all open files belonging to all active processes on the system:
On my current macOS system, which has been running for a long time, this shows a lot of open files, 1,582 to be specific:
$ lsof | wc -l 1582
Note that I didn’t have to be logged in as the root user to see this information on my Mac system.
Adding the head command to lsof shows what some of this output looks like:
$ lsof | head COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME loginwind 32 Al cwd DIR 14,2 1564 2 / loginwind 32 Al txt REG 14,2 1754096 243026930 /System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow loginwind 32 Al txt REG 14,2 113744 3190067 /System/Library/LoginPlugins/FSDisconnect.loginPlugin/Contents/MacOS/FSDisconnect loginwind 32 Al txt REG 14,2 425504 117920371 /System/Library/LoginPlugins/DisplayServices.loginPlugin/Contents/MacOS/DisplayServices loginwind 32 Al txt REG 14,2 3144 3161654 /System/Library/ColorSync/Profiles/sRGB Profile.icc loginwind 32 Al txt REG 14,2 96704 242998403 /System/Library/PrivateFrameworks/MachineSettings.framework/Versions/A/MachineSettings loginwind 32 Al txt REG 14,2 51288 251253153 /private/var/folders/h5/h59HESVvEmG+3I4Q8lOAxE+++TI/-Caches-/mds/mdsDirectory.db loginwind 32 Al txt REG 14,2 724688 117923285 /System/Library/LoginPlugins/BezelServices.loginPlugin/Contents/MacOS/BezelServices loginwind 32 Al txt REG 14,2 329376 117923166 /System/Library/Extensions/IOHIDFamily.kext/Contents/PlugIns/IOHIDLib.plugin/Contents/MacOS/IOHIDLib
Common lsof options
As mentioned, these details go on for 1,582 lines, so it helps to have some way to weed through that output, whether that involves using the grep command, or some of the lsof options shown below.
This command lists all open files belonging to PID (process ID) 11925 :
$ lsof -p 11925
This command lists all open files belonging to processes owned by the user named «al»:
This command lists files that are open in the directory specified, but it does not descend into sub-directories:
$ lsof +d '/Users/al'
The next command lists files that are open in the directory specified, and also descends into sub-directories. Beware: this can take a very long time to run for large directory structures:
$ lsof +D '/Users/al'
Summary: Linux lsof examples
I hope these Linux lsof command examples have been helpful. As you can see, the lsof command can be used to generate a list of open files on your Unix and Linux system with a variety of different command line options for different circumstances.
For more information on the lsof command, please see the «Related» block on this page, follow this link to lsof command search results on this website, or leave a note in the Comments section below.