The Linux /proc Filesystem as a Programmers' Tool
June 17th, 2005 by Joshua Birnbaum in
One of the best investments in time that a person with a keen interest in operating systems can make is to explore them from multiple angles. Operating system installation and configuration can go a long way toward solidifying the concepts that one reads about in system administration and networking texts. Electronic references in the form of system manual (man) pages and the Linux info(1) facility are available for instant consultation. groups.google.com, with its archive of 20-plus years of Usenet postings, can provide expert guidance on issues ranging from DNS configuration to memory interleaving. However, I feel another approach is singularly unique when it comes to exploring operating systems--programming them.
My entry into systems programming was guided by my desire to understand further the operating systems I was working with daily as a contract UNIX and, later, Linux system administrator. The result of this was ifchk, a packet sniffer detector I wrote in C and released in June of 2003. ifchk initially was written under IRIX and then ported to Linux, mostly under the 2.4 kernel. The current ifchk revision, beta 4, recently was released and beta 5 is on the way.
My work on ifchk has allowed me to examine programmatically several areas of operating system functionality. Examples include the Linux netlink(7) and rtnetlink(7) facilities, device control--that is, network interfaces--via ioctl(2), signals and proc, the process filesystem. Proc and its ability to display a wide array of data concerning the runtime state of a system are the focus of our discussion here.
Before we begin to talk about the proc filesystem as a programming facility, we need need to establish what it actually is. The proc filesystem is a pseudo-filesystem rooted at /proc that contains user-accessible objects that pertain to the runtime state of the kernel and, by extension, the executing processes that run on top of it. "Pseudo" is used because the proc filesystem exists only as a reflection of the in-memory kernel data structures it displays. This is why most files and directories within /proc are 0 bytes in size.
Broadly speaking, a directory listing of /proc reveals two main file groups. Each numerically named directory within /proc corresponds to the process ID (PID) of a process currently executing on the system. The following line of ls output illustrates this:
dr-xr-xr-x 3 noorg noorg 0 Apr 16 23:24 19636
Directory 19636 corresponds to PID 19636, a current bash shell session. These per-process directories contain both subdirectories and regular files that further elaborate on the runtime attributes of a given process. The proc(5) manual page discusses these process attributes at length.
The second file group within /proc is the non-numerically named directories and regular files that describe some aspect of kernel operation. As an example, the file /proc/version contains revision information relevant to the running kernel image.
Proc files are either read-only or read-write. The /proc/version file above is an example of a read-only file. Its contents are viewable by way of cat(1), and they remain static while the system is powered up and accessible to users. Read-write files, however, allow for both the display and modification of the runtime state of the kernel. /proc/sys/net/ipv4/ip_forwarding is one such file. Using cat(1) on this file reveals if the system is forwarding IP datagrams between network interfaces--the file contains a 1--or not--the file contains a 0. In echo(1)ing 1 or 0 to this file, that is, writing to the file, we can enable or disable the kernels ability to forward packets without having to build and boot a new kernel image. This works for many other proc files with read-write permissions.
Readers are invited to explore the /proc directory of an available system and consult the proc(5) manual page to solidify their understanding of the above discussion.
With the above foundation in place, we now turn our attention to using the contents of /proc to examine programmatically an aspect of the running kernel. A word of note: although the sample file ifmetric.txt discussed below contains all of the code we are referencing, additional understanding can be gleaned by downloading and building ifchk and by walking through its code, via gdb(1).
One area of ifchk functionality deals with the display of counters that describe transmitted and received packets across all network interfaces attached to the system. ifchk does this by parsing and processing /proc/net/dev. Although the file contains all manner of statistics concerning network interfaces, we are interested mainly in the extraction of packet count data.
ifMetric() is the function that implements all of the above functionality. It can be found in the file, ifmetric.txt, that is excerpted below. ifMetric() also can be found within the ifchk distribution in ~/ifchk-0.95b4/linux.c.
The ifMetric() function is defined as follows:
int ifMetric( struct ifList *list );
*list is a pointer to the head of a linked list of structs of type ifList. Each node describes characteristics of an interface present on the system. ifList is defined in ~/ifchk-0.95b4/linux.h as such:
struct ifList
{
int flags; /* Interface flags. */
char data[DATASZ]; /* Interface name/unit number, e.g., "eth0". */
struct ifList *next; /* Pointer to next struct ifList. */
};
In getting started, our first inclination might be to open the /proc/net/dev file and begin searching for the relevant packet count data. There is, however, some file reconnaissance work to be done in between these two steps. Program failure due to maliciously crafted input is a staple of security advisories these days. We cannot make any assumptions about external program input, regardless of its source. As we will see, there is another security-related reason why we sequence the above file access operations as we do. With all of the above in mind, let's get to work.
540 int ifMetric( struct ifList *list )
541 {
542 struct stat fileAttrs; /* /proc/net/dev file
attributes. */
543 struct stat linkAttrs; /* /proc/net/dev link
attributes. */
544 char *filePath = NULL; /* Path to /proc/net/dev
file. */
545 FILE *file = NULL; /* File pointer for
fopen(). */
546 int status = 0; /* /proc/net/dev file
close() status. */
547 char buf[1024] = ""; /* Character buffer. */
548 struct ifList *cur = NULL; /* Current node in
linked list. */
549 int conv = 0; /* sscanf() string match
count. */
550 long long rxPackets = 0; /* Received packet
count. */
551 long long txPackets = 0; /* Transmitted packet
count. */
552 char *delim = NULL; /* Ptr to matched
character in string. */
553 unsigned int ifIndex = 0; /* Interface index. */
554 mode_t mode = 0; /* /proc/net/dev file
permissions. */
558 cur = list;
559 if( cur -> data == NULL )
560 {
561 fprintf( stderr, "ifchk: ERROR: interface list is empty\n"
);
562 return (-1);
563 }
564 filePath = "/proc/net/dev";
565 if( ( lstat( filePath, &linkAttrs ) ) != 0 )
566 {
567 perror( "lstat" );
568 return (-1);
569 }
570 if( S_ISLNK( linkAttrs.st_mode ) )
571 {
572 fprintf( stderr, "ifchk: ERROR: /proc/net/dev is a symbolic
link\n" );
573 return (-1);
574 }
Before we open /proc/net/dev, we must be sure that the file is not actually a symbolic link (symlink). If passed a symlink, which our proc file shouldn't be, fopen(3) would follow that link to what it points to. Our subsequent fstat(2) call, using the file descriptor returned by fopen(3), would return data on the wrong file. To protect against this, we lstat(2) /proc/net/dev and then check if it is a symlink, by using the S_ISLNK POSIX macro. If S_ISLNK finds a symlink, we print an error message with fprintf(3) and return -1, signifying failure. Otherwise, we continue on.
578 if( ( file = fopen( "/proc/net/dev", "r" ) ) == NULL )
579 {
580 perror( "fopen" );
581 return (-1);
582 }
Presuming that S_ISLNK didn't find a symlink, we next open the /proc/net/dev file by calling fopen(3). If our call succeeds, fopen(3) returns a FILE pointer for use with future operations on /proc/net/dev. If our call fails, we call perror(3) and return -1, signifying failure. Notice that we check the return value of the fopen(3) call. Checking function return values is critical, to say the least.
586 if( ( fstat( fileno( file ), &fileAttrs ) ) != 0 )
587 {
588 perror( "fstat" );
589 return (-1);
590 }
One of the first things I think about when writing code is how it might fail. Additionally, I also think about how I can minimize the impact of failure by failing gracefully through programming defensively. Doing this is crucial, I feel, especially in light of the heightened state of concern regarding system security and the potential impact of security compromises.
Given this, we must continue to probe /proc/net/dev, via fstat(2), to see if the file exhibits what constitutes plausible attributes for a read-only proc file. These attributes include its file type outside of being a symlink, size in bytes and disk blocks, user and group ownership status and permissions. The following attribute criteria is based on what I have seen for /proc/net/dev on the bulk of Linux systems I have worked on.
file type: regular size in bytes: 0 size in blocks: 0 file ownership: root:root file permissions: 0444 (-r--r--r--)
From the perspective of a default ifchk build, our /proc/net/dev file must conform to the above attribute criteria. However, a simple modification to the ifchk code, if required, can accommodate site policies and so on that differ from the above.
If successful, fstat(2) fills in fileAttrs with /proc/net/dev attributes. In the event of failure, we relay a descriptive error message to the user via a call to perror(3). We then return -1, signifying failure. Examining fileAttrs in gdb(1), we see that fstat(2) has the following to say about /proc/net/dev (some struct members were removed from GDB output, as they did not add to the discussion):
(gdb) print fileAttrs
$1 = {..., st_mode = 33060,
st_uid = 0,
st_gid = 0,
st_size = 0,
st_blocks = 0, ...}
In the discussion above, I alluded to an additional security-related reason behind the sequencing of our /proc/net/dev access procedures. To recap, our handling of /proc/net/dev--outside of lstat(2) and our not wanting to follow symlinks--currently consists of calling fopen(3) followed by fstat(2). We just as easily could have achieved the same result via a call to stat(2), not fstat(2), and then fopen(3), as stat(2) returns the same file attribute data as fstat(2) does. So, why use the former sequence--fopen(3), fstat(2)--instead of the latter one--stat(2), fopen(3)? Because we wish to avoid a race condition. The stat(2), fopen(3) sequence creates the possibility that the file we referenced during the stat(2) call could have been substituted with another one with possibly different attributes or even different contents once we got to the fopen(3) call. In this situation, we'd think we were calling fopen(3) on the same file we just called stat(2) on but, alas, not. The danger of this, I think, is obvious.
591 if( ( ( linkAttrs.st_ino ) != ( fileAttrs.st_ino ) ) ||
592 ( ( linkAttrs.st_dev ) != ( fileAttrs.st_dev ) ) )
593 {
594 fprintf( stderr, "ifchk: ERROR: /proc/net/dev file
attribute inconsistency\n" );
595 return (-1);
596 }
As an added measure in checking that we are working with the proc file we think we are, we compare the inode numbers, st_ino, and resident filesystem, st_dev, that both lstat(2) and fstat(2) reported in their /proc/net/dev attribute checks. If all is well, the value of linkAttrs.st_ino should equal fileAttrs.st_ino and the value of linkAttrs.st_dev should equal the the value of fileAttrs.st_dev. If we're okay here, we continue on. If not, we report an attribute consistency error via fprintf(3) and return -1, signifying failure.
600 if( ! ( S_ISREG( fileAttrs.st_mode ) ) )
601 {
602 fprintf( stderr, "ifchk: ERROR: /proc/net/dev is not a
regular file\n" );
603 return (-1);
604 }
S_ISREG is a POSIX macro that checks to see if its argument is a regular file and not, say, a directory. If it is, we continue on. If not, we print an error message via fprintf(3), and return -1, signifying failure. At this point, you might be asking why we need the lstat(2)/S_ISLNK symlink test above if we're testing for file type here. Referring back to the symlink test above should help to answer that question.
608 if( ( ( fileAttrs.st_size ) || ( fileAttrs.st_blocks ) ) != 0 )
609 {
610 fprintf( stderr, "ifchk: ERROR: /proc/net/dev file size is
greater than 0\n" );
611 return (-1);
612 }
Is /proc/net/dev 0 bytes in length and does it occupy 0 disk blocks? If we see zero for both byte count and disk blocks, we continue on. If not, we print an error message via fprintf(3) and return -1, signifying failure. Notice that only one of the two file tests has to fail for the program to fail.
616 if( ( ( fileAttrs.st_uid ) || ( fileAttrs.st_gid ) ) != 0 )
617 {
618 fprintf( stderr, "ifchk: ERROR: /proc/net/dev is not owned
by UID 0, GID 0\n" );
619 return (-1);
620 }
Is /proc/net/dev owned by user root and group root? Here again, only one of the two tests has to fail for the program to fail and return -1, signifying failure.
624 if( ( mode = fileAttrs.st_mode & ALLPERMS ) != MODEMASK )
625 {
626 fprintf( stderr, "ifchk: ERROR: /proc/net/dev permissions
are not mode 0444\n" );
627 return (-1);
628 }
Is /proc/net/dev mode 0444--read-only user, group and other? ALLPERMS, defined in the /usr/include/sys/stat.h system header file, is a mask that defines all file permissions, or mode 07777. MODEMASK, defined within ~/ifchk-0.95b4/linux.h, is a mask that defines user, group and other read permissions, or mode 0444.
By bitwise ANDing fileAttrs.st_mode with ALLPERMS and then comparing that result to MODEMASK, we can see if /proc/net/dev is mode 0444. If it is, we continue execution. If not, we print an error message via fprintf(3) and return -1, signifying failure. This concludes our /proc/net/dev file attribute tests. However, before ifchk can work with the file, we must examine its internal contents.
Testing the internal content structure or format of /proc/net/dev required that I define a criteria under which ifchk would accept or reject the proc file. As Linux has progressed, the number of fields--bytes, packets, errs--in /proc/net/dev have changed. All of the /proc/net/dev files I have seen share an identical content structure to the file below; output to far right was truncated, due to space limitations:
Inter-| Receive | Transmit ...
face |bytes packets errs drop fifo frame compressed multicast|bytes ...
lo: 34230 586 0 0 0 0 0 0 34230 ...
eth0:22476180 208548 0 0 0 0 0 0 52718375 ...
Two lines of headers are followed by lines of per-interface statistics. Older versions of the file do not contain the compressed field. In the name of simplicity, I decided that /proc/net/dev files that did not contain this field would be rejected by ifchk. With that foundation in place, we now begin the process of examining /proc/net/dev internally.
632 if( ! fgets(buf, sizeof( buf ), file) )
633 {
634 perror( "fgets" );
635 return (-1);
636 }
637 if( ! fgets(buf, sizeof( buf ), file) )
638 {
639 perror( "fgets" );
640 return (-1);
641 }
645 if( ( strstr( buf, "compressed" ) ) == NULL )
646 {
647 fprintf( stderr, "ifchk: ERROR: /proc/net/dev header format
is not supported\n" );
648 return (-1);
649 }
We make two identical fgets(3) calls in a row to read the first and second line of headers from /proc/net/dev. Each fgets(3) call results in an overwrite of what previously was in buf. As a result, buf now contains the second header line. We then check to see if the second line of headers contains the compressed field.
If compressed is located in buf, our strstr(3) call succeeds and we have what looks like a usable /proc/net/dev file. If compressed cannot be located in buf, we print an error message via fprintf(3) and return -1, signifying failure. With this, all of our testing, which began by looking at file attributes, is done.
The remainder of our counter output code takes the form of a while loop that handles the processing and output of data for each interface. It iterates as many times as there are interfaces on the system.
653 printf( "*** Network Interface Metrics ***\n" );
654 printf( "Name Index RX-OK TX-OK\n" );
659 while( fgets( buf, sizeof( buf ), file ) )
660 {
664 if( ( strstr( buf, cur -> data ) ) != NULL )
665 {
666 delim = strchr( buf, ':' );
670 if( *( delim + 1 ) == ' ' )
671 {
672 conv = sscanf( buf,
673 "%*s %*Lu %Lu %*lu %*lu %*lu %*lu %*lu %*lu %*Lu
%Lu %*lu %*lu %*lu %*lu %*lu %*lu",
674 &rxPackets, &txPackets );
675 }
676 else
677 {
678 conv = sscanf( buf,
679 "%*s %Lu %*lu %*lu %*lu %*lu %*lu %*lu %*Lu %Lu
%*lu %*lu %*lu %*lu %*lu %*lu",
680 &rxPackets, &txPackets );
681 }
682 }
We call fgets(3) to read the next line of the /proc/net/dev file into buf. We then call strstr(3) to check that the interface name in cur -> data, ifmetric.txt:558:, matches the interface name in the /proc/net/dev line we just read in. Interface statistics lines in /proc/net/dev begin with an interface name, followed by a colon followed by a count of bytes received on that interface. In some cases, there is whitespace between the colon and the received bytes count, for example, eth0: 6571407, and in other cases, not, eth0:12795779).
In order to maintain uniform column output in either of these cases, we use pointer arithmetic to test for the existence of this white space. If whitespace does exist, we enter the if() statement on line 670, whose sscanf(3) format specifiers deal with it. If there is no whitespace, we enter the else block on line 676. These format specifiers deal with the lack of whitespace.
In either case, the counters for both received and transmitted packets are copied by sscanf(3) from /proc/net/dev to the variables rxPackets and txPackets for later output.
683 else
684 {
685 fprintf( stderr, "ifchk: ERROR: current metrics do not
describe current interface %s\n",
686
cur -> data );
687 return (-1);
688 }
If we compare the interface name in cur -> data to the name in /proc/net/dev and find a mismatch, we print an error message via fprintf(3) and return -1, signifying failure.
692 if( conv != 2 )
693 {
694 fprintf( stderr, "ifchk: ERROR: /proc/net/dev parse
error\n" );
695 return (-1);
696 }
If successful, our above sscanf(3) call returns the number of matched items. As a result, the variable conv should equal 2 for rxPackets and txPackets. If not, we print an error message via fprintf(3) and return -1, signifying failure.
697 if( ( ifIndex = if_nametoindex( cur -> data ) ) == 0 )
698 {
699 perror( "if_nametoindex" );
700 return (-1);
701 }
Next, we call if_nametoindex(), passing it the interface name in cur -> data and, if successful, store the integer interface index in ifIndex. If the call fails, we handle it as usual. An interface index is a positive integer that the kernel assigns to each interface present on the system.
702 printf( "%-7s %-7d %-13Lu %-13Lu\n", cur -> data,
ifIndex, rxPackets, txPackets );
703
704 conv = 0;
705 if( cur -> next != NULL )
706 {
707 cur = cur -> next;
708 }
709 }
Having built a line of counter output for the current interface, we print it. We then return to the beginning of the while loop and continue or, having reached our loop termination condition, exit the loop.
713 if( ( status = fclose( file ) != 0 ) )
714 {
715 perror( "fclose" );
716 return (-1);
717 }
721 if( ( writeLog( LOGINFO, pw -> pw_name, NULLSTATE ) ) != 0 )
722 {
723 fprintf( stderr, "ifchk: ERROR: could not pass logging
message to syslogd\n" );
724 return (-1);
725 }
726 return (0);
727 }
Having exited the while loop, we call fclose(3), which corresponds to our fopen(3) call on line 578. We then call our logging function to log that an interface counter dump was performed.
With all processing done, ifchk produces the following packet count output on a system with two interfaces:
*** Network Interface Metrics *** Name Index RX-OK TX-OK lo 1 104 104 eth0 3 1280903 1162571<--. ^ ^ ^ | | | |[from /proc/net/dev]-----' | | | |[from if_nametoindex()] | |[from cur -> data]
The process filesystem provides all who make use of it with a wealth of system-level information. The ability to manipulate all manners of runtime state information by using file-level system calls and commands, such as cat(1) and echo(1), make proc a high priority candidate for inclusion in anyone's Linux toolkit.
Subscribe now!
Recently Popular
| Building a Call Center with LTSP and Soft Phones | Aug-25-05 |
| Why Python? | May-01-00 |
| An Open Video to HP | Jul-02-08 |
| Boot with GRUB | May-01-01 |
| Data Manipulation with Sprog | Jul-03-08 |
| Chapter 16: Ubuntu and Your iPod | Aug-30-06 |
Featured Video
From the Magazine
July 2008, #171
Heard of the Web? If not, read on. This month we talk with Matt Mullenweg about WordPress. If you want to get your hands dirty in Web code, take a look at the rest of our feature articles on WebKit, Dojo and OpenLaszlo.
In the rest of the issue, you'll find articles on OpenID, RDFa and Quanta Plus.
Kyle Rankin puts a new spin (as in "no" spin SSD) on hard drives and
also tells you how to migrate to that new disk (spinning or not).
Mick Bauer continues his series on customizing live CD's.
And, James Gray gives us a feel for the state of Linux in the enterprise.
After all that, you may need some TV time. If so, check out our review
on how to make that digital TV tuner card work in your Linux box.
Delicious
Digg
Reddit
Newsvine
Technorati






Only user space /proc file system description
On November 6th, 2006 Anton (not verified) says:
I've found this article because I work with some GPL published kernel code of MIPS-based device. What I'm trying to do is to interact with /proc file system to hack the hardaware. Since the application is not GPL-ed, only the kernel, I can only play with the kernel source code. But everything on the article is from user space point of view. Anyway, great introduction to /proc. Thanks
sscanf vs. hash tables
On August 20th, 2005 Lincoln (not verified) says:
I've just started to do more detailed programming with Linux and have also seen proc files processed with GHashTables. This seems like it would work very with for stuff that lists off stuff in the "Desc: value" format. Later you can just do lookups on the hash table. I realize that that would be using a glib.h stuff, and is somewhat tied to gnome, but for now, lets not debate that part, and I'm working on gnome projects. I just like to know if this is considered a valid way of processing the proc files. Thanks.
Lincoln
Damn, parsing proc files is j
On June 29th, 2005 Walter Stryder (not verified) says:
Damn, parsing proc files is just so much easier with Perl, and can be used to produce real nice output.
Re: Damn, parsing proc files is j
On July 3rd, 2005 Josh Birnbaum (not verified) says:
> Damn, parsing proc files is just so much easier with Perl,
Originally, ifchk was a perl(1) wrapper around netstat(8) and ifconfig(8) (minus about 60% of it's current functionality).
I decided to rewrite and extend the program in C for several reasons. One was runtime performance.
Also, if I had written the Linux proc routines in perl(1), that would have required a glue layer to bind the C code to it. I don't want this added overhead, runtime or otherwise.
Also, consider systems that, as a matter of policy, do not/must not have a perl(1) interpreter installed. A firewall is a good example of this.
In my opinion, these systems should be loaded with the bare minimum to allow them to do their job. In this case, filtering packets, doing NAT, etc.
What I'm getting at here is that the addition of programmatic tools, outside of a command interpreter, on such systems, is potentially dangerous. Such additions should be justified.
The proc routines that I provide in the article can be learnt by anyone willing to invest the time to do so. Additionally, an integral aim of the piece was to also provide some background on secure file access proceedures.
> and can be used to produce real nice output.
netstat(8), with its sscanf(3) calls, is also capable of formatted output.
perl c fussion
On December 29th, 2005 Anonymous (not verified) says:
man perlxstut
Time the result and see how bad it realy is. Because it's quite acceptable.
this article...
On June 20th, 2005 nikhil bharava (not verified) says:
It is clear, concise and very informative article. I enjoyed reading it alot. May be in coming times, there would be an indepth article on internals of certain working utilities in Linux like top.
nikhil
adapting to /proc/net/dev is easy
On June 19th, 2005 dean gaudet (not verified) says:
long before i learned about "sar -n DEV 5 0" i wrote a perl script which handles /proc/net/dev ... and adapting to differing numbers of fields was trivial.
http://arctic.org/~dean/scripts/bandwidth
it's also unclear to me why it matters if /proc/net/dev is a symlink... you're opening it read-only.
-dean
Re: adapting to /proc/net/dev is easy
On June 24th, 2005 Josh Birnbaum (not verified) says:
> http://arctic.org/~dean/scripts/bandwidth
Thanks for the URL. I'll check it out.
> it's also unclear to me why it matters if /proc/net/dev is a symlink... you're opening it read-only.
It has been my experience that /proc/net/dev has always been a zero byte file system object of type "file" (as opposed to a link/directory/fifo, etc).
The file access sequence I discuss in the article (lstat(2) -> fopen(3) -> fstat(2)) revolves around secure file access. What do I mean by that?
Well, consider this scenario. We first call stat(2) on the file, checking that it's zero bytes in size, chowned root:root, etc. If it passes these attribute tests, the file conforms to our expectations of a legit procfs object. We then call fopen(3) on the file and access its contents. But... there's a problem here. What if the file we stat(2)ed is _not_ the same file we then call fopen(3) on? That is, what if the file was replaced with a different file between the 2 calls? What I'm describing here is a possible file based race condition.
My point is that you *cannot* assume anything when dealing with external input.
In writing these routines, I was doing things like attempting file open operations on jpg images of Ferraris, MS Word docs, PDF files, gzipped tar archives, etc. I wanted to see how ifchk would deal with, what is, in the context of a legitimate /proc/net/dev file, garbage.
I hope this answers your question.
I'm curious what flavor of Li
On June 20th, 2005 mikebo (not verified) says:
I'm curious what flavor of Linux the author targeted. My make failed spectacularly under Fedora Core 3.
Re: I'm curious what flavor of Li
On June 20th, 2005 Josh Birnbaum (not verified) says:
> I'm curious what flavor of Linux the author targeted.
I did the ifchk Linux port mostly under the 2.4 kernel, from 2.4.22 onwards. I'm now running 2.4.31.
I'm currently trying to get access to a 2.6 system, to test on.
> My make failed spectacularly under Fedora Core 3.
Does the make output look like what's at the URL below:
http://www.noorg.org/ifchk/news/05032005b.html
Drop me a line at engineer@noorg.org and we'll work on this.
the nice /proc file system
On June 19th, 2005 Ioan Gartner (not verified) says:
- I think /proc is a great idea and somehow in line with UNIX overall philosophy (all is a "file").
- I regret sometimes that the layout and the values of the/proc file system change from one OS version to the other, but maybe evolution requires that, so that's ok with me.
- The real pity is not as much that its layout changes, but the fact that its documentation is often difficult to find and very poor.
- In that respect I think this article is a great idea, that is the reason I am here reading and commenting. Let's get out of "computer middle ages" of the 70es or 80es and recognize that after all an OS is just another application (I agree, a special one inn many respects, it has its own special objects to manipulate, has its own delicate "timing" conditions, it's sensitive HW interfaces etc....) but why so much "mistery" around it?
Re: the nice /proc file system
On June 19th, 2005 Josh Birnbaum (not verified) says:
> I think /proc is a great idea and somehow in line with UNIX overall philosophy (all is a "file").
This is one of the things that really stood out for me when I started working with Linux. I can now access in-kernel structures as if they were a text file. cat(1), less(1), fopen(3), fstat(2) on a proc file. No problem.
> I regret sometimes that the layout and the values of the/proc file system change from one OS version to the other, but maybe evolution requires that, so that's ok with me.
I comment on this, from within the context of sscanf(3), below.
> The real pity is not as much that its layout changes, but the fact that its documentation is often difficult to find and very poor.
This is where the Usenet archives shine. You can really piece alot together by sifting through the archives at groups.google.com. It's a _very_ powerful resource.
> In that respect I think this article is a great idea,..
Thank you. I'm glad you enjoyed it. I certainly had alot of fun writing it.
> ...but why so much "mistery" around it?
The more exploration one does, the more the mystery lessens. This is what I was getting at at the beginning of the article. Systems programming is like being able to view the internals of a running car engine, from all angles, in real time. That's enticing. And, like Usenet, powerful.
Windows has /proc, too
On June 18th, 2005 mangoo (not verified) says:
In Windows, there is a Windows Registry instead of /proc (more or less).
For those more familiar with Linux - it is possible to view and edit the registry in a /proc-like mode.
All it takes is installing Cygwin on a Windows machine.
Uh, no
On June 20th, 2005 Anonymous (not verified) says:
The Windows Registry is NOTHING like /proc. /proc gives you real time access to kernel parameters and the resources of running processes. /proc exists entirely in memory.
The Windows Registry, on the other hand, is a database of configuration paramaters. It's NOT real time, it does not contain info on running processes, and it does not give access to Windows kernel runtime parameters.
They are nothing alike.
> Before we begin to talk abo
On June 17th, 2005 Matt (not verified) says:
> Before we begin to talk about the proc filesystem as a programming
> facility, we need need to establish what it actually is.
The proc filesystem should be used as a programming facility. There are system calls for the same info. The format of the items in /proc can change from one kernel version to the next. Not all systems have /proc mounted. Also, not at flavours of Unix support /proc.
This article is a bad idea.
Re: The Linux /proc Filesystem as a Programmers' Tool
On June 18th, 2005 Josh Birnbaum (not verified) says:
> The proc filesystem should be used as a programming facility.
I agree.
> There are system calls for the same info.
Parsing proc files in /proc is a common way of accessing
in-kernel structures (netstat(8) and ifconfig(8) do this).
Sifting through the comp.os.linux.development.{system,apps}
Usenet group archive illustrates this.
> The format of the items in /proc can change from one kernel
> version to the next.
The programmer has to take care when dealing with conversion
specification in sscanf(3) calls, etc. He/she has to understand
the format of the proc object that is to be scanned.
> Not all systems have /proc mounted.
That's ok. This is where function return value checks are so important. The lstat(2) call in the article code (line 565)
returns error if it can't get to /proc/net/dev and we exit
gracefully.
> Also, not at flavours of Unix support /proc.
I wrote this piece from the perspective of the Linux system.
> This article is a bad idea.
Thanks for your feedback.
I just need a tool to mon the process
On September 20th, 2007 libbyliugang.cn (not verified) says:
I just need a tool to mon the process.
But the way to do this is different between WIN/UNIX/LINUX.
In most unix,such as AIX,HP-UX(RX),SUN-Soloar,there are some syscall function to use. Win has the same thing.But in linux, I have found them for long time,but the result is I must parse the /proc file myself, and the format is defferent between defferent version of Linux-Kernel....
These system api is very usefull and very importent,for a large system.
May be we need a standerd of Linux proc filesystem, or a new project to do these.
Not always a bad idea
On June 18th, 2005 Michael Jastram (not verified) says:
This article is a bad idea.
You can't generalize that. For instance, most firewall shell scripts use the /proc file system, which is perfectly legitimate. The question is how far you want to push it, and the author is pushing it quite far.
Ultimately, this goes back to the "right tool for the right job" philosophy. And the /proc filesystem definitely has its place in the toolbox.
a tool to program /proc/sys
On June 17th, 2005 Anonymous (not verified) says:
Here's a tool that lets you program and experiment with your /proc/sys run-time variables without having to deal with cat/echo time. It's ncurses based and, therefore, very fast.
http://freshmeat.net/projects/lkcp