The self directory

Processes can be selected by explicit reference to their PIDs, but the data of the currently running process can be accessed without knowing PID by selecting the /proc/self directory — the kernel then automatically determines which process is currently running. For example, outputting the contents of /proc/self/map with cat produces the following result:

[email protected]> cat /proc/self/cmdline cat/proc/self/cmdline

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

[email protected]> perl -e 'open(DAT, "< /proc/self/cmdline"); print(<DAT>); close(DAT);' perl-eopen(DAT, "< /proc/self/cmdline"); print(<DAT>); 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

The self case is handled first in proc_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 defined proc_self_inode_operations instance 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,

The self directory 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 to which process 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 in proc_self_inode_operations whose implementations require just a few lines:

fs/proc/base.c static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen) {

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 into tmp. For proc_self_readlink, it holds the thread group ID of the currently running process, which is read using current->tgid. For proc_self_follow_link, the PID 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 at www.nyx.net/~gthompso/quine.htm.

with the classic PID for single-threaded processes. The sprintf function, with which we are familiar from the C programming of userspace applications, converts the integer number into a string.

The remaining work is then delegated to standard virtual filesystem functions that are responsible for directing the lookup operation to the right places.

Continue reading here: Selection According to PID

Was this article helpful?

0 0