Number of Running Processes on a Minix system from C code
Asked Answered
C

8

4

So, this seemed simple at first, but after crawling Google and here, the answer doesn't seem as simple as I first thought.

Basically, I'm editing a MINIX kernel as part of a practical for my Operating Systems course, and I have to add a little function that spits out the number of running processes when you hit a function key in the Information Server. I've figured out how to integrate the functionality so all the other stuff works, but for the life of me, I can not figure out how to get the current number of processes running in the system into my C code and into a variable to print out.

First I thought there'd be a nifty Syscall like SYS_NUMPROCS or something that'd return the value, but no luck. Then, I tried piping output from a system("ps -ax | wc -l") to a file and the file wouldn't create. I tried using popen() and no luck there either - even with a simple "ls" read into a buffer, it just bombs the code and "hangs" the run of the code, so there's no output.

So now I'm truly stumped, and any help would be super awesome, because at this point I've exhausted all the obvious options.

The only two things I can think of now would be a loop counting all the processes, but first you have to get to the system's process list, and I've heard vague things said about /proc/ as a directory, but I haven't a clue how to access/run through that or how it'd link up to getting the number of processes in the first place.

Thanks a stack (lol pun), guys :)

Also, I haven't included code explicitly because nothing I've written aside from basic printf'ing for cosmetic output, because none of the things I've tried gave me any joy :/

Edit notes: Guys, this is a kernel edit - I'm writing the function to printf the information in a system C file, then recompiling the kernel and rebooting the system to test. It's a UNIX (MINIX) kernel, not a Linux kernel, and it's not a user mode program.

My code for popen(), as some of you requested, is as follows:

public void cos_dmp(){
    char buffer[512];
    FILE * f;

    f = popen("ps -ax | wc -l","r");

    fgets(buffer, sizeof(buffer),f);

  //buffer should now contain result of popen()

     printf(buffer);
}

That's a bit of a hacked together version from what I remember and keeping it ultra simple and showing you guys that's what I was trying to do. Again though, there must be a better way to do this aside from essentially calling the output of a system() call.

Edit again: the above code woks perfectly from a user program but won't work from the kernel function. Anybody have an idea why?:/

Chastise answered 29/8, 2011 at 18:40 Comment(8)
So are you editing the kernel source code, or are you trying to write an ordinary program?Nedrud
Linux != Minix. Torvalds and Tanenbaum would both be very disappointed with you...Obduliaobdurate
Minix isn't linux, its unix... Tannenbaum would probably kill you for suggesting that his kernel design is anything like Torvald's. You might go wrong if you're reading linux kernel guides. (Comment void if this is some other minix I haven't heard about ;-))Epithet
Yes, yes, you're all right, it's UNIX, which I remembered after you all pointed it out :) - a lot of the kernel is similar in terms of core functionality at this point in that what I have to change would probably be similar for both Linux and Minix, but I have't even really found a Linux way of doing it yet, either.Chastise
Your fgets() will leave a newline ('\n') at the end of the string. printf(buffer) is generally unwise if you don't completely control the contents of buffer (if it contains a % character, you're in trouble); use printf("%s", buffer) or fputs(buffer, stdout).Ricardo
@James: As far as I know, Minix isn't Unix; both Minux and Linux are Unix-like. (To be called Unix, or more officially UNIX, an OS has to pass a conformance test.)Ricardo
@Keith - helpful, but it didn't change my problem - to be clear, that code should work as hoped, and does work at user-level, it just doesn't work at kernel level - I think it might to do with the fact that the code's executing from the compiled kernel, so it might be that when the code is run it doesn't "understand" the system call, but I'm probably wrong - I just don't know why it won't work.Chastise
@Adam: Yes, it was a clarification, not an answer. But ... do popen, fgets, and printf even work in kernel mode? There's something called kprintf, but I don't know much about it. Try some simpler examples.Ricardo
S
3
struct kinfo kinfo;
int nr_tasks, nr_procs;
getsysinfo(PM_PROC_NR, SI_KINFO, &kinfo);
nr_procs = kinfo.nr_pro;

This will get you the number of processes running

Stylus answered 3/9, 2011 at 18:44 Comment(0)
S
3

try looking to see what ps does. Look at its source code; it knows how many processes there are

Sprig answered 29/8, 2011 at 18:46 Comment(1)
It uses a proc_data_t to enumerate the processes. Not sure where this is defined...Underplay
F
3

