Minix: Determining size of process table - c

I would like to iterate through all possible process id's but for this, I would need to know the limit of the process table. How can I find this out?
My idea is to do something like
while (counter < table size)
{
do something
}

I think there is no posix API to get these info directly in C,you need popen() function to call command line to get this kind of info,I do not recommend system() though it is similar with popen.(Display all process using a posix function).
the system max process number can be set/check by command ulimit.
popen("ulimit -a max user processes","r");
or you can check the current max number in current processes ids.(ps aux show all processes,sed find last line ,and awk find process id)
FILE *fp = popen("ps aux|sed -n '$p'|awk '{print $2F}'","r");
if(NULL!=fp)
{
char buff[1024];
fgets(buff,1024,fp);
printf("%s\n",buff);
pclose(fp);
}

Related

How does my Linux C process know how many files were opened on the command line?

When I start a process under Linux, I can pass multiple input and output redirections. For example, if I'd like to have 14 output files, I'll do that:
command >f1 3>f2 4>f3 5>f4 6>f5 7>f6 8>f7 9>f8 10>f9 11>f10 12>f11 13>f12 14>f13 15>f14
Can my command know exactly how many such files were passed on the command line?
I know I can always add a command line option such as --count 14. I hope we don't have to.
There is no way to distinguish between redirections established on the command line and redirections which were already present in the execution environment.
For example, when utility util runs in the script
exec 4<file4
# ...
util 3<file3
it will see both fd 3 and fd 4 open for reading; it can't tell that only one was opened on the command line. If you care about that, which you probably should because there can be a number of these.
That aside, you can certainly figure out which fds are currently open, for example by cycling through all of them or examining the /proc/self/fd pseudo-directory. See this question for some example solutions to finding all the open file descriptors under Linux.
Can my command know exactly how many such files were passed on the command line?
Yes, if you order them sequentially. You can open() a dummy file (like /dev/null) and then subtract 3 from the fd returned by open to get the number of extra open files (other than stdin, stdout, and stderr) in the process. You can loop through them by starting from 3 and looping until you reach the dummy fd.
Example:
int dummy_fd = open("/dev/null", O_RDONLY);
printf("number of files open: %d\n", dummy_fd - 3);
for(int fd_ctr = 3; fd_ctr < fd; fd_ctr++)
/* ... */;
close(dummy_fd);
I know I can always add a command line option such as --count 14.
Good idea. While you're at it, how about you just pass the file names as command-line arguments, too?
Your process never sees any of those redirections. What happens is that the shell will connect up all the files to the equivalent file handles (opening them as necessary) and then run your code.
All your code can do is use the file handles that have been opened for you. Any tricks you use to find the maximum open handle inside your code will not work if you have gaps, like:
command >f1 5>f5
I suspect you'd be better off just using command line options to do this, something like:
command --output=file1 --output=file2 --output==file3
Then you have full control over how you handle those arguments in your code. For example, you can create a map of the files as you open each one.
It will also allow you to use different handles for other purposes, such as data files you need to access (I imagine you'd be rather miffed if you overwrote them with output data unrelated to the expected content simply because they were a file handle that was open).
On linux, you can just inspect the files in /proc/self/fd/. Each filename will correspond to an open fd.
Such example program:
#include <dirent.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
int main() {
printf("Open fds:");
DIR *dir = opendir("/proc/self/fd/");
assert(dir != NULL);
struct dirent *d;
while (d = readdir(dir), d != NULL) {
if (d->d_type != DT_LNK) continue;
errno = 0;
const int i = atoi(d->d_name);
assert(errno == 0);
printf(" %d", i);
}
printf("\n");
}
When executes does this:
$ ./a.out 5>a 6>b 100>c
Open fds: 0 1 2 3 5 6 100

C: Temp file deleted immediately after opening

I'm trying to make a temp file, to which I want write a bunch of stuff, and then print out upon receiving a signal. However, after some diagnostics with lsof it looks like the temp file is deleted immediately after opening it. Take the following snippet:
FILE *tmp;
int main(int argc, char *argv[]) {
if ((tmp = tmpfile()) == NULL)
err_sys("tmpfile error");
sleep(60);
Now if I go do a ps aux, get the pid of my process, and then do a lsof -p <pid>, I see the following:
10.06 1159 daniel 3u REG 0,1 0 10696049115128289 /tmp/tmpfCrM7Jn (deleted)
This is a bit of a head-scratcher for me. Considering that it's really only a single built in function call, which is not causing an error when being called, I'm not sure what the problem is.
From the man page:
The created file is unlinked before tmpfile() returns, causing the
file to be automatically deleted when the last reference to it is
closed.
The output from lsof simply indicates that the path pointing to the inode was removed. However, the current file handle FILE *tmp should still be valid, until the file is closed, or the program exits.

Programmatically read all the processes status from /proc

I want to save all of the running processes' status from the /proc folder in a file. After reading some questions and answers here I think I should use the pstatus struct to determine which fields I want to save (correct me if I'm wrong?), but I don't know how I can efficiently loop through all of the running processes.
In Linux process status is saved in /proc/PID/status pseudo-file and represented in textual form (other OS have completely different structure of their procfs):
$ grep State /proc/self/status
State: R (running)
So you need a "parser" for that file:
void print_status(long tgid) {
char path[40], line[100], *p;
FILE* statusf;
snprintf(path, 40, "/proc/%ld/status", tgid);
statusf = fopen(path, "r");
if(!statusf)
return;
while(fgets(line, 100, statusf)) {
if(strncmp(line, "State:", 6) != 0)
continue;
// Ignore "State:" and whitespace
p = line + 7;
while(isspace(*p)) ++p;
printf("%6d %s", tgid, p);
break;
}
fclose(statusf);
}
To read all processes you have to use opendir()/readdir()/closedir() and open only directories that have numerical characters (other are sysctl variables, etc.):
DIR* proc = opendir("/proc");
struct dirent* ent;
long tgid;
if(proc == NULL) {
perror("opendir(/proc)");
return 1;
}
while(ent = readdir(proc)) {
if(!isdigit(*ent->d_name))
continue;
tgid = strtol(ent->d_name, NULL, 10);
print_status(tgid);
}
closedir(proc);
Alternatively, you may use procps tools which already implemented it.
This snippet below invokes two C programs that do just that:
find /proc -maxdepth 2 -wholename '/proc/[0-9]*/status' | xargs cat
It's an old question, but still definitely a relevant one.
If you don't want to mess with parsing procfs yourself, you should definitely check out pfs. It a library for parsing most of procfs written in C++. (Disclaimer: I'm the author of the library)
On a Linux system, every task (process or thread) has an entry under the /procfs directory.
When enumerating the directories under /procfs you'll get a directory for each running processes.
Under each directory, you can find two files: stat and status, that include the current process status.
The possible statuses are described (almost correctly) under man proc(5):
(3) state %c
One of the following characters, indicating process state:
R Running
S Sleeping in an interruptible wait
D Waiting in uninterruptible disk sleep
Z Zombie
T Stopped (on a signal) or (before Linux 2.6.33) trace stopped
t Tracing stop (Linux 2.6.33 onward)
W Paging (only before Linux 2.6.0)
X Dead (from Linux 2.6.0 onward)
x Dead (Linux 2.6.33 to 3.13 only)
K Wakekill (Linux 2.6.33 to 3.13 only)
W Waking (Linux 2.6.33 to 3.13 only)
P Parked (Linux 3.9 to 3.13 only)
This is almost correct, because there's an additional possible value that is missing from this list:
I Idle
If you want to get the value from stat, the simplest way to go is probably use as fopen & fscanf. The format is intimately described under man proc(5) as well. Note: Just be carefull with the comm value format. They say it's %s, but it's actually much more complicated, since it might include spaces or any other character, it might screw up your parser (one more reason to use a mature parsing library).
If you want to get the value from status, you should probably open the file using std::ifstream or something like that and use std::getline till the lines starts with Status:, and then extract the value you want.

