In Linux, there is a header file called <sys/utsname.h>. And there is a utsname structure which shall contain members below:
char sysname[] Name of this implementation of the operating system.
char nodename[] Name of this node within the communications
network to which this node is attached, if any.
char release[] Current release level of this implementation.
char version[] Current version level of this release.
char machine[] Name of the hardware type on which the system is running.
I'm curious about the letter "u, t, s", what do they mean?
I think it comes from the ancestor operating system where this syscall was already defined, so utsname means "Unix Time-Sharing System Name".
The full name for UNIX can be seen here:
http://cva.stanford.edu/classes/cs99s/papers/ritchie-thompson-unix-time-sharing-system.pdf
Related
On Linux, sched.h contains the definition of
int sched_rr_get_interval(pid_t pid, struct timespec * tp);
to get the time slice of a process. However the file shipping with OS X El Capitan doesn't hold that definition.
Is there an alternative for this on OS X?
The API's related to this stuff are pretty byzantine and poorly documented, but here's what I've found.
First, the datatypes related to RR scheduling seem to be in /usr/include/mach/policy.h, around line 155. There's this struct:
struct policy_rr_info {
...
integer_t quantum;
....
};
The quantum is, I think, the timeslice (not sure of units.) Then grepping around for this or related types defined in the same place, I found the file /usr/include/mach/mach_types.def, which says that the type struct thread_policy_t contains a field policy_rr_info_t on line 203.
Next, I found in /usr/include/mach/thread_act.h the public function thread_policy_get, which can retrieve information about a thread's policy into a struct thread_policy_t *.
So, working backwards. I think (but haven't tried at all) that you can
Use the thread_policy_get() routine to return information about the thread's scheduling state into a thread_policy_t
That struct seems to have a policy_rr_info_t sub-substructure
That sub-structure should have a quantum field.
That field appears to be the timeslice, but I don't know about the units.
There are no man pages for this part of the API, but this Apple Developer page explains at least a little bit about how to use this API.
Note that this is all gleaned from just grepping the various kernel headers, and I've definitely not tried to use any of these APIs in any actual code.
Given a function or variable run-time address, my code needs to find out the name and, if it's a variable, type information of the symbol. Or at least provide enough information for later, off-line extraction of the name (and type info).
It is Linux code and it is assumed debug information is available.
I tried to look into the ELF file format, binutils and all but the subject is huge, so I was hoping somebody can help me narrow the scope.
I can see the following types of solutions:
find the range of the code/data segments of the modules currently loaded in memory - HOW TO DO THAT ?. Save the address's module and segment name and offset in it's segment. Off-line then use binutils to find the symbol in the module's debug info - again, HOW TO DO THAT?
use some API/system services I do not know of to find the symbol and info at run-time - HOW?
Thank you in advance.
GNU libc provides a dladdr function for this exact purpose. However, it only works on functions, not variables.
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <dlfcn.h>
int dladdr(void *addr, Dl_info *info);
The function dladdr() takes a function pointer and tries to resolve
name and file where it is located. Information is stored in the
Dl_info structure:
typedef struct {
const char *dli_fname; /* Pathname of shared object that
contains address */
void *dli_fbase; /* Address at which shared object
is loaded */
const char *dli_sname; /* Name of symbol whose definition
overlaps addr */
void *dli_saddr; /* Exact address of symbol named
in dli_sname */
} Dl_info;
If no symbol matching addr could be found, then dli_sname and dli_saddr
are set to NULL.
dladdr() returns 0 on error, and nonzero on success.
Of course, usually I do this sort of thing from gdb, not within the program itself.
What you want to look at is the Binary File Descriptor library specifically the symbol handling functions. libbfd provides a common set of functions for manipulating and reading various object formats. It does this by providing an abstract view of object files and then has specific back ends to handle the details of specific object types and architectures. ELF file formats are supported as is most likely the architecture you want to use.
I don't find libbfd difficult to use but I am always open to alternatives and libelf is another one. You will probably want to look at the gelf_getsym function specifically.
C is a fully-compiled language. The names and types and other info about variables are generally discarded in the compilation process.
An exception is that most compilers will produce an executable with debugging information included, so that a live debugger has access to this information. This info is totally OS-specific, and even compiler-specific, and might even be in parts of memory not accessible to the program.
POSIX statvfs() description says:
The following flags can be returned in the f_flag member:
ST_RDONLY - Read-only file system.
ST_NOSUID - Setuid/setgid bits ignored by exec.
It is unspecified whether all members of the statvfs structure have meaningful values on all file systems.
Also sys/statvfs.h description:
The <sys/statvfs.h> header shall define the following symbolic constants for the f_flag member:
ST_RDONLY - Read-only file system.
ST_NOSUID - Does not support the semantics of the ST_ISUID and ST_ISGID file mode bits.
How to interpret this correctly? I mean:
does it allow POSIX compliant system to return nonsense, where ST_RDONLY is meaningfull?
if statvfs structure member is meaningful for particular filesystem, is OS allowed to return nonsense (I understand some fields may have no meaning for synthetic filesystems like /proc)?
Is there any OS known to return incorrect ST_RDONLY or ST_NOSUID for filesystems used to store data/executables, while claiming POSIX compatibility of it's statvfs() implementation?
The POSIX spec requires very little of statvfs(), aside from its existence.
In particular, it requires that statvfs() fill the specified struct statvfs * buffer with "information about the file system," but does not guarantee the meaning of that information. In other words it could be complete garbage and in fact is on many systems (including HFS+ on OS X).
That includes the f_flag member of struct statvfs, which can be masked to ST_RDONLY and/or ST_NOSUID but many not be on all filesystems (even when it should be).
If you need to reliably obtain filesystem information across multiple platforms, you may (ironically) have to resort to an unstandardized function like statfs(). On Linux, however, statvfs() behaves pretty well on most non-synthetic filesystems.
man getdensts says that in d_off an offset to next struct dirent is kept. But what should be kept in this field for last dirent? I was unable to find this SVr4 standard to look there, but man says nothing
"SVr4" means Unix System V Release 4. Solaris is based on that, and Solaris says:
The d_off entry contains a value which is interpretable only by the filesystem that generated it. It may be supplied as an offset to lseek(2) to find the entry following the current one in a directory.
If you look at the example in the Linux manpage, you'll find a program that uses getdents. It doesn't rely on the d_off of the final entry, which is apparently indeterminate, but on the return value from getdents, to determine how many entries there are.
Btw., the Linux manpage also states quite clearly that you shouldn't be using the getdents system call and that it isn't even supported by GLibc. Use the POSIX readdir interface instead.
I'd say it's 0, which could not indicate any next entry as the value implicitly needs to be larger 0 and also wouldn't be wrong as it points to a valid entry, namely the first one.
In the 2nd edition of "The C Programming Language" by Kernighan and Ritchie they implement a simplified version of the UNIX command ls (section 8.6 "Example - Listing Directories", p. 179). For this purpose they create the following interface which provides a system-independent access to the name and inode number of the files stored in a directory.
#define NAME_MAX 14 /* longest filename component; */
/* system dependent */
typedef struct { /* portable director-entry */
long ino; /* inode number */
char name[NAME_MAX+1]; /* name + '\0' terminator */
} Dirent;
typedef struct { /* minimal DIR: no buffering, etc. */
int fd; /* file descriptor for directory */
Dirent d; /* the directory entry */
} DIR;
DIR *opendir(char *dirname);
Dirent *readdir(DIR *dfd);
void closedir(DIR *dfd);
Then they implement this interface for Version 7 and System V UNIX systems.
opendir() basically uses the system
call open() to open a directory and
malloc() to allocate space for a
DIR structure. The file descriptor
returned by open() is then stored
in the variable fd of that DIR.
Nothing is stored in the Dirent
component.
readdir() uses the system call
read() to get the next
(system-dependent) directory entry of
an opened directory and copies the so
obtained inode number and filename
into a static Dirent structure (to
which a pointer is returned). The
only information needed by
readdir() is the file descriptor
stored in the DIR structure.
Now to my question: What is the point of having a DIR structure? If my understanding of this program is correct, the Dirent component of DIR is never used, so why not replace the whole structure with a file descriptor and directly use open() and close()?
Thanks.
Ps: I am aware that on modern UNIX systems read() can no longer be used on directories (I have tried out this program on Ubuntu 10.04), but I still want to make sure that I have not overlooked something important in this example.
From K&R:
Regrettably, the format and precise contents of a directory are not the same on all
versions of the system. So we will divide the task into two pieces to try to isolate
the non-portable parts. The outer level defines a structure called a Dirent and three routines opendir, readdir, and closedir to provide system-independent access to the name and inode number in a directory entry.
So the reason is portability. They want to define an interface that can survive on systems that have different stat structs or nonstandard open() and close(). They go on to build a bunch of reusable tools around it, which don't even care if they're on a Unix-like system. That's the point of wrappers.
Maybe it's not used because they started out by defining their data structures (with a Dirent inside DIR) but ended up not using it. Keeping data structures grouped like that is good design.
It is so they don't have to allocate memory for the Dirent structure that is returned by readdir. This way they can reuse the Dirent between subsiquent calls to readdir.