add pid value to /proc/"pid"/stat - c

hi i need to add the pid number to /proc/%d/stat
how i can do that ?
this is my full code , with this i have the total cpu usage :
unsigned sleep(unsigned sec);
struct cpustat {
unsigned long t_user;
unsigned long t_nice;
unsigned long t_system;
unsigned long t_idle;
unsigned long t_iowait;
unsigned long t_irq;
unsigned long t_softirq;
};
void skip_lines(FILE *fp, int numlines)
{
int cnt = 0;
char ch;
while((cnt < numlines) && ((ch = getc(fp)) != EOF))
{
if (ch == '\n')
cnt++;
}
return;
}
void get_stats(struct cpustat *st, int cpunum)
{
FILE *fp = fopen("/proc/stat", "r");
int lskip = cpunum+1;
skip_lines(fp, lskip);
char cpun[255];

Obviously, to replace the %d with an integer, you'll need to use sprintf into a buffer as you do in your second example. You could also just use /proc/self/stat to get the stats of the current process, rather than getpid+sprintf.
Your main problem seems to be with the contents/format you're expecting to see. stat contains a single line of info about the process, as described in proc(5). For example:
$ cat /proc/self/stat
27646 (cat) R 3284 27646 3284 34835 27646 4194304 86 0 1 0 0 0 0 0 20 0 1 0 163223159 7618560 210 18446744073709551615 4194304 4240236 140730092885472 0 0 0 0 0 0 0 0 0 17 1 0 0 2 0 0 6340112 6341364 37523456 140730092888335 140730092888355 140730092888355 140730092892143 0
You seem to be skipping some initial lines, and then trying to read something with a different format.
from the proc(5) man page, some of those numbers from /proc/self/stat are related to cpu time:
(14) utime %lu
Amount of time that this process has been scheduled in user mode, mea‐
sured in clock ticks (divide by sysconf(_SC_CLK_TCK)). This includes
guest time, guest_time (time spent running a virtual CPU, see below), so
that applications that are not aware of the guest time field do not lose
that time from their calculations.
(15) stime %lu
Amount of time that this process has been scheduled in kernel mode, mea‐
sured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
Which gives you the total cpu time in this process since it started. With the above cat program, those numbers are both 0 (it runs too fast to accumulate any ticks), but if I do
$ cat /proc/$$/stat
3284 (bash) S 2979 3284 3284 34835 12764 4194304 71122 947545 36 4525 104 66 1930 916 20 0 1 0 6160 24752128 1448 18446744073709551615 4194304 5192964 140726761267456 0 0 0 65536 3670020 1266777851 1 0 0 17 1 0 0 68 0 0 7290352 7326856 30253056 140726761273517 140726761273522 140726761273522 140726761275374 0
you can see that my shell has 104 ticks of user time and 66 ticks of system time.

Related

Parsing a binary packet (from C) in Go

Im writing a go application that listens for UDP packets over a network and parses them.
the udp packets are written in C and the struct definition (according to their docs) is something like the below. (Please understand that new to C and networking in general)
typedef struct foo
{
int code;
char seg[10];
char sym[25];
short type;
long amtToday;
long price;
...etc
} foo;
A sample network packet is something like the below
[233 3 0 0 99 100 101 95 102 111 0 0 0 0 55 52 51 57 0 69 69 68 49 48 50 48 74 65 78 50 48 50 49 0 0 58 254 127 0 0 1 0 166 58 254 127 0 0 255 255 255 255 255 255 255 255 32 232 141 0 0 0 0 0 0 135 166 58 254 127 0 0 ... etc]
in short, im having trouble getting the right values after the sym field.
i read up a bit about struct alignment in C and guessing that im ignoring the padded values. But im a bit confused as to where the padding occurs
is it this
typedef struct foo
{
int code;
char seg[10];
**char pad[6];**
char sym[25];
**char pad[7];**
short type;
long amtToday;
long price;
...etc
} foo;
i.e padding is added after each char field
or is it more like this
typedef struct foo
{
int code;
char seg[10];
char sym[25];
**char pad[1];**
short type;
long amtToday;
long price;
...etc
} foo;
the problem is that there is no way for me to determine if either of these are right at my end. I need to parse the entire struct before confirming - but unable to do so because of the padding issue
or am i heading in the wrong direction parsing this packet?
The best way to convince yourself of how it works is probably to write C-code that computes the offsets:
#include <stdio.h>
typedef struct foo
{
int code;
char seg[10];
char sym[25];
short type;
long amtToday;
long price;
} foo;
int main() {
// What are the memory offsets between individual struct members?
foo x;
printf(
"code: %ld, seg: %ld, sym: %ld, type: %ld, amtToday: %ld, price: %ld\n",
(long)&x.code - (long)&x,
(long)&x.seg - (long)&x,
(long)&x.sym - (long)&x,
(long)&x.type - (long)&x,
(long)&x.amtToday - (long)&x,
(long)&x.price - (long)&x
);
// How much space does the struct take up if we create an array for it?
foo y[2];
printf("offset: %ld\n", (long)&y[1] - (long)&y[0]);
return 0;
}
Output:
code: 0, seg: 4, sym: 14, type: 40, amtToday: 48, price: 56
offset: 64
The offsets can depend on architecture and the compiler being used. If you are able to edit the C-program, adding explicit padding to the struct might be the best way to guarantee the same offsets on 32-bit and 64-bit systems.

How do I increase the size of int, so that i could store the value of 5 ^ 30 in it

I'm trying to write a program and the requirement is to store the power of 5^30 into int but when I'm trying to do it, it gives a output as a negative number.
It runs fine with double or long
#include <stdio.h>
int PowerFive(){
int a, i, n=5, e=1;
for (i = 0; i<=30; i++)
{
a=e;
printf("%d, ", e);
e = e*n;
}
return 0;
}
int main()
{
PowerFive();
}
increase the size of int
Compilers sometimes offer controls of int size, yet often that is fixed to the target system as 32, 16, 64, .. bits. It must be at least 16.
store the value of 5 ^ 30
530 is 931322574615478515625, a 70 bit number.
C does not specify an integer type wide enough for that, although some systems do support 128 bit integer.
Lacking 128-bit integers, to store that integer value requires a different approach. Various arbitrary width libraries exists.
A quickie is to use a string - not very efficient, but gets the job done.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *strmult(char *s, size_t size, unsigned char m) {
size_t len = strlen(s);
if (len >= size) {
return NULL;
}
int carry = 0;
for (size_t i = len; i-- > 0;) {
if (!isdigit((unsigned char ) s[i])) {
return NULL;
}
int sum = (s[i] - '0') * m + carry;
s[i] = sum % 10 + '0';
carry = sum / 10;
}
while (carry) {
if (len + 1 >= size) {
return NULL;
}
memmove(s + 1, s, len + 1);
s[0] = carry + '0';
carry /= 10;
}
return s;
}
int main(void) {
char s[100] = "1";
for (int i = 0; i < 30; i++) {
strmult(s, sizeof s, 5);
}
puts(s);
}
Output
931322574615478515625
You can't; int has a fixed size.
long may be larger than int, but it looks like you need more than 64 bits to get the correct answer. In that case, your best bet is probably to use __int128.
The number of bit/bytes of int, long, double, ... is implementation/platform dependent.
For that reason, on some platforms this may not work with long.
The a note about 'it works with double': In general, with double or float you may think it worked, but the answer could be wrong: rounded to a value close to the correct answer.
You have to implement your own big-int code that uses 3 (or more) ints.
UPDATE : quick note on how to get 5^30 very quickly, without needing a dedicated bigint package :
{m,g}awk 'BEGIN { CONVFMT=OFMT="%.250g"
print _ = int(__=(_+=(_^=_<_)+(_+=_))^(__+=__=++_+--_) * \
(_+=_^=!_)^-_^++_) int((__-int(__))*(--_+(_*=_+_))^_) }'
931322574615478515625
In fact, using the same technique, you can leverage double-precision floating point and perform a very specific type of multiplication/squaring MUCH faster than dedicated bigint packages :
fgc;
( time ( perl -le 'use bigint; my $__=5; $__**=537;
$__*=88777979; print int(($__)*($__))'
) | gfactor ) | sanitize_gnu_factor
sleep .5
( time ( python3 -c '_=537; __=88777979; ___=2;____=5;
print(int(pow(pow(____,_)*__,___)))'
) | gfactor ) | sanitize_gnu_factor
sleep .5
( time ( gawk -Mbe 'BEGIN { _=537; __=88777979; ___=2
____=5; print (____^_*__)^___ }'
) | gfactor ) | sanitize_gnu_factor
sleep .5
( time ( mawk2 'BEGIN { CONVFMT=OFMT= "%."(-(_+=++_)-(_+=_)+_^_)"g"
print substr("",
(_=sprintf("%.*g",_^_++*_--,
(__=88777979)*__*_^-_^_-- * \
(--_)^(_++^_^--_-_*(___=(_^++_)^_+_^_+_^!_-_++)))\
\
)~(___="^[+-]?[0]+[.][0]+"(__="")) ? sub(___,__,_) \
: gsub("[.]|^[+-]*[0]*|[Ee][+-]?[0-9]+$",__,_))_ }'
) | gfactor ) | sanitize_gnu_factor
389399298996824262817161994......640522278845310211181640625 } 767 dgts :
5^1,074
88,777,979^2
( perl -le ; ) 0.03s user 0.00s system 95% cpu 0.034 total
gfactor 0.00s user 0.00s system 10% cpu 0.034 total
389399298996824262817161994......640522278845310211181640625 } 767 dgts :
5^1,074
88,777,979^2
( python3 -c ; ) 0.02s user 0.01s system 86% cpu 0.035 total
gfactor 0.00s user 0.00s system 15% cpu 0.034 total
389399298996824262817161994......640522278845310211181640625 } 767 dgts :
5^1,074
88,777,979^2
( gawk -Mbe ; ) 0.00s user 0.00s system 64% cpu 0.011 total
gfactor 0.00s user 0.00s system 39% cpu 0.011 total
( mawk2 ; ) 0.00s user 0.00s system 59% cpu 0.005 total
gfactor 0.00s user 0.00s system 77% cpu 0.006 total
389399298996824262817161994......640522278845310211181640625 } 767 dgts :
5^1,074
88,777,979^2
the task : full precision squaring of ( 5 ** 537 ) * 88777979, a result that's 767 decimal digits long and approx. 2546.55817-bits.
using only user-level scripting, IEEE 754 double precision floating point math, plus a tiny bit of cleanup string ops, mawk2, an app that no built-in bigint support at all, came out faster than all of these :
perl 5.34 with bigint package enabled,
python 3.10.6 with built-in big-int support, and
gnu-gawk 5.1.1 with gnu-GMP bigint package
======================================================
you get integer powers of 5 in the inclusive range of [-1023, 1074] essentially for free whenever your platform uses IEEE 754 double precision floating point math, so you don't really have to "store" them per se :
jot - -100 100 13 |
mawk '($++NF = +(__=$!____)<-(___=(_^=_<_)-+-++_+_)*!_\
? sprintf("%.fe%.f", _^-__,+__) \
:+__<(___^_-_) \
? ___^__ : substr(___="", _=sprintf("%.*f",__,
_^-__), sub("^[0.]+",___,_))_)_' CONVFMT='%.20g'
-100 1267650600228229401496703205376e-100
-87 154742504910672534362390528e-87
-74 18889465931478580854784e-74
-61 2305843009213693952e-61
-48 281474976710656e-48
-35 34359738368e-35
-22 4194304e-22
-9 512e-9
4 625
17 762939453125
30 931322574615478515625
43 1136868377216160297393798828125
56 1387778780781445675529539585113525390625
69 1694065894508600678136645001359283924102783203125
82 2067951531382569187178521730174907133914530277252197265625
95 2524354896707237777317531408904915934954260592348873615264892578125