awk read data from file with getline as it's being written

I have a script that is running two commands. The first command is writing data to a temp file. The second command is piping to awk while the first command is running in the background. awk, in the second command, needs to read the data from the temp file, but it's parsing its own data faster than data is getting written to the temp file.
Here's an example:
#!/bin/bash
command1 > /tmp/data.txt &
# command1 takes several minutes to run, so start command 2 while it runs in the background
command2 | awk '
/SEARCH/ {
#Matched input so pull next line from temp file
getline temp_line < "/tmp/data.txt"
}
'
This works, unless awk parses the data from command2 so fast that command1 can't keep up with it. I.e. awk is getting an EOF from /tmp/data.txt before command1 has finished writing to it.
I've also tried wrapping some checks around getline, like:
while ((getline temp_line < "/tmp/data.txt") < 0) {
system("sleep 1") # let command1 write more to the temp file
}
# Keep processing now that we have read the next line
But I think once it hits an EOF in the temp file, it stops trying to read from it. Or something like that.
The overall script works as long as command1 writes to the temp file faster than awk tries to read from it. If I put a sleep 10 command between the two commands, then the temp file builds enough buffer and the script produces the output I need. But I may be parsing files much larger than what I've tested on, or the commands might run at different speeds on different systems, etc, so I'd like a safety mechanism to wait for the file until data has been written to it.
Any ideas how I can do this?
I think you'd need to close the file between iterations and read it from the start again back to where you had read it before, something like this (untested);
sleepTime = 0
while ((getline temp_line < "/tmp/data.txt") <= 0) {
close("/tmp/data.txt")
system("sleep " ++sleepTime) # let command1 write more to the temp file
numLines = 0
while (++numLines < prevLines) {
if ( (getline temp_line < "/tmp/data.txt") <= 0 ) {
print "Aaargghhh, my file is gone!" | "cat>&2"
exit
}
}
}
++prevLines
Note that I built in a variable "sleepTime" to have your command sleep longer each time through the loop so if it's taking your tmp file a long time to fill up your 2nd command waits longer for it each iteration. Use that or not as you like.
Using getline in nested loops with system() commands all seems a tad clumsy and error-prone though - I can't help thinking there's probably a better approach but I don't know what off the top of my head.

