 |
 |
 |
 |
| Programming & Packaging A place to discuss programming and packaging. |

30th March 2009, 12:44 PM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
|
C program...processes.
ok...i wrote a program that takes user input within 5 secs 3 times ... the user should enter a number before the timer expires...
here is the code
Code:
/* This program checks if the user has "5" as input before the countdown is over or not*/
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
int main()
{
int x,i=0,pid,pid2;
system("clear");
for(x=0;x<3;x++)
{
pid=-1;pid2=-1;
if((pid=fork()) == 0) //child process- the countdown timer
{
pid=getpid();
for(i=5;i>0;i--) //start a 5 sec countdown
{
printf("X=%d\tenter number(ppid=%d,pid=%d)",x,getppid(),getpid());
printf("\t\t\t\t\t\t\t%d\a\n",i);
sleep(1);
}
exit(666+x); //exit when 5 secs are over
}
else //parent process
{
if((pid2=fork()) == 0) //create a seperate child process for input
{
pid2=getpid();
printf("\n\nscanf pid2=%d\n\n",pid2);
scanf("%d",&i);
kill(pid,SIGKILL); //when input is recieved kill the timer process
if(i==5) //check the user input
{
printf("\nYES i=5(pid=%d) for x=%d\n\n",getpid(),x);
}
else
{
printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);
}
exit(777+i);
}
wait(); //wait for child process...timer process.
sleep(3); //take a deep breath
printf("\n\npid2=%d(i must execute only after wait() is over)\n\n",pid2);
if((kill(pid2,SIGKILL))==0) //after the timer child process finishes ,if input process is still running...kill it
{
printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);//default msg
}
}
}
printf("THE END(pid=%d\n",getpid()); //this should be executed when all other child processes are over.
return 0;
}
but i get a lot of unexpected behaviour...
this output is one example
Code:
#i wont be entering any input whatsoever...
X=0 enter number(ppid=24800,pid=24802) 5
scanf pid2=24803
X=0 enter number(ppid=24800,pid=24802) 4
X=0 enter number(ppid=24800,pid=24802) 3
X=0 enter number(ppid=24800,pid=24802) 2
X=0 enter number(ppid=24800,pid=24802) 1
pid2=24803(i must execute only after wait() is over)
NO i!=5(pid=24800) for x=0 #its ok till here...it waited till timer exited then executed the rest,killing scanf process.
X=1 enter number(ppid=24800,pid=24812) #new timer process 5
scanf pid2=24813 #new child scanf process
X=1 enter number(ppid=24800,pid=24812) 4
X=1 enter number(ppid=24800,pid=24812) 3
pid2=24813(i must execute only after wait() is over) #why didnt it wait till timer process exited?
NO i!=5(pid=24800) for x=1 #this killed my scanf before the timer expired.
X=1 enter number(ppid=24800,pid=24812) 2
X=2 enter number(ppid=24800,pid=24817) 5
scanf pid2=24818 # x=2 has started before x=1 even finished
X=1 enter number(ppid=24800,pid=24812) 1
#the sleep(3) statement never executed again
X=2 enter number(ppid=24800,pid=24817) 4
X=2 enter number(ppid=24800,pid=24817) 3
X=2 enter number(ppid=24800,pid=24817) 2
pid2=24818(i must execute only after wait() is over)
NO i!=5(pid=24800) for x=2
THE END(pid=24800 #the parent exits , leaving the timer process an orphan
[c_d@localhost C scratchpad]$ X=2 enter number(ppid=1,pid=24817) 1
the unexpected behaviour is highlighed with red...and commentaries are written by side of output in blue...
please comment.
__________________
c_d -- superfluously plenteous yet indolently otiose
Last edited by creeping death; 30th March 2009 at 01:38 PM.
|

30th March 2009, 02:19 PM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
well,
i just changed from wait to waitpid() and there has been a lot of improvement.
Code:
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
int main()
{
int x,i=0,pid,pid2,status,r;
system("clear");
for(x=0;x<3;x++)
{
pid=-1;pid2=-1;
if((pid=fork()) == 0) //child process- the countdown timer
{
pid=getpid();
for(i=5;i>0;i--) //start a 5 sec countdown
{
printf("X=%d\tenter number(ppid=%d,pid=%d)",x,getppid(),getpid());
printf("\t\t\t\t\t\t\t%d\a\n",i);
sleep(1);
}
exit(111+x); //exit when 5 secs are over
}
else //parent process
{
if((pid2=fork()) == 0) //create a seperate child process for input
{
pid2=getpid();
//printf("\n\nscanf pid2=%d\n\n",pid2);
scanf("%d",&i);
kill(pid,SIGKILL); //when input is recieved kill the timer process
if(i==5) //check the user input
{
printf("\nYES i=5(pid=%d) for x=%d\n\n",getpid(),x);
}
else
{
printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);
}
exit(0);
}
r=waitpid(pid,&status); //wait for child process...timer process.
sleep(3); //take a deep breath
printf("\n\npid=%d,pid2=%d(wait status=%d,r=%d)\n\n",pid,pid2,status,r);
if((kill(pid2,SIGKILL))==0) //after the timer child process finishes ,if input process is still running...kill it
{
printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);//since the user did not enter anything within time.display this
}
}
}
printf("THE END(pid=%d\n",getpid()); //this should be executed when all other child processes are over.
return 0;
}
output:
Code:
X=0 enter number(ppid=7095,pid=7097) 5
X=0 enter number(ppid=7095,pid=7097) 4
X=0 enter number(ppid=7095,pid=7097) 3
X=0 enter number(ppid=7095,pid=7097) 2
X=0 enter number(ppid=7095,pid=7097) 1
pid=7097,pid2=7098(wait status=28416,r=7097)
NO i!=5(pid=7095) for x=0
X=1 enter number(ppid=7095,pid=7115) 5
X=1 enter number(ppid=7095,pid=7115) 4
X=1 enter number(ppid=7095,pid=7115) 3
X=1 enter number(ppid=7095,pid=7115) 2
X=1 enter number(ppid=7095,pid=7115) 1
pid=7115,pid2=7116(wait status=28672,r=7115)
NO i!=5(pid=7095) for x=1
X=2 enter number(ppid=7095,pid=7141) 5
X=2 enter number(ppid=7095,pid=7141) 4
X=2 enter number(ppid=7095,pid=7141) 3
X=2 enter number(ppid=7095,pid=7141) 2
pid=7141,pid2=7142(wait status=28672,r=0) #why is r=0 when pid=7141,in this case?
NO i!=5(pid=7095) for x=2
THE END(pid=7095
[c_d@localhost C scratchpad]$ X=2 enter number(ppid=1,pid=7141) 1 #orphaned yet again
[c_d@localhost C scratchpad]$
any ideas why the third time why return value of waitpid() was 0?
__________________
c_d -- superfluously plenteous yet indolently otiose
Last edited by creeping death; 30th March 2009 at 02:24 PM.
|

30th March 2009, 02:37 PM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
|
SUCCESS!
forgot to include <sys/wait.h>
__________________
c_d -- superfluously plenteous yet indolently otiose
|

31st March 2009, 10:45 AM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
final code
Code:
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include <sys/wait.h>
#define CL system
#define C "clear"
int main()
{
int x,i=0,pid,pid2,status;
FILE *temp,*rf; //temp will contain the marks,rf will contain if user gave an input or not
temp=fopen("temp","w");
fputc(0,temp); //set marks to 0
fputc(0,temp);
fclose(temp);
CL(C); //CL(C)=clear screen(see #define)
for(x=0;x<3;x++)
{
CL(C);
pid=-1;pid2=-1;
if((pid=fork()) == 0) //child process- the countdown timer
{
for(i=5;i>0;i--) //start a 5 sec countdown
{
CL(C);
printf("X=%d\tenter a number(ppid=%d,pid=%d)",x,getppid(),getpid());
printf("\t\t\t\t\t\t\t%d\a\n",i);
sleep(1);
}
exit(0); //exit when 5 secs are over
}
else //parent process
{
if((pid2=fork()) == 0) //create a seperate child process for input
{
int noattempts,nocorrect,rval;
rf=fopen("rval","w"); //set value in rval file to -1
fclose(rf);
rval=scanf("%d",&i);
rf=fopen("rval","w");
fputc(rval,rf); //if scanf worked correctly then value in rval file will be 1
fclose(rf);
kill(pid,SIGKILL); //when input is recieved kill the timer process
temp=fopen("temp","r");
noattempts=fgetc(temp);
nocorrect=fgetc(temp);
fclose(temp);
if(i==5) //check the user input
{
printf("\nYES i=5(pid=%d) for x=%d\n\n",getpid(),x);
noattempts++;
nocorrect++;
}
else
{
printf("\nNO i!=5(pid=%d) for x=%d\n\n",getpid(),x);
noattempts++;
}
temp=fopen("temp","w");
fputc(noattempts,temp); //update marks
fputc(nocorrect,temp);
fclose(temp);
exit(0); //exit the scanf process.no need to kill this if user entered input appropriately
}
waitpid(pid,&status,0); //wait for child process...timer process.
rf=fopen("rval","r");
if(fgetc(rf)!=1) //check if user entered input appropriately
{
printf("\nAppropriate input not specified\n");
kill(pid2,SIGKILL);
}
fclose(rf);
}
printf("\n\nNext question...");
fflush(stdout);
sleep(3); //take a deep breath
}
CL(C);
temp=fopen("temp","r");
printf("THE END(pid=%d)\nNo of Correct=%d\nNo of Attempts=%d\n",getpid(),fgetc(temp),fgetc(temp)); //this should be executed when all other child processes are over.
fclose(temp);
remove("temp"); //cleanup
remove("rval");
return 0;
}
it works as i want it to , but here i m using files, to "pass" values from one process to another.
i m sure there are much more efficient ways...what other alternative do i have?
__________________
c_d -- superfluously plenteous yet indolently otiose
|

1st April 2009, 04:52 AM
|
 |
Banned (for/from) behaving just like everybody else!
|
|
Join Date: Jul 2007
Location: Beijing, China
Posts: 1,307

|
|
Quote:
Originally Posted by creeping death
it works as i want it to , but here i m using files, to "pass" values from one process to another.
i m sure there are much more efficient ways...what other alternative do i have?
|
Using a file to pass messages is not that bad an idea, but you don't have to use an actual on-disk file, just a pipe is enough.
There are a vast number of inter-process communication methods, such as signals, shared memory objects, and pipe/sockets.
For smaller programs you can also run the program in one process with several threads. I wrote something similar using POSIX threads. The program is too long (~100 lines) to post here, please look at the pastbin: http://aleph.pastebin.com/f60796f12
The comments in the code contains my opinions about the code.
__________________
I believe in nerditarianism. I read FedoraForum for the Fedora-related posts.
|

1st April 2009, 07:14 AM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
thanks man...its really cool for you...
i dont know what you are saying...
you can pass variables from one process to another using signals?
Quote:
|
...I wrote something similar using POSIX threads....
|
i m new to process/threads/signals stuff...so...is there a specific way to compile this?
because i get errors.
Code:
[c_d@localhost c scratchpad]$ gcc temp2.c
/tmp/ccoV9PqL.o: In function `main':
temp2.c:(.text+0x16d): undefined reference to `pthread_create'
temp2.c:(.text+0x190): undefined reference to `pthread_create'
temp2.c:(.text+0x1a3): undefined reference to `pthread_join'
temp2.c:(.text+0x1b6): undefined reference to `pthread_join'
collect2: ld returned 1 exit status
can you recommend a good book to guide me through all this...processes/threads/signals etc...good and small
have you thought of the stdin question on the other thread?
__________________
c_d -- superfluously plenteous yet indolently otiose
Last edited by creeping death; 1st April 2009 at 07:25 AM.
|

1st April 2009, 08:05 AM
|
 |
Banned (for/from) behaving just like everybody else!
|
|
Join Date: Jul 2007
Location: Beijing, China
Posts: 1,307

|
|
1. (pipes) I mean, you don't have to use an on-disk file. Just connect the input and output of both processes. Look at the man page of pipe(2) and you'll see a fine example doing IPC via a pipe.
2. (signals) I talked about signals... of course singnals alone can't carry much information, but what if you don't have that much information to send... sometimes "hey, wake up!" is enough.
3. (threads) to compile the program, use the command
Code:
gcc -pthread whatever.c
There's also more information in the code comments.
4. (books) I'm teaching myself half-baked system programming. Don't take my words seriously. Get a real course.
5. (that stdin issue) no..
Hope that helps.
__________________
I believe in nerditarianism. I read FedoraForum for the Fedora-related posts.
|

1st April 2009, 07:28 PM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
Quote:
Originally Posted by aleph
1. (pipes) I mean, you don't have to use an on-disk file. Just connect the input and output of both processes. Look at the man page of pipe(2) and you'll see a fine example doing IPC via a pipe.
|
thanks for the tip. just saw that, it can only recognise byte stream...but what if i wished to send "222456.8973" (float) value from one process to another? the only way that i see is to convert the float to a sting , find the length ,and then write(with size_t count(3rd argument)=string length+1);
any other ideas?
Quote:
|
2. (signals) I talked about signals... of course singnals alone can't carry much information, but what if you don't have that much information to send... sometimes "hey, wake up!" is enough.
|
ok...thats what i did in my program...parent said to child "die kid!!".
Quote:
3. (threads) to compile the program, use the command
Code:
gcc -pthread whatever.c
There's also more information in the code comments.
|
my bad...btw i did not understand somethings...but i wont bother you until i read about thread myself first...hopefully i'll understand it fully when i read about it.
Quote:
4. (books) I'm teaching myself half-baked system programming. Don't take my words seriously. Get a real course.
5. (that stdin issue) no..
Hope that helps.
|
alright, but how is unix for programmer and users glass and ables?
__________________
c_d -- superfluously plenteous yet indolently otiose
|

2nd April 2009, 04:33 AM
|
 |
Registered User
|
|
Join Date: Apr 2006
Location: Ohio, USA
Posts: 8,303

|
|
Quote:
Originally Posted by creeping death
thanks for the tip. just saw that, it can only recognise byte stream...but what if i wished to send "222456.8973" (float) value from one process to another? the only way that i see is to convert the float to a sting , find the length ,and then write(with size_t count(3rd argument)=string length+1);
any other ideas?
|
No - you misunderstand. It means the pipe is just a stream of bytes w/o and higher level structure. You can send floats or binary stuff just fine.
float myfloat = 3.14159265;
write(fd, &myfloat, sizeof(float));
or
struct foobar someAwefulStruct = { .... }
write(fd, &someAwefulStruct, sizeof(struct foobar));
The interprocess communication methods include pipes, unix local sockets(AF_UNIX or AF_LOCAL), shared memory, messages, semaphores, signals. Also you can create external devices (pseudo-ttys and fifos for example). It's a very rich set.
Interprocess communication is a complex topic unless the communication is rather trivial - like pipes.
|

2nd April 2009, 05:16 AM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
Quote:
Originally Posted by stevea
No - you misunderstand. It means the pipe is just a stream of bytes w/o and higher level structure. You can send floats or binary stuff just fine.
float myfloat = 3.14159265;
write(fd, &myfloat, sizeof(float));
or
struct foobar someAwefulStruct = { .... }
write(fd, &someAwefulStruct, sizeof(struct foobar));
The interprocess communication methods include pipes, unix local sockets(AF_UNIX or AF_LOCAL), shared memory, messages, semaphores, signals. Also you can create external devices (pseudo-ttys and fifos for example). It's a very rich set.
Interprocess communication is a complex topic unless the communication is rather trivial - like pipes.
|
i had tried this before before posting.
Code:
#include<stdio.h>
#include<unistd.h>
int main()
{
float f;
printf("normal way\n");
scanf("%f",&f);
printf("%f",f);
fflush(stdout);
printf("\nSystem call\n");
read(STDIN_FILENO,&f,sizeof(float));
perror("read");
write(STDOUT_FILENO,&f,sizeof(float));
perror("write");
return 0;
}
OP:
Code:
[c_d@localhost c scratchpad]$ gcc temp4.c
[c_d@localhost c scratchpad]$ ./a.out
normal way
88888.8765
88888.875000
System call
88888.8765
read: Success
8888write: Success
[c_d@localhost c scratchpad]$ 8.8765
bash: 8.8765: command not found
[c_d@localhost c scratchpad]$
i had also seen sockets(2) and there were a list of domains given at socket.h...and i confused with what to use...thanks for mentioning AF_UNIX/AF_LOCAL.
__________________
c_d -- superfluously plenteous yet indolently otiose
Last edited by creeping death; 2nd April 2009 at 07:02 AM.
|

2nd April 2009, 11:12 AM
|
 |
Banned (for/from) behaving just like everybody else!
|
|
Join Date: Jul 2007
Location: Beijing, China
Posts: 1,307

|
|
|
Are you TYPING a float point number to be read(2) from stdin? You are typing a series of chars which made up a textual representation of a float, not a float itself.
__________________
I believe in nerditarianism. I read FedoraForum for the Fedora-related posts.
|

2nd April 2009, 12:20 PM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
ok
see this now...
the float variable is declared as well as initialised
Code:
[c_d@localhost c scratchpad]$ cat temp4.c
#include<stdio.h>
#include<unistd.h>
int main()
{
float f=88888.8789;
fflush(stdout);
write(STDOUT_FILENO,&f,sizeof(float));
perror("\nwrite");
return 0;
}
[c_d@localhost c scratchpad]$ gcc temp4.c
[c_d@localhost c scratchpad]$ ./a.out
p��G
write: Success
[c_d@localhost c scratchpad]$
....well?
__________________
c_d -- superfluously plenteous yet indolently otiose
|

2nd April 2009, 04:27 PM
|
 |
Banned (for/from) behaving just like everybody else!
|
|
Join Date: Jul 2007
Location: Beijing, China
Posts: 1,307

|
|
Quote:
Originally Posted by creeping death
....well?
|
That's right. You just dumped a 32-bit float to the terminal, which is shown as gibberish (of course).
Just write another program that reads from stdin, decode the float and printf(2) it. Pipe the raw float to this program and you'll see how it's possible to do what you intended to do.
__________________
I believe in nerditarianism. I read FedoraForum for the Fedora-related posts.
|

2nd April 2009, 04:56 PM
|
 |
Registered User
|
|
Join Date: Feb 2008
Posts: 655

|
|
Quote:
Originally Posted by aleph
That's right. You just dumped a 32-bit float to the terminal, which is shown as gibberish (of course).
Just write another program that reads from stdin, decode the float and printf(2) it. Pipe the raw float to this program and you'll see how it's possible to do what you intended to do.
|
of course? why do you say "of course"???? please explain...
so, write() just dumps bytes onto the terminal, printf() formats them appropriately first and then dumps them to terminal. is that right?
__________________
c_d -- superfluously plenteous yet indolently otiose
|

2nd April 2009, 04:59 PM
|
 |
Banned (for/from) behaving just like everybody else!
|
|
Join Date: Jul 2007
Location: Beijing, China
Posts: 1,307

|
|
Quote:
Originally Posted by creeping death
so, write() just dumps bytes onto the terminal, printf() formats them appropriately first and then dumps them to terminal. is that right?
|
Of course
__________________
I believe in nerditarianism. I read FedoraForum for the Fedora-related posts.
|
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
Current GMT-time: 00:27 (Sunday, 26-05-2013)
|
|
 |
 |
 |
 |
|
|