Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 10: Filesystems without Persistent Storage


automatically determines which process is currently running. For example, outputting the contents of
/proc/self/mapwithcatproduces the following result:

wolfgang@meitner>cat /proc/self/cmdline
cat/proc/self/cmdline

If a Perl script is used to read the file, the following information is obtained.

wolfgang@meitner>perl -e ’open(DAT, "< /proc/self/cmdline"); print(); close(DAT);’
perl-eopen(DAT, "< /proc/self/cmdline"); print(); close(DAT);


Because the script was passed to the Perl interpreter as a command-line parameter, it reproduces
itself — in fact, it is almost a self-printing Perl script.^1

Theselfcase is handled first inproc_pid_lookup, as the code flow diagram in Figure 10-4 shows.

When a new inode instance is generated, only a few uninteresting standard fields need to be filled. Of
prime importance is the fact that the statically definedproc_self_inode_operationsinstance is used
for the inode operations:

fs/proc/base.c
static struct inode_operations proc_self_inode_operations = {
.readlink = proc_self_readlink,
.follow_link = proc_self_follow_link,
};

Theselfdirectory is implemented as a link to a PID-specific directory. As a result, the associated inode
always has the same structure and does not contain any information as towhichprocess it refers. This
information is obtained dynamically when the link target is read (this is necessary when following or
reading a link, e.g., when listing the entries of/proc). This is precisely the purpose of the two functions
inproc_self_inode_operationswhose implementations require just a few lines:

fs/proc/base.c
static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
{
char tmp[30];
sprintf(tmp, "%d", current->tgid);
return vfs_readlink(dentry,buffer,buflen,tmp);
}

static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
{
char tmp[PROC_NUMBUF];
sprintf(tmp, "%d", task_tgid_vnr(current));
return ERR_PTR(vfs_follow_link(nd,tmp));
}

Both functions generate a string intotmp.Forproc_self_readlink, it holds the thread group ID of the
currently running process, which is read usingcurrent->tgid.Forproc_self_follow_link,thePID
that the current namespace associates with the task is used. Recall from Chapter 2 that PIDs are not
unique across the system because of namespaces. Also remember that the thread group ID is identical

(^1) Writing programs that print themselves is an old hacker’s delight. A collection of such programs in a wide variety of high-level
languages is available atwww.nyx.net/~gthompso/quine.htm.

Free download pdf