Perhaps you could show us the code your wrote for capturing the result of system("ps -ax | wc -l"), or the code you wrote to use popen and we could help you diagnose the problem with it.

Regardless, the most efficient way I can think of to count the number of existing (not the same as running) processes on the system is to opendir("/proc") and count the number of entries that are strings of decimal digits. Each process in the system will be represented by a subdirectory of /proc, named after the decimal process id number of that process.

So, if you find "/proc/3432", for example, then you know that there exists a process with a pid of "3432". Simply count the number of subdirectories you find whose names are decimal numbers.


Assumptions:
  • You are asking about Linux, not MINIX.
  • You are writing a user-mode program, not modifiying the kernel.
Flax answered 29/8, 2011 at 18:47 Comment(0)
S
3
struct kinfo kinfo;
int nr_tasks, nr_procs;
getsysinfo(PM_PROC_NR, SI_KINFO, &kinfo);
nr_procs = kinfo.nr_pro;

This will get you the number of processes running

Stylus answered 3/9, 2011 at 18:44 Comment(0)
O
1

So I have been having the same problem and found a solution. (MINIX 3.1) within the method to count the processes use this code: (This is ANSI C)

It simply runs through the process table and counts the number of processes.

I know this is an old thread but it might help someone in the future.

#include "../pm/mproc.h"

/* inside function */

struct mproc *mp;
int i, n=0;

printf("Number of running processes:\n");

getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);

for (i = 0; i<NR_PROCS; i++) {
    mp = &mprocs[i];
    if (mp->mp_pid == 0 && i != PM_PROCS_NR) continue;
    n++;   
}

printf("%d", n);

/* function end */
Ow answered 25/8, 2014 at 9:20 Comment(0)
R
1

I had the same assignment at my university so i will post my solution if someone needs it in future. I am using Minix 3.3 and VMware player for virtual machines.
In pm server at location /usr/src/minix/servers/pm there is glo.h file which contains various global variables used by pm server. In that file, there is fortunately one variable called procs_in_use defined as EXTERN int procs_in_use;
So simple printf("%d\n",procs_in_use); from a system call will show the number of current processes running. You can test this by adding fork() function in your user space program in the middle of a loop.

One more mention : first answer that says

struct kinfo kinfo;
int nr_tasks, nr_procs;
getsysinfo(PM_PROC_NR, SI_KINFO, &kinfo);
nr_procs = kinfo.nr_procs;

didn't work out for me. SI_KINFO no more exists so you should use SI_PROC_TABLE. Also there can be problems with permissions, so you will not be able to call this function from your regular system call. There is alternative function sys_getkinfo(&kinfo) that can be called from your fresh system call and that will do the same as the above. The problem is kinfo.nr_procs will not return number of current processes but number of maximum user processes that can be in operative system which is 256 by default, and can be changed manually in file where NR_PROCS is defined. On the other hand kinfo.nr_taskswill return maximum number of kernel processes that can be held by operative system, which is 5 by default.

Roseleeroselia answered 17/9, 2015 at 13:44 Comment(1)
This prints out the number 38 for me. That seems highMulch
C
0

Check this out: http://procps.sourceforge.net/

It's got source to a number of small utilities that do these kinds of things. It'll be a good learning experience :) and I think PS is i n there as pm100 noted.

Castillo answered 29/8, 2011 at 18:56 Comment(0)
E
0

If you're editing the kernel, the most efficient way to solve this problem is to maintain a count every time a process (i.e., a task_struct entry) is created (and make sure you decrement the count every where a process terminates).

You could always loop through the list of processes in the kernel using the built-in macro (but its expensive, so you should try to avoid it):

struct task_struct *p;
unsigned int count = 0;
for_each_process(task) {
    count++;
}
Excitation answered 29/8, 2011 at 18:57 Comment(2)
I like your latter idea with the process list. I know it's expensive, but tbh that doesn't really matter for functionality that's hardly ever called. I had a look at some of the other source in the file and it's referencing some constant buffer for a number of processes, but I'm still not sure how I'm supposed to obtain the process list to loop through.Chastise
Since it is still UNIX, look for a way to find the init task (PID 0) and iterate from there (if there is no built-in iterator).Excitation
S
0

Check this out: http://sourceforge.net/p/readproc/code/ci/master/tree/

#include"read_proc.h"
int main(void)
{
     struct Root * root=read_proc();
     printf("%lu\n",root->len);
     return 0;
}
Sihunn answered 7/12, 2014 at 17:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.