Improper reading of file in C

I am doing a socket programming for hospital chanelling.
I am trying to read a text file like this
1 Kavi card 0 0 0
2 Anparasanesan gene 0 0 0
3 Thilak card 0 0 0
4 Akilanesan immu 0 0 0
5 Aravinthanesan derm 0 0 0
6 Akalya derm 0 0 0
7 Vishvapriya derm 0 0 0
8 Kavinga immu 0 0 0
9 Anjalie andr 0 0 0
10 Tom andr 0 0 0
but when i am reading that file it gives me the output as :
1 Kavi cardgenecardimmudermdermdermimmuandrandr
2 Anparasanesan genecardimmudermdermdermimmuandrandr
3 Thilak cardimmudermdermdermimmuandrandr
4 Akilanesan immudermdermdermimmuandrandr
5 Aravinthanesan dermdermdermimmuandrandr
6 Akalya dermdermimmuandrandr
7 Vishvapriya dermimmuandrandr
8 Kavinga immuandrandr
9 Anjalie andrandr
10 Tom andr
Here is my code segment
char line[MAXCHAR];
int x = 0;
while (fgets(line, sizeof(line), fp)){
sscanf(line,"%d\t%s\t%s\t%d\t%d\t%d",&dno,&dname,&dspl,&ti1,&ti2,&ti3);
id[x]=dno;
strncpy(name[x], dname, 50);
strncpy(spl[x], dspl, 4);
times[x][0]=ti1;
times[x][1]=ti2;
times[x][2]=ti3;
x++;
}
int z=0;
for(z=0;z<10;z++)
{
snprintf(line, sizeof(line),"%d\t%s\t%s\n",id[z],name[z],spl[z]);
n = strlen(line);
Writen(sockfd,line,n);
}
Let us look at one of the problems.
evil strncpy
Code is using strncpy with a magic number 4. This does not insure spl[x] is a string as the characters may lack a final null character.
strncpy(spl[x], dspl, 4); // Avoid code like this
Later code tries to print a string with "%s" and spl[z] and gets "cardgene..." rather than the expected "card". When spl[z] is not a string, the result is undefined behavior (UB) - anything may happen.
// Alternative: could limit output with
snprintf(line, sizeof(line),"%.*s\n",(int) (sizeof spl[z]), spl[z]);
How to fix?
Do not use sscanf(line,"%s",&dspl); as it lacks either a width limit, or it is not known that dspl is about the same size of line. I'd expect
char dspl[4+1];
sscanf(line,"%4s", dspl);
Better to insure the source string and destination array are sufficient than use strncpy() without tests.
char spl[X_N][4+1];
char dspl[sizeof spl[0]];
// strncpy(spl[x], dspl, 4);
strcpy(spl[x], dspl);
Others fixes include make certain the sscanf() completed as expected. A simple approach uses " %n" to record the scan offset, if it got that far and then look for extra garbage. Unnecessary "\t" removed.
// Insure dname is at least 50+1, dspl is 4+1 or as big as the line
char dname[sizeof line];
char dspl[sizeof line];
// sscanf(line,"%d\t%s\t%s\t%d\t%d\t%d",&dno,&dname,&dspl,&ti1,&ti2,&ti3);
int n = 0;
sscanf(line,"%d%50s%4s%d%d%d %n",&dno,dname,dspl,&ti1,&ti2,&ti3, &n);
if (n==0 || line[n]) {
puts("Bad Input"); // Handle bad input in some fashion
exit(RETURN_FAILURE);
}

