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

  1. C,IoT, POSIX & LINUX
  2. Kernel Mode, User Mode & Syscall
  3. Execution, Permissions & Systemd
    Extract Running Programs With Systemd
  4. Signals & Exceptions
  5. Integer Arithmetic
  6. Fixed Point
  7. Floating Point
  8. File Descriptors
  9. The Pseudo-File System
    Extract: The Pseudo File System 
  10. Graphics
    Extract: framebuffer 
  11. Sockets
  12. Threading
    Extract  Condition Variables
    Extract  Deadline Scheduling
  13. Cores Atomics & Memory Management
  14. Interupts & Polling
  15. Assembler
    Extract: Assembler ***NEW

Also see the companion book: Fundamental C

<ASIN:1871962609>

<ASIN:1871962463>

<ASIN:1871962617>

<ASIN:1871962455>

ACcover

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 Directories

There 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
Isn’t mountable and is used to create pipes.

tmpfs
Usually mounted as /tmp/shm used to share memory areas.

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
MemTotal: 949444 kB MemFree: 250276 kB MemAvailable: 588716 kB Buffers: 94528 kB Cached: 355420 kB SwapCached: 0 kB Active: 454272 kB Inactive: 193148 kB

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 Name

As 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:

  • Working with GPIO
  • Accessing Memory
  • Memory Mapping Files
  • Shared Memory
  • Semaphore Locking

Summary

 

  • The general principle of “everything is a file” leads to the pseudo file system which wraps many hardware sources and sinks of data as files and folders.

  • From an IoT point of view the most important of the pseudo directories is sysfs which provides access to the GPIO.

  • Working with GPIO lines using sysfs is a matter of exporting the line you want to use and then using the folders and files created to manipulate it.

  • Sysfs has a reputation for being slow, but this is mainly due to the closing and reopening of files on each access. If you make use of fflush or file descriptors then it is much faster, although still slower than direct access to the GPIO.

  • To access memory directly with the cooperation of the memory management hardware you have to use the mem pseudo file. Reading and writing this file gives you direct access to memory.

  • Any file can be loaded into a process’s memory and accessed directly using pointers. This is faster than repeated disk accesses.

  • If the mem pseudo file is loaded into a process's memory then you can have direct access to a machine’s memory using pointers rather than file operations. This is the standard way of accessing memory-mapped I/O on most machines.

  • A memory mapped file can be shared between processes.

  • To lock a memory mapped file use a semaphore.

 

Related Articles

Remote C/C++ Development With NetBeans

Raspberry Pi And The IoT In C

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.

Banner


This Weekend Save On edX Training
29/11/2019

If you like a bargain you've probably been waiting for the Black Friday to Cyber Monday period to make all sorts of hardware purchases. We've discovered there are also substantial savings to be made o [ ... ]



Microsoft Tools Up For Voice Era
27/11/2019

Microsoft has released a public preview of a tool for building chatbots as well as revamping and renaming Microsoft Flow as Power Automate.


More News

graphics

 



 

Comments




or email your comment to: comments@i-programmer.info

 

 

 

Last Updated ( Monday, 12 August 2019 )