Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the size of /proc/%u/fd/%u

Tags:

c

linux

How much size do I need to allocate for /proc/%u/fd/%u?

In strace code they allocated char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];

I didn't understand the calc , how did they calc this size?

like image 634
MicrosoctCprog Avatar asked Jan 25 '23 19:01

MicrosoctCprog


2 Answers

That may seem a rather bizarre way to do it, but it works (see below). They're assuming that you'll need no more than 2 + 3n characters for both the process ID and file descriptor, where n is the number of bytes in an integer (2 because the %u will be replaced, 3n because of the sizeof component).

It does actually work, as per the following chars/int values (for 8-bit char), formula results, and the maximum unsigned int that will come from it:

chars/int  sizeof(int) * 3 + 2       max value
---------  -------------------  --------------------
        1                    5                   255 (3/5 needed)
        2                    8                 65535 (5/8 needed)
        4                   14            4294967296 (10/14)
        8                   26  18446744073709551616 (20/26)
       16                   50           3.3 * 10^38 (39/50)

You can see that the storage allocated keeps up with the storage required, to the point where you could just as easily use:

char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int) * 3 - 2];
//                                              add this ^^^

And it will also work for char sizes beyond eight bits as well since doubling the bits in a value at most doubles the number of decimal digits (the table shows this with the needed size: 3, 5, 10, 20, 39, ...). That, combined with the fact that the int doubles in size as well, means there will always be enough space.


You may think that, for safety and portability, you could actually get the maximum PID and process file descriptor respectively from /proc/sys/kernel/pid_max and /proc/<pid>/limits (programatically) and use that to dynamically allocate enough space to hold the information:

pax:~> cat /proc/sys/kernel/pid_max
32768
pax:~> cat /proc/self/limits | awk '$1$2$3=="Maxopenfiles"{print $5}'
4096

Hence the first %u would need 5 characters and the second four characters.


Or, you could just allocate 20 characters for each on the likely case that you won't see 66-bit PIDs or FDs anytime in the near future :-) You could still check against the procfs files, if only to exit gracefully if they were too large.


But, to be honest, both of those are overkill, since you may already have a thing that's meant to provide the limit on file paths, PATH_MAX (see limits.h), for Linux. It's probably okay to use that and wear the minimal wastage. And, if you don't have that, you could either get the value from maximum length with a call to pathconf(). Or choose a sensible default (say, 60 characters), then just use snprintf to detect if the actual path was longer than your buffer, and exit gracefully.

If you really wanted to use the optimal method for minimal storage (i.e., you think a PATH_MAX of 4K is too much wastage) then, by all means, use the strace method, but with two subtracted as per my earlier comment(a).


(a) If you're going to worry about 4K here and there, you may as well do it fully :-)

like image 152
paxdiablo Avatar answered Jan 29 '23 02:01

paxdiablo


The best answer is, replace this calculation for MAX_PATH (include <limits.h>) that makes your code to more cleaner and portable.

like image 20
paramikoooo Avatar answered Jan 29 '23 02:01

paramikoooo