Having issues iterating through machine code

I'm attempting to recreate the wc command in c and having issues getting the proper number of words in any file containing machine code (core files or compiled c). The number of logged words always comes up around 90% short of the amount returned by wc.
For reference here is the project info
Compile statement
gcc -ggdb wordCount.c -o wordCount -std=c99
wordCount.c
/*
* Author(s) - Colin McGrath
* Description - Lab 3 - WC LINUX
* Date - January 28, 2015
*/
#include<stdio.h>
#include<string.h>
#include<dirent.h>
#include<sys/stat.h>
#include<ctype.h>
struct counterStruct {
int newlines;
int words;
int bt;
};
typedef struct counterStruct ct;
ct totals = {0};
struct stat st;
void wc(ct counter, char *arg)
{
printf("%6lu %6lu %6lu %s\n", counter.newlines, counter.words, counter.bt, arg);
}
void process(char *arg)
{
lstat(arg, &st);
if (S_ISDIR(st.st_mode))
{
char message[4056] = "wc: ";
strcat(message, arg);
strcat(message, ": Is a directory\n");
printf(message);
ct counter = {0};
wc(counter, arg);
}
else if (S_ISREG(st.st_mode))
{
FILE *file;
file = fopen(arg, "r");
ct currentCount = {0};
if (file != NULL)
{
char holder[65536];
while (fgets(holder, 65536, file) != NULL)
{
totals.newlines++;
currentCount.newlines++;
int c = 0;
for (int i=0; i<strlen(holder); i++)
{
if (isspace(holder[i]))
{
if (c != 0)
{
totals.words++;
currentCount.words++;
c = 0;
}
}
else
c = 1;
}
}
}
currentCount.bt = st.st_size;
totals.bt = totals.bt + st.st_size;
wc(currentCount, arg);
}
}
int main(int argc, char *argv[])
{
if (argc > 1)
{
for (int i=1; i<argc; i++)
{
//printf("%s\n", argv[i]);
process(argv[i]);
}
}
wc(totals, "total");
return 0;
}
Sample wc output:
135 742 360448 /home/cpmcgrat/53/labs/lab-2/core.22321
231 1189 192512 /home/cpmcgrat/53/labs/lab-2/core.26554
5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/file
24 224 12494 /home/cpmcgrat/53/labs/lab-2/frequency
45 116 869 /home/cpmcgrat/53/labs/lab-2/frequency.c
5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/lineIn
12 50 1013 /home/cpmcgrat/53/labs/lab-2/lineIn2
0 0 0 /home/cpmcgrat/53/labs/lab-2/lineOut
39 247 11225 /home/cpmcgrat/53/labs/lab-2/parseURL
138 318 2151 /home/cpmcgrat/53/labs/lab-2/parseURL.c
41 230 10942 /home/cpmcgrat/53/labs/lab-2/roman
66 162 1164 /home/cpmcgrat/53/labs/lab-2/roman.c
13 13 83 /home/cpmcgrat/53/labs/lab-2/romanIn
13 39 169 /home/cpmcgrat/53/labs/lab-2/romanOut
7 6 287 /home/cpmcgrat/53/labs/lab-2/URLs
11508 85256 1324239 total
Sample rebuild output (./wordCount):
139 76 360448 /home/cpmcgrat/53/labs/lab-2/core.22321
233 493 192512 /home/cpmcgrat/53/labs/lab-2/core.26554
5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/file
25 3 12494 /home/cpmcgrat/53/labs/lab-2/frequency
45 116 869 /home/cpmcgrat/53/labs/lab-2/frequency.c
5372 40960 365441 /home/cpmcgrat/53/labs/lab-2/lineIn
12 50 1013 /home/cpmcgrat/53/labs/lab-2/lineIn2
0 0 0 /home/cpmcgrat/53/labs/lab-2/lineOut
40 6 11225 /home/cpmcgrat/53/labs/lab-2/parseURL
138 318 2151 /home/cpmcgrat/53/labs/lab-2/parseURL.c
42 3 10942 /home/cpmcgrat/53/labs/lab-2/roman
66 162 1164 /home/cpmcgrat/53/labs/lab-2/roman.c
13 13 83 /home/cpmcgrat/53/labs/lab-2/romanIn
13 39 169 /home/cpmcgrat/53/labs/lab-2/romanOut
7 6 287 /home/cpmcgrat/53/labs/lab-2/URLs
11517 83205 1324239 total
Notice the difference in the word count (second int) from the first two files (core files) as well as the roman file and parseURL files (machine code, no extension).
C strings do not store their length. They are terminated by a single NUL (0) byte.
Consequently, strlen needs to scan the entire string, character by character, until it reaches the NUL. That makes this:
for (int i=0; i<strlen(holder); i++)
desperately inefficient: for every character in holder, it needs to count all the characters in holder in order to test whether i is still in range. That transforms a simple linear Θ(N) algorithm into an Θ(N2) cycle-burner.
But in this case, it also produces the wrong result, since binary files typically include lots of NUL characters. Since strlen will actually tell you where the first NUL is, rather than how long the "line" is, you'll end up skipping a lot of bytes in the file. (On the bright side, that makes the scan quadratically faster, but computing the wrong result more rapidly is not really a win.)
You cannot use fgets to read binary files because the fgets interface doesn't tell you how much it read. You can use the Posix 2008 getline interface instead, or you can do binary input with fread, which is more efficient but will force you to count newlines yourself. (Not the worst thing in the world; you seem to be getting that count wrong, too.)
Or, of course, you could read the file one character at a time with fgetc. For a school exercise, that's not a bad solution; the resulting code is easy to write and understand, and typical implementations of fgetc are more efficient than the FUD would indicate.

