I've written a program which forks in a loop. The only thing children processes do is to increase a counter and exit, whereas a parent process waits for each of them.
My goal is to measure user and system time of parent process and all his children separately.
I've succeded with parent process using times() function and struct tms. Surprisingly, the same aproach to children processes isn't working. What is the mistake that I'm doing? How to measure those times?
I've also tried getrusage() and I/it failed.
My code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/times.h>
#include <time.h>
#ifndef COUNT
#define COUNT 100000
#endif
int counter;
int main(){
struct tms time1,time2;
times(&time1);
int count = COUNT;
pid_t pid;
while(count--){
if((pid=fork())<0){
printf("fork error\n");
} else if(pid==0){ /* child */
counter++;
_exit(0);
} else {
waitpid(pid,NULL,0); /*wait()*/
}
}
printf("COUNTER: %d\n",counter);
times(&time2);
long double clktck=sysconf(_SC_CLK_TCK);
double user=(time2.tms_utime-time1.tms_utime)/(double)clktck;
double system=(time2.tms_stime-time1.tms_stime)/(double)clktck;
double cuser=(time2.tms_cutime-time1.tms_cutime)/(double)clktck;
double csystem=(time2.tms_cstime-time1.tms_cstime)/(double)clktck;
printf("USER:%lf\nSYSTEM:%lf\n",user,system);
printf("CUSER:%lf\nCSYSTEM:%lf\n",cuser,csystem);
return 0;
}
I think the problem is that your children are executing too quickly; they don't take enough time to execute, so the sum of their time is plenty of zeros. To test this theory, I slightly changed your program:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/times.h>
#include <time.h>
#ifndef COUNT
#define COUNT 100
#endif
int counter;
int main(){
struct tms time1,time2;
times(&time1);
int count = COUNT;
pid_t pid;
while(count--){
if((pid=fork())<0){
printf("fork error\n");
} else if(pid==0){ /* child */
int i;
for (i=0; i<10000; i++) {
printf("in child %i\n", getpid());
}
exit(0);
} else {
waitpid(pid,NULL,0); /*wait()*/
}
}
printf("COUNTER: %d\n",counter);
times(&time2);
printf("%lu %lu %lu %lu\n", time2.tms_utime, time2.tms_stime, time2.tms_cutime, time2.tms_cstime);
long double clktck=sysconf(_SC_CLK_TCK);
double user=(time2.tms_utime-time1.tms_utime)/(double)clktck;
double system=(time2.tms_stime-time1.tms_stime)/(double)clktck;
double cuser=(time2.tms_cutime-time1.tms_cutime)/(double)clktck;
double csystem=(time2.tms_cstime-time1.tms_cstime)/(double)clktck;
printf("USER:%lf\nSYSTEM:%lf\n",user,system);
printf("CUSER:%lf\nCSYSTEM:%lf\n",cuser,csystem);
return 0;
}
You'll see that I drastically cut down on the number of children, and made the children do some real work; 10_000 printf(... getpid()) operations. Now the times amount to something:
$ time ./times
...
in child 16181
COUNTER: 0
1 0 24 95
USER:0.010000
SYSTEM:0.000000
CUSER:0.240000
CSYSTEM:0.950000
real 0m2.234s
user 0m0.250s
sys 0m0.950s
I'm afraid your children just didn't have enough work to do to amount to anything. (Odd, sounds like parenting advice.)
Each child is given their own address space. The code will not work because it will increment it's own local copy of counter and quit, leaving the version in the parent process/all other children untouched.
Also, you are very likely to get some errors with that many children.
Sorry I could only help with half the program :(.
Related
I'm writing a program that open a .txt file by vim and whenever i press CTRL+C the process will be killed. But the thing is i can't find the process's pid that i've just created and kill it. Can anybody help me?
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
void ctrl_C(int sig){
system("kill -9 $(pidof id)");
printf("\n You pressed Ctrl + C,Good Bye \n");
exit(0);
}
int main(){
printf("I am Programmer \n");
pid_t id = system("gnome-terminal -- vi abcd.txt");
signal(SIGINT,ctrl_C);
while(1){}
}
There are multiple issues with your code:
system(3) does NOT return PID of child process, but instead waits for it to exit, and returns its exit code. You need to use the traditional fork+exec approach.
With child PID available, it's easier to call kill(2) than kill(1)
Better add sleep in a dead loop waiting for input. This reduces CPU load and your electricity bill.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
pid_t child_id;
void ctrl_C(int sig){
kill(child_id, 9);
printf("\n You pressed Ctrl + C,Good Bye \n");
exit(0);
}
int main(){
printf("I am Programmer \n");
pid_t child_id = fork();
if (child_id == 0) {
execlp("gnome-terminal", "gnome-terminal", "--", "vi", "abcd.txt", NULL);
return 255;
}
signal(SIGINT,ctrl_C);
while (1) {
sleep(1);
}
}
I think i am very close, but some detail is missing here.
The task:
Write a program in C that creates a father and child process. Father and child are both counting from 1 to 1000 "using" a loop.
The father process only counts the even numbers, while the child process only counts the odd numbers.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void main (){
int id = fork();
int i;
if (id == 0){
for (i=1;i<=1000;i=i+2){
printf("%d\n",i);
}
}
if (id > 0){
for (i=0;i<=1000;i=i+2){
printf("%d\n",i);
wait(0);
}
}
}
The problem i have here is, that all the numbers a completely mixed up.
It seems that my wait system call is not working correctly :(
I appreciate any help. Thanks in advance :)
Your wait system call should placed out of for loop, because there's only one child process to wait.
like that
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void main (){
int id = fork();
int i;
if (id == 0){
for (i=1;i<=1000;i=i+2){
printf("%d\n",i);
}
}
if (id > 0){
for (i=0;i<=1000;i=i+2){
printf("%d\n",i);
}
wait(0);
}
}
i wrote the below code: after fork() function the parent send a signal to child. i think the child receive the signal and terminates.
i don't want the solution because i can solve it by two below ways.
i want to know what is the cause of this problem?
what i tried at first is below code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <wait.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#define maxchild 1
int inchild=-1;
void sighandler(int signo){
char buffer[256];
int a,b=0;
switch(signo){
case SIGUSR1:
printf("SIGUSR1\n");
break;
case SIGUSR2:
printf("SIGUSR2\n");
break;
}
}
int main(){
pid_t ids[maxchild];
struct sigaction control;
control.sa_flags=0;
control.sa_handler=sighandler;
sigemptyset(&control.sa_mask);
sigaction(SIGUSR1,&control,NULL);
sigaction(SIGUSR2,&control,NULL);
for(int i=0;i<maxchild;i++){
ids[i]=fork();
printf("here %d\n",ids[i]);
if(ids[i]==0){
printf("in child\n");
inchild=i+1;
break;
}
}
while(inchild>=0) {
}
// sleep(1);
if(inchild==-1){
for(int i=0;i<maxchild;i++){
printf("child: %d\n parent: %d\n",ids[i],getpid());
kill(ids[i],SIGUSR1);
}
}
if (inchild==-1) wait(NULL);
return 0;
}
when i run the code so many times, i expect to see the "SIGUSR1" in output every time but mostly the output is:
here 17573 (or any other positive number)
child: 17573
parent: 17572
and then program terminates suddenly.
i understand i can solve it by two solution:
1. parent most sleep after fork() function:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <wait.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#define maxchild 1
int inchild=-1;
void sighandler(int signo){
char buffer[256];
int a,b=0;
switch(signo){
case SIGUSR1:
printf("SIGUSR1\n");
break;
case SIGUSR2:
printf("SIGUSR2\n");
break;
}
}
int main(){
pid_t ids[maxchild];
struct sigaction control;
control.sa_flags=0;
control.sa_handler=sighandler;
sigemptyset(&control.sa_mask);
sigaction(SIGUSR1,&control,NULL);
sigaction(SIGUSR2,&control,NULL);
for(int i=0;i<maxchild;i++){
ids[i]=fork();
printf("here %d\n",ids[i]);
if(ids[i]==0){
printf("in child\n");
inchild=i+1;
break;
}
}
while(inchild>=0) {
}
sleep(1);
if(inchild==-1){
for(int i=0;i<maxchild;i++){
printf("child: %d\n parent: %d\n",ids[i],getpid());
kill(ids[i],SIGUSR1);
}
}
if (inchild==-1) wait(NULL);
return 0;
}
that it will work fine
i can comment the "kill(...)" line too to solve the problem:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <wait.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#define maxchild 1
int inchild=-1;
void sighandler(int signo){
char buffer[256];
int a,b=0;
switch(signo){
case SIGUSR1:
printf("SIGUSR1\n");
break;
case SIGUSR2:
printf("SIGUSR2\n");
break;
}
}
int main(){
pid_t ids[maxchild];
struct sigaction control;
control.sa_flags=0;
control.sa_handler=sighandler;
sigemptyset(&control.sa_mask);
sigaction(SIGUSR1,&control,NULL);
sigaction(SIGUSR2,&control,NULL);
for(int i=0;i<maxchild;i++){
ids[i]=fork();
printf("here %d\n",ids[i]);
if(ids[i]==0){
printf("in child\n");
inchild=i+1;
break;
}
}
while(inchild>=0) {
}
// sleep(1);
if(inchild==-1){
for(int i=0;i<maxchild;i++){
printf("child: %d\n parent: %d\n",ids[i],getpid());
// kill(ids[i],SIGUSR1);
}
}
if (inchild==-1) wait(NULL);
return 0;
}
now i want to know the reason of problem.
i want to run the first code and see:
here (an positive number)
here 0
in child
child: (an positive number)
parent: (an positive number)
SIGUSR1
and the program must continue running until i press the Ctrl+c
(of course the order of line in output doesn't matter)
i didn't want to change the code, i want to know what is the cause of problem.
thank you in advance
If a process has a signal-handler installed this gets called on reception of the signal. This process is not ended then. So all the children are stuck in
while (inchild >= 0) {
}
As no child ends, the parent is blocking in wait().
To fix this replace the above snippet by
if (inchild >= 0) {
pause();
}
I'm trying to write a small program that generates a child process with fork() that will have to increase a variable shared with the parent, how do I share an unsigned int variable?
code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
static unsigned int elapsed;
int count(){
while(1){
sleep(1);
elapsed++;
}
exit(EXIT_SUCCESS);
}
void hadler(int sig){
if( sig == SIGUSR1){
printf("elapsed: %u\n", elapsed);
}
}
int main(){
pid_t pid = getpid();
printf("This is my pid: %d\n", pid);
pid = fork();
if(pid == 0)
count();
while(1){
signal(SIGUSR1, hadler);
}
}
You can see there is a child than exec count() (increase a variable "elapsed" every second). The parent is waiting for SIGUSR1, when receive the signal he print the "elapsed".
Naively I tried to use a static global variable but it doesn't work for obvious reasons.
I made the following simple example to read memory from a child process using ptrace.
I want to see the value at a specific address, 0x601050, every second during the execution of a small matrix multiplication program. I use PTRACE_PEEKDATA followed by PTRACE_CONT and sleep for 1 second, in an infinite loop, to do so.
However, the matrix multiplication program never proceeds--it should print to stdout in the first instruction, but it never seems to execute. I understood that ptrace(PTRACE_CONT,pid) would signal the child to resume execution and that sleep(1) would allow it to execute for a second (until the next ptrace call), but that is not the case.
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <sys/reg.h>
int read_mem(long *out, pid_t pid, long addr, size_t sz)
{
long tmp;
size_t copied = 0;
while(copied < sz)
{
tmp = ptrace(PTRACE_PEEKDATA, pid, addr+copied);
if(errno)
{
fprintf(stderr,"ptrace: error : %s\n",strerror(errno));
return copied;
}
memcpy(out,&tmp,sizeof(long));
copied += sizeof(long);
out++;
printf("ptrace: copied %d bytes\n",copied);
}
return copied;
}
int main()
{
pid_t child;
long result;
struct user_regs_struct regs;
int status;
long addr = 0x601050;
size_t sz = sizeof(double);
long *buf = (long*)malloc(sz);
child = fork();
if(child == 0)
{
ptrace(PTRACE_TRACEME);
execl("./matmul", "matmul", NULL);
}
else
{
ptrace(PTRACE_GETREGS, child, ®s);
printf("ptrace: regs.rip : 0x%lx\n", regs.rip);
while(1)
{
read_mem(buf, child, addr, sz);
printf("ptrace: read(0x%lx) : %f\n", addr, (double)(*buf));
ptrace(PTRACE_CONT, child);
sleep(1);
}
}
return 0;
}
You don't seem to set a PTRACE_O_TRACEEXEC option. Failing to do so results in SIGTRAP being sent to tracee upon a call to exec; if it is not prepared, the default action is a termination with a core dump.