nicku33 / exercises

A place to do exercise and collab with others

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Write "ps"

nicku33 opened this issue · comments

I assume the OS has some way to list active processes.

In OS X, I think you need to use the sysctl function. I read about MIB's but it seems really in the weeds and possibly OS X specific? But maybe not.

https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysctl.3.html
http://kb.paessler.com/en/topic/653-how-do-snmp-mibs-and-oids-work

I couldn't get the example code from the sysctl documentation to compile.

#include <sys/types.h>
#include <sys/sysctl.h>
int mib[2], maxproc;
size_t len;

mib[0] = CTL_KERN;
mib[1] = KERN_MAXPROC;
len = sizeof(maxproc);
sysctl(mib, 2, &maxproc, &len, NULL, 0);

Finally got around to looking at this.
I also struggled with that example code, and then I realized this isn't python and you can't write statements outside of functions, but you can write variable declarations. Why is this ?

int[2] x; is not actually executable code. I think what happens is it just tells the compiler to add it to the symbol table for the program. Then when you launch the program (but before your program 'starts'), 2 bytes are set aside and the address is copied everywhere the label "x" is found in the source code. So it's not really a piece of code that executes. It's more of an entry in an inventory.

A statement turns into assembly code, and every block of assembly code needs a starting point to know how to enter it. In python, everything is a statement, even import statements, and there is an implicit function call to line 1 of whatever file you are executing. C uses "main" as it's entry point.

OK. So that explains that. I think when we get around to learning about linkers this will get clearer for me.

http://stackoverflow.com/questions/11313450/code-outside-functions

The following compiles and executes.

#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>     // imports, not actually code
int mib[2], maxproc;   // declaration, not actually code
size_t len;

void fn(){
    mib[0] = CTL_KERN;   // generates code, uses registers etc
    mib[1] = KERN_MAXPROC;
    len = sizeof(maxproc);
    sysctl(mib, 2, &maxproc, &len, NULL, 0);
    printf("mib = %d, %d\n", mib[0], mib[1]);
}

int main(int argc, char** argv){
    fn();
    return 0;
}

However, this turned out to be alot more beurocracy than I was thinking, so maybe it's not that interesting an exercise. On linux, you can just use

ls /proc

because all info about processes is exposed as a filesystem.
https://en.wikipedia.org/wiki/Procfs

but OSX derived from BSD which just used system calls. There's a person who thought about hacking together a /proc for OS X btw.

http://osxbook.com/book/bonus/ancient/procfs/

Ah, that makes much more sense! Newbie mistake, although it's nice to know that other people ran into the same issue.

I agree that it's not worth unpacking the OS specific structs that store all the process information. It's interesting how files are used as an abstraction for so many things.