VxWorks 5.5 not filling stack with 0xEEEEEEEE

From taskSpawn VxWorks 5.5 documentation :
"The only resource allocated to a spawned task is a stack of a specified size stackSize, which is allocated from the system memory partition. Stack size should be an even integer. A task control block (TCB) is carved from the stack, as well as any memory required by the task name. The remaining memory is the task's stack and every byte is filled with the value 0xEE for the checkStack( ) facility. See the manual entry for checkStack( ) for stack-size checking aids. "
However when tried to scan the stack by spawning a brand new task:
int scan_the_stack(...)
{
printf("Going to scan the stack forward\n");
int i = 0;
int* stack_addr = &i;
for (int i = 0; i < 100; i++)
{
printf("%d : %X\n", i, *stack_addr);
stack_addr++;
}
return 0;
}
void spawn_scan_stack()
{
taskSpawn("tScanner", /* name of new task (stored at pStackBase) */
150, /* priority of new task */
VX_FP_TASK, /* task option word */
10000, /* size (bytes) of stack needed plus name */
scan_the_stack, /* entry point of new task */
0, /* 1st of 10 req'd args to pass to entryPt */
0,0,0,0,0,0,0,0,0);
}
Instead of getting expected consecutive 'EEEEEEEE' I got some 'EE' intermixed with other values:
-> spawn_scan_stack
value = 80735920 = 0x4cfeeb0
-> Going to scan the stack forward
0 : 0
1 : 4CFEE1C
2 : 2
3 : EEEEEEEE
4 : EEEEEEEE
5 : EEEEEEEE
6 : EEEEEEEE
7 : 0
8 : 0
9 : 0
10 : 4CFEE70
11 : 2951F4
12 : 0
13 : 0
14 : EEEEEEEE
15 : EEEEEEEE
16 : EEEEEEEE
17 : EEEEEEEE
18 : EEEEEEEE
19 : 0
20 : 0
21 : 0
22 : 0
23 : 0
24 : EEEEEEEE
25 : EEEEEEEE
26 : EEEEEEEE
27 : EEEEEEEE
28 : 0
29 : 0
30 : 0
31 : 0
32 : 0
33 : 0
34 : 0
35 : 0
36 : 0
37 : 0
38 : 0
39 : 0
40 : 96
41 : FF630
42 : 20
43 : 11000001
44 : 19BDD /*...*/
The question is why isn't the stack filled with EEEEEEE (also checkStack seems to be working still).
Try 'stack_addr--;' - bet you're on Intel where the stacks grow downwards. You are looking up at valid stack data - return addresses and local vars, some of which are uninitialised.
My initial assumption was that the task had been spawned with VX_NO_STACK_FILL, which tells vxworks not to initialise the stack to 0xEE. But, looking at your code, you just use VX_FP_TASK (for floating point support). So the stack should be correctly initialised.
That really leaves two possibilities. The first (and more unlikely) is that something else is writing where it shouldn't be, but you would likely be seeing strange behaviour elsewhere (and i might expect checkStack to show that something has been smashed)
The second, as already suggested by others is that you are on one of the architectures (such as intel) where the stack grows downwards. The VxWorks Architecture Supplement should tell you which direction the stack grows for your architecture.
You might also be able to tell at compile time by including vxArch.h and testing the value of _STACK_DIR for _STACK_GROWS_DOWN or _STACK_GROWS_UP

Resources