Applying C - The Pseudo File System |
Written by Harry Fairhead |
Monday, 22 July 2019 |
The pseudo file system is mysterious - well not really. It is the place that Linux/POSIX puts everything that you can access from user mode. The confusing part is that it all pretends to be a set of directories and files even though it isn't. 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> The idea that everything in Linux/Posix is a file doesn’t seem strange until you meet the pseudo file system – also sometimes called the synthetic file system. This is a file system designed to wrap hardware, drivers, system state and just about anything that isn’t a really a file, as a file. The pseudo file system has folders and files and you can generally work with these as if they were perfectly normal. You can read/write and even use seek to move to a position in such a file. Of course, exactly what you can and cannot do varies according to the object being wrapped as a file or folder. One of the big problems of the pseudo file system is that it is poorly documented and its behavior can vary a lot depending on the hardware it is implemented on. In this chapter we will look at the Linux pseudo file system. Unix and other operating systems have similar facilities, but there is no standard for the pseudo file system. The Linux Pseudo DirectoriesThere are a two well-known pseudo directories: procfs Usually mounted as /proc, contains a large number of directories concerned with the state of the system and has a subdirectory for every process running containing information about that process. sysfs Usually mounted as /sys, contains folders that expose the hardware and driver information. There are also some lesser known ones including: debugfs Usually mounted as /sys/debug, is used by debugging utilities. pipefs tmpfs It is also worth mentioning /dev which contains folders that correspond to device drivers of various sorts. This predates the sysfs file system and contains many pseudo directories that probably would be in sysfs if reinvented today. What can you do with these file systems? If the file is a wrapper for some status data then generally you can read it to find out the current values. For example, /proc/meminfo gives memory use statistics. You can open it and read it or just use the cat command: cat /proc/meminfo Most of the data is used by system utilities that report on the state of the system to the user. Another useful directory is /proc/iomem which lists the addresses and uses of the physical memory. That is: cat /proc/iomem will display a memory map for the device that you are working with. However, it doesn’t always contain all of the information you might hope for. For an example of a pseudo directory that you can read and write to, consider /sys/power/ which controls the power state of the machine. If you write any of the strings “disk”, “freeze” or “standby” to the file /sys/power/state then the machine will go into hibernation, suspend-to-idle and standby states. If it doesn’t support sleep states, the directory is missing. Notice that you can use C standard file handling or POSIX file handling to access pseudo files, but sometimes only POSIX will do. In particular, the POSIX file functions don’t buffer the data and this is sometimes what you need when writing to hardware. How do you find out what is available in the pseudo file systems? The answer is that you look it up in the man pages for the relevant file system. However, how well any given feature is implemented varies. Sometimes you will find features omitted, half-implemented or augmented. You simply have to look at the file system and try things out. Finding a PID by NameAs an example of the sort of things that the pseudo file system is used for, consider the question of how to find the PID of a program by name. That is, assuming that myProgram is running, what is its PID? At first thought it seems likely that there would be a syscall for this action, after all there is getpid which returns the PID of the calling program, and getppid, which returns the PID of the parent process. You can, however, search the documentation in vain as there is no predefined way to get a PID of a named process. The solution is to use the /proc pseudo directory. This contains a directory for each running process with a name given by the PID. Within this directory are files and other directories that give information about the process. If you consult the man page for /proc you will find a file called comm which gives the command name for the process i.e. what the user types on the command line to get the program running. You can also use the cmdline file to discover exactly what the user typed including arguments. So the method is to open the /proc directory and read each directory entry in turn - see the end of Chapter 8 for information on working with directories. This way we can step through the information on each process running in an effort to find the one with the required name. Each directory entry contains the PID of the process and this can then be used to construct a path to /proc/pid/comm where pid is the name of the directory entry corresponding to the process with that pid. You can then open this file and read it to discover the name of the process with that pid. If this is the name that you are looking for you have found the PID. The program is: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <sys/types.h> int main(int argc, char** argv) { struct dirent *direntry; char path[200]; char name[200]; FILE *fp; DIR *dir = opendir("/proc/"); while ((direntry = readdir(dir)) != NULL) { strcpy(path, "/proc/"); strcat(path, direntry->d_name); strcat(path, "/comm"); fp = fopen(path, "r"); if (fp != NULL) { fscanf(fp, "%s", name); printf("%s-%s\n\r", direntry->d_name, name); fflush(NULL); fclose(fp); } } closedir(dir); return (EXIT_SUCCESS); } Notice that we have not checked for buffer overruns for simplicity. It is also necessary to check that the constructed path does correspond to an openable file as as it could be a directory or "." say - hence the test if(fp!=NULL). The program simply prints the PID and the names of each process. You can easily use this example to construct a function that matches the name of each item against a target name and returns the PID. In the rest of the chapter:
Summary
Related Articles Remote 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, 12 August 2019 ) |