How to get the PID of a process in Linux in C

I need to kill a process using the kill API. For that I need the process id of the process. I tried to get it using:
ret = system("pidof -s raj-srv");
but it is not returning the correct value. I dont want to kill the process using this:
ret = system("pkill raj");
Is there any API that could be used to get the process id?
You are getting the return status of system. That's not the pid. You want something like this:
char line[LEN];
FILE *cmd = popen("pidof...", "r");
fgets(line, LEN, cmd);
pid_t pid = strtoul(line, NULL, 10);
pclose(cmd);
There could be multiple instances of processes running in that case , pidof returns strings of pid seperated by space .
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
main()
{
char pidline[1024];
char *pid;
int i =0;
int pidno[64];
FILE *fp = popen("pidof bash","r");
fgets(pidline,1024,fp);
printf("%s",pidline);
pid = strtok (pidline," ");
while(pid != NULL)
{
pidno[i] = atoi(pid);
printf("%d\n",pidno[i]);
pid = strtok (NULL , " ");
i++;
}
pclose(fp);
}
The system() call doesn't return the output of pidof, it returns pidof's return code, which is zero if it succeeds.
You could consume the output of pidof using popen() instead of system(), but I'm sure there's a better way (the way pidof itself uses). Perhaps it wanders through /proc.
What is returned by the system function is the return code from the command being executed.
What you can do is something like this:
system("pidof -s raj-srv > /tmp/pid-of-raj-srv");
And then read the contents of the file /tmp/pid-of-raj-srv.
I know it is not a fresh thread, but as I have only recently faced the same question, I will ask you. Did you see one of this:
Get process id by name in C
C function to find a process ID and kill it
man sysctl(3)
You can use sysctl to give you the needed information without having to pass through a system( "bla, bla" ) call.
It seems to be far more complicated at first, but may be worth depending on your needs